# System Patterns: Web Application ## Architecture Overview The application follows a domain-driven, Effector-based Flux architecture. ### Domain Structure Each feature domain in `src/domains//` contains: - `model.ts`: Effector events, stores, and effects (pure, testable) - `view-model.ts`: React hooks (`useStore`/`useUnit`) adapting model logic to components - `ui/`: Dumb presentational React components The application entry point (``) and routing are in `src/app/root.tsx` and `src/app/routes.tsx`. ## Key Design Patterns ### Effector-based Flux - **Events**: `createEvent()` represent actions triggered by the user or effects - **Stores**: `createStore()` hold application state and update via `.on(event, ...)` - **Effects**: `createEffect()` handle async side-effects, dispatching success/fail events - **Domains**: Group related events, stores, and effects into isolated modules ### ViewModel Layer - Encapsulates Effector usage in thin hooks (`view-model.ts`) - Components consume view-model hooks and remain focused on presentation ### UI Components - Design-system atoms in `src/shared/ui/` - Domain-specific components in `src/domains//ui/` - Core UI components include: Button, Input, Textarea, Switch, Tabs, ImageUpload, Card, Dialog ## Data Flow ``` event ───┐ │ triggers store ───┤ updates ──> view-model hook ──> React component render │ effect <─┘ (async; dispatches done/fail events) ``` User interactions invoke events, stores update state, view-model hooks propagate changes to the UI. ## Authentication - OpenID Connect (OIDC) for authentication via dynamic `/oidc.json` configuration - `AuthProvider` initializes auth flow; tokens stored in `localStorage` with auto-refresh - Protected routes using the `ProtectedRoute` component with optional `requiredRoles` ## Deployment - Path-agnostic SPA deployment with Vite and Docker - `BASE_PATH` injected into `public/config.js` at container startup by `docker-entrypoint.sh` - Client-side environment variables (`CLIENT_*`) surfaced on `window.appConfig` - Asset paths managed via `getAssetPath()` in `src/utils/config.ts` ## Styling - Tailwind CSS configured via `tailwind.config.js` - Utility-first styling with dark theme support and a consistent design system