Application Architecture
Relevant source files
The following files were used as context for generating this wiki page:
The RoundingWell frontend application is built on a modular, event-driven architecture utilizing Backbone.js, Marionette.js, and Marionette.Toolkit. The system is organized into a tree of asynchronous "Apps" that manage business logic, data fetching, and view orchestration. This structure promotes encapsulation, where discrete units of functionality are managed by dedicated controllers that interact via a centralized messaging bus provided by Backbone.Radio.
The architecture emphasizes a clean separation of concerns: Apps handle state and data coordination, Views manage the DOM and user interactions, and Entities serve as the exclusive layer for AJAX communication and data modeling.
Sources: README.md:120-135, src/js/apps/README.md:3-8, AGENTS.md:16-24
Core Component Hierarchy
The application structure is defined by three primary class types derived from Marionette and Marionette.Toolkit.
Toolkit Apps
Apps represent the business logic layer. They are responsible for creating layouts within their assigned regions, requesting data from services, and passing that data to views or child apps. By default, Apps in this project are asynchronous, allowing them to wait for data requirements before completing their start lifecycle.
The diagram shows the relationship between a Toolkit App, its internal state, and how it orchestrates the UI through regions and child views.
Sources: README.md:120-128, src/js/apps/README.md:3-6
Components
Components are configurable, encapsulated widgets (e.g., datepickers) that control a specific region and view combined with a state model. They provide a consistent API for interaction and are intended to be used as-is rather than extended.
Sources: README.md:143-148
Views
Views are Marionette-based and follow a strict convention where DOM mutations are scoped exclusively to the view's own template. Developers are encouraged to use the ui hash for element selection and triggers for event delegation.
Sources: README.md:213-220, src/js/views/README.md:3-6
Data Management and Services
Data integrity and synchronization are maintained through specialized libraries and service patterns.
| Library/Pattern | Purpose | Implementation Detail |
|---|---|---|
| Backbone.Store | Identity Map | Ensures only a single instance of a model exists in memory for a given ID. |
| Entities Service | Data Access | The exclusive layer allowed to perform AJAX/API requests. |
| State Models | Local State | Preferred over instance properties for storing UI and application state. |
| Backbone.Radio | Communication | Messaging bus for decoupling components via pub/sub patterns. |
Sources: README.md:150-165, README.md:221, src/js/README.md:79-81, AGENTS.md:32-34
Data Flow Sequence
The following sequence demonstrates how a typical App initializes data and renders the interface.
This diagram illustrates the asynchronous start lifecycle where data is requested via Radio before views are initialized.
Sources: README.md:128-140, src/js/README.md:38-40
Implementation Standards
Import Architecture
The project uses Vite with specific import aliases (e.g., js/* maps to src/js/*). A strict import order is enforced to maintain dependency clarity.
- Polyfills and third-party libraries (Underscore, Marionette)
- Global SCSS modules
- Shared utilities and base classes
- Entities and service modules
- Apps and controllers
- Views and components
- Templates and local styles
Sources: src/js/README.md:3-36, AGENTS.md:43-52
Templating and Security
Handlebars is the primary templating engine. Templates are either stored in .hbs files or defined inline using handlebars-inline-precompile.
- XSS Prevention: All data from the API is treated as hostile. Double braces
{{ }}escape by default; triple braces{{{ }}}are reserved for trusted HTML and require explicit_.escape()if data originates from the API. - Logic: Template logic is kept minimal, favoring small, broken-down chunks over complex if/else blocks.
Sources: src/js/views/README.md:9-19, src/js/views/README.md:42-45
Styling (Sass)
The application uses the BEM (Block, Element, Modifier) naming convention.
- Organization: Styles are split into
core/(global),modules/(generic components), anddomain/(business-specific). - View-specific Styles: Scss files located within
src/js/views/are imported directly by the JS modules that render them, building a dependency tree that Vite processes.
Sources: src/scss/README.md:22-35, src/scss/README.md:65-90, AGENTS.md:35-37
Internationalization (i18n)
Localization is handled via handlebars-intl and a YAML-based key system.
- Key Strategy:
view.directory.fileViews.viewName.stringContextName. - Formatting: Uses
formatjsfor messages and pluralization, whiledayjsis used for date/time formatting.
Sources: src/js/i18n/README.md:6-18, src/js/i18n/README.md:66-68
Summary
The Application Architecture of the RoundingWell frontend is designed for high maintainability and scalability. By utilizing Marionette.Toolkit's App tree and enforcing strict data-access boundaries through the Entities Service, the project ensures that business logic remains decoupled from the UI layer. The integration of Backbone.Store and Backbone.Radio further strengthens this by providing a unified state management and communication infrastructure.
Sources: README.md:120-135, README.md:213-225, AGENTS.md:16-24