Handbook
Search for the articles here or browse the categories below.
Browse by topic
Find guides, tutorials, and answers organised by category.
Company
Articles about the company
Browse
Culture
Articles about culture
Browse
Design
Articles about Design
Browse
Engineering
Articles on engineering practices at Chatwoot.
Browse
Enterprise Edition
Articles about Enterprise Edition
Browse
Marketing
Articles about marketing practices at Chatwoot.
Browse
Processes
The details of the process we follow in Chatwoot.
Browse
Popular articles
What other people are reading right now.
How do push notifications work in Chatwoot?
Chatwoot offers two services for sending push notifications: 1. The first service sends push notifications through a relay server. 2. The second service sends push notifications directly through the Chatwoot server. The flow of push notifications is determined by the environment variable and installation configuration details. ENABLE_PUSH_RELAY_SERVER Navigate to <installation_url>/super_admin/app_config. Check if you have added the Firebase Project ID and Firebase Credentials. - If both Firebase Project ID and Firebase Credentials have been added, push notifications will be sent to your custom-built mobile apps. - If neither Firebase Project ID nor Firebase Credentials have been added, and ENABLE_PUSH_RELAY_SERVER is true, push notifications will be sent to official mobile apps. - If neither Firebase Project ID nor Firebase Credentials have been added, and ENABLE_PUSH_RELAY_SERVER is false, push notifications will not be sent to any device. To enable push notifications on a custom branded app, you must configure Firebase. Detailed instructions can be found here. In summary, you need to either use custom builds for both Android and iOS apps or use the official apps for both platforms.
π©βπ» EngineeringSwagger Documentation
Chatwoot maintains its API documentation using swagger. Therefore, whenever you commit an API change to Chatwoot, The associated swagger Documentation needs to be updated. This guide will walk you through adding documentation for a new endpoint in Chatwoot's swagger.json. The guide uses Canned Responses as the example object for documentation. Prerequisities You can access swagger documentation for the Chatwoot app in your local installation over: http://localhost:3000/swagger The commands to update your swagger.json is as follows. rake swagger:build If you are familiar with the process, need a sample reference, head over to the example Pull Request Steps to add a new endpoint 1. Define Tag in swagger index Define the Tag for the object to be added in swagger/index.yml. Since we want this endpoint under Application APIs, it is added under the name Application. see the changes in reference commit 2. Add the resource definition Add the resource definition and its attributes to a definition file. You should place the resource definition file in the root or a sub folder of swagger/definitions/resource. Don't forget to add the resource definition path to index in swagger/definitions/index.yml In our case for the Canned Response, we are placing it in swagger/definitions/resource/canned_response.yml see the changes in reference commit 3. Define request payloads The next step is to define the request payloads. You can split methods like create, update etc. into single or multiple files based on your requirement. Also, make sure to add the paths to the index. Ensure to add the response payload definition path to index in swagger/definitions/index.yml In our case of Canned Response, since the payload is the same for both create and update, we are adding it in swagger/definitions/request/canned_response/create_update_payload.yml see the changes in reference commit 4. Define request paths Define the required paths for the endpoint to swagger/paths/index.yml. Create appropriate files for each route. In the path definitions, you can reference the request objects defined in step 2 and params from step 3. For Canned Response, we are defining the following path files. swagger/paths/application/canned_responses/create.yml swagger/paths/application/canned_responses/delete.yml swagger/paths/application/canned_responses/index.yml swagger/paths/application/canned_responses/update.yml see the changes in reference commit 5. Build and verify Run rake swagger:build and verify the updated documentation at http://localhost:3000/swagger. If there are build errors, you will see them while loading the documentation in the browser. Fix the issues and re-run build until the documentation is ready. Then, raise a PR with the changes. Ensure to commit the newly generated /swagger/swagger.json. see the changes in reference commit Updating Chatwoot API docs page If you are a community contributor, The PR reviewer will take care of this step. Updating the swagger documentation on https://www.chatwoot.com/developers/api/ requires a commit on the chatwoot-website repo. You should copy the contents of newly generated swagger.json and update the following files in the chatwoot-website repo src/data/swagger/swagger-develop.json src/data/swagger/swagger.json see the changes in reference pull request
πΈ Enterprise EditionDeveloping Enterprise Edition Features
Chatwoot ships two versions of its software, a Community Edition and an Enterprise Edition. This guide focuses on the engineering best practices while developing features for the Enterprise edition. The guidelines followed in Chatwoot's Enterprise edition development are heavily inspired by the model adopted by Gitlab, and hence their guide is an excellent reference to learn more. Testing Community Edition Chatwoot team should be developing features over the Enterprise Edition in their local development environments by default. You can test how the community edition will behave by toggling the environment variable DISABLE_ENTERPRISE to true and restarting Chatwoot Server. Organization of Code The JavaScript part of Chatwoot code is completely MIT, while enterprise separation is applied over the ruby code concerning the backend Chatwoot APIs and Services. Always place Enterprise edition proprietary code under the top-level enterprise directory. In addition, the modules should follow the structure as close to their Community Edition counterparts (See the specifics in sub Sections). The enterprise edition specs should reside in the spec/enterprise folder. How to develop features For Community Edition features, you can follow the general best practices for Ruby on Rails and Vue.js Development. But when you identify an exclusive feature or Enterprise edition extension, you must follow the appropriate guidelines mentioned below. General Guidelines JavaScript The JavaScript part of Chatwoot code is available under MIT. But you might want to limit the visibility of specific components based on the edition of Chatwoot Version. In such cases, you can rely on the helper method isEnterprise() available in app/javascript/shared/mixins/configMixin.js. Then, include the mixin in your Component and implement a conditional check to render the sub-component appropriately. Helpers in ruby Code While working in the ruby code, ChatwootApp.enterprise? helper is available for you to determine whether the user is running the Enterprise Edition of the software. Data Models & Data Migrations Users could be migrating between versions. So we always have to ensure that all the migrations are run for both the edition. The database schema needs to remain the same for both editions. In the Case of DataMigrations, you can have blank implementations for these migrations by conditionally excluding Enterprise specific DataModels with ChatwootApp.enterprise? Routes If you want to limit the access of a specific route to Enterprise Edition alone, use the ChatwootApp.enterprise? helper. if ChatwootApp.enterprise? get '/enterprise', to: 'dashboard#enterprise' else Developing features as an extension of Community Edition When developing Enterprise features built over the Community Edition software, Implement a base functionality in Community edition code and extend it over in an Enterprise licensed module. As shown in the example, we write a module in the Enterprise namespace and inject it into the community edition class. # app/models/inbox.rb class Inbox < ApplicationRecord # placeholder method which will be overriden in Enterprise edition def member_ids_with_assignment_capacity members.ids end end Inbox.prepend_mod_with('Inbox') # enterprise/app/models/enterprise/inbox.rb module Enterprise::Inbox def member_ids_with_assignment_capacity super - get_agent_ids_over_assignment_limit end private def get_agent_ids_over_assignment_limit # implement proprietry enterprise logic end end You can use the helper methods like prepend_mod_with, extend_mod_with, or include_mod_with, depending on how you want to include the enterprise method into the chain. Refer InjectEnterpriseEditionModule to learn more. Ensure that the module written to extend the Community Logic is put under the Enterprise namespace. # notice the extra namespacing with in models directory # enterprise/app/models/enterprise/inbox.rb # other examples # enterprise/app/controllers/enterprise/paid_feature_controller.rb # enterprise/app/builders/enterprise/paid_builder.rb Developing features exclusive in the Enterprise Edition If the feature is not present in Community Edition, we must directly put the code into the enterprise directory without the enterprise namespace. This works because we have the enterprise directory in autoload paths. # no need for extra enterprise namespacing since we aren't prepending # enterprise/app/controllers/paid_feature_controller.rb # enterprise/app/models/paid_feature.rb CI Pipeline for Community Edition We run a Community Edition pipeline over all the pull requests raised against Chatwoot to ensure that the updates don't break existing features in the CE edition. This pipeline ensures stability by stripping off the enterprise folder from the codebase and running the full suite of tests against Chatwoot. Troubleshooting My module does not prepend/initialize This could be a problem with the directory; if you notice the directory structure, we have and enterprise folder inside models as well. If you're adding anything to models/enterprise or lib/enterprise. Suppose you're adding a new namespace called extras; ensure an enterprise folder is inside it. Constants declared are not accessible when prepending This happens because prepend does not allow accessing the values across ancestors, you can access those using self.class::CONSTANT_NAME
π©βπ» EngineeringFrontend Guidelines
This guide explains the best practices, patterns used in frontend development. Events vs. props for methods in Vue Components Prefer events instead of passing a function down to the component. This helps you to write @methods on the component. Read the official doc on listening to child components here. // Bad <template> <child-component :on-close="handleClose" /> </template> // Good <template> <child-component @close="handleClose" /> </template> Usage of computed properties While having logic or conditions inside the Vue template, prefer writing a computed property than a complex logic. // Bad <template> <child-component :is-available="a > b && c - d === 2" /> </template> // Good <template> <child-component @close="handleClose" /> </template> <script> export default { computed() { isAvailable() { return this.a > this.b && (this.c - this.d) === 2 } } } </script> Use CSS Variables instead of SCSS variables We have CSS variables defined for spacing, font size, colors, etc., instead of importing SCSS variables in the dashboard. We are promoting the Usage of CSS variables as it helps us to customize the dashboard during runtime. Follow semantics while writing HTML Avoid using block dom nodes like div, section, etc to wrap text inside HTML. Read more about HTML semantics here Note on accessibility - Use alt tags for all images you have added to the code. - Use an anchor tag to place links to other pages, do not use it to create a link button. Read about accessibility here CSS naming convention. Follow BEM guidelines for CSS naming. While planning DOM structuring to adapt the style needed for CSS, keep it simple and readable. If possible, use pseudo selectors as an alternative to dummy dom nodes just for use in CSS styling. More on this here Note: We have used OOCSS at places that need to be rewritten. The naming convention for vuex actions All the CRUD API actions should follow the same name as Rails APIs. See the following example. fetchAllHelpCenters => index fetchOneHelpCenter => show createHelpCenter => create updateHelpCenter => update deleteHelpCenter => delete This makes it easier to read and understand the methods. For e.g.: Instead of portals/fetchAllHelpCenters, this becomes portals/index. Avoid manipulating DOM directly In most cases, there is no need to manipulate the DOM directly. Use Vue methods and state to change the DOM elements. Vue is data-driven, and thus, its features are built around this concept and do not encourage manipulating the DOM βthe jQuery way.β If you want to access DOM directly, use this.$refs.
β MarketingBrand Guidelines
The brand color for Chatwoot is #1f93ff Square logo and long-form assets can be viewed in the Dropbox link below (Use SVG/PNG based on the requirement). Use a square or long-form logo for smaller screens/display types. Download Brand Assets: - PNG: https://www.dropbox.com/sh/yhn4ffmj4ksfc2k/AADa5XMe5FHX1pesq2kSYqJEa - SVG: https://www.dropbox.com/sh/q47125duam4h0b1/AACtWBE3a-j3uyntNu-8ZuZOa
π¨ DesignGuidelines
Design & Frontend Development Guidelines Principles - Usability: Design decisions and implementation should always favor delivering the solution that lets the end-user use Chatwoot most effectively, efficiently, and satisfactorily. - Standardization: The design and coding decisions we make at Chatwoot concur with industry standards and an established organization standard. This helps us with our public contributors, onboarding new team members, and helping existing teammates to progress in their careers. - Productivity: Our processes should focus on improving productivity for all the stakeholders. While designing, this means reduced decision fatigue and a defined set of constraints for the team members. The designs developed by the design team should be easily translatable to code. The end products we deliver should always be optimized to improve productivity - Iteration: Constant iteration over our decision frameworks and implementations to ensure that we concur with the stated principles and continue improving and growing as a team. Design Process At Chatwoot, we follow a 12-column grid layout for the designs. The design team will develop designs for each device category ( web/tablet/mobile) and pass them to the development team. Advantages - Sticking to the standard grid helps us to work under guidelines. - Established framework for the thought process. - Standardization across the organization for design decisions. - Easier onboarding for newer team members / public contributors. - Easier translation of the design to code. Coding Guidelines The development team will work with the design team to understand the motivation behind the choices, brainstorm edge cases, and start working on the implementation. Since the designs are based on the standard grid, translating the design to code should be relatively more straightforward using the front-end framework's helper classes. If the design is not implemented using helper classes, it should be done by defining utility classes. Otherwise, scope the related styles in the Vue components itself. Writing CSS CSS is awesome, but maintaining CSS is hard!!! We try to be judicious about writing custom CSS. It is hard to identify and remove dead CSS code. While writing custom CSS, one should work with the awareness of that responsibility. - At all times possible, move common styles to utility classes and avoid rewriting CSS utility classes that are already available. - Isolate component-specific CSS within the components. - When there are cases where you have to write specific CSS, discuss the possibility of converting them into utility classes. Complex Layouts There are cases when a complex layout based on the grid might not translate well with varied display sizes under a specific device category. We will work on reinforcements over the original grid-based design in such cases. - The design process starts with grid helper classes, over which reinforcements are applied based on the design review. - For a three-column layout with varying widths for specific break-points, use the SCSS mixin available. - We can rethink whether the layout should change further accordingly to the varying display sizes. Example: converting linear buttons into stacked ones when available size reduces. - Write additional reinforcement CSS like min-width after discussing with the team. - If the grid-based design works well for almost 95% of cases and the breakage is for minor edge cases, we will compromise it in favor of code maintainability. Final Review The development team will work with the design team for the final approval of the design. This process is when the completed work is comparable with the original design. The designer can suggest additional changes to the work if it doesnβt confer with the original design. The teams iterate over this process until the final go-ahead is received from the design team. Ownership At times the development team might find difficulties in implementing the designs proposed by the design team. This might include but is not limited to going against development best practices, making compromises in code quality, etc. In such cases, the development team can discuss the issues with the design team and try to convince them of the caveats. The ownership of this decision-making and the visual aspect of the application falls upon the design team. If the design team isnβt convinced of the caveats, the development team will have to compromise and develop an implementation plan outside the existing guidelines.