Frontend System Design
Runtime Building Blocks
The runtime is split into four layers:
- Bootstrap layer (
index.tsx) - Shell layer (
App.tsx) - State layer (
provider/*) - Feature layer (
pages/*+components/*)
This separation limits cross-cutting complexity.
Bootstrap Layer
The entrypoint does three critical tasks:
- initializes router and route tree
- configures API base URL (
OpenAPI.BASE = window.location.origin) - mounts app into DOM root
The API base is intentionally derived from browser origin so frontend and backend can be deployed behind one host/proxy without rebuilding the app per environment.
Shell Layer (App.tsx)
The shell owns global chrome:
- app bar
- sidebar
- page outlet
- footer
It also contains route-driven UI behavior. Example: on / the sidebar is force-opened via effect.
Provider Order and Why It Matters
Current runtime context stack (outer -> inner):
graph LR
Theme["ThemeProvider"] --> Layout["LayoutProvider"]
Layout --> I18n["I18nProvider"]
I18n --> Auth["AuthProvider"]
Auth --> User["UserProvider"]
User --> Project["ProjectProvider"]
Project --> Guide["GuideProvider"]
Guide --> Ai["AiProvider"]
Ai --> Shell["Shell UI (AppBar, Sidebar, Outlet, Footer)"]
Rationale:
ThemeProvider(SUID Material) is outermost so UI components share one theme configuration.LayoutProvideris early so shell controls (sidebar open/closed) are globally available to the shell and the guided tour.I18nProviderwraps UI and the tour so translated labels exist before a tour step is constructed or rendered.AuthProviderowns the action-based auth/session lifecycle and writes token/username into the OpenAPI runtime configuration.- Auth session publication follows a strict ordering invariant: OpenAPI credentials are written before auth state is published to reactive consumers.
UserProviderandProjectProviderconsume auth state to load domain data only for an active session.GuideProviderdepends on layout and i18n to navigate routes and target mounted, translated UI anchors reliably.AiProviderdepends on auth/user/project state to include current context (user, project, selected ticket) in chat requests.
Module Boundaries
These boundaries prevent logic duplication:
pages/*: route composition and screen-level feedbackcomponents/*: local interactions and renderingprovider/*: async orchestration, state mutations, server sync logicapi/*: generated transport and DTO types only
Source Code Structure
The runtime layers are reflected in the current source structure:
| Structure of frontend source code | |
|---|---|
1 2 3 4 5 6 7 8 | |
This structure is not only organizational. It encodes an ownership rule: view code reads provider state and invokes provider commands, while providers own API interaction and reconciliation logic.
Route Responsibility Map
/: project selection and import entry (Projects,Filedrop)/Sprint: ticket operation workspace (TicketFilters,Kanban,Backlog,TicketInfo)/Profile: current user data/About,/Privacy: static content
Why This Structure Scales
- New pages can reuse provider actions without reimplementing API flow.
- Global policies (auth checks, rollback behavior, relation sync) remain centralized.
- UI refactors stay local because state and transport contracts are decoupled.
Frameworks and Libraries
The system design described above is implemented using the following key frontend technologies:
- SolidJS: reactive UI framework and component model used throughout
src/*. - @solidjs/router: client-side routing used in
src/index.tsx. - Vite: build tool and dev server, including the local
/apiproxy. - SUID Material: component library used for UI composition in
src/components/*andsrc/pages/*.
The guided tour and localization stack are documented separately: - Guided Tour (Shepherd.js) - Internationalization (i18n) (i18next)