Entry Point
frontend/src/main.tsx mounts <App />, loads global styles, and registers the Theme context.
frontend/vite.config.ts).Entry Point
frontend/src/main.tsx mounts <App />, loads global styles, and registers the Theme context.
Layout
features/app/components/AppLayout.tsx wraps the workspace, routing, and announcement banner.
Routing
App.tsx renders authenticated vs unauthenticated routes; React Router handles page shells.
// Login success -> SecureAPI.setToken(token)// 1. Fetch salt -> /api/v1/auth/login// 2. cryptoService.deriveKeyFromPassword(password, salt)// 3. Master key decrypted and cached in cryptoService.masterKey// 4. Note payloads encrypted via cryptoService.encryptDataSecureAPI (services/secureApi.ts)├── Adds JWT + CSRF headers├── Handles 401 -> logout└── Wraps fetch with logging
CryptoService (services/cryptoService.ts)├── Lazy-loads libsodium├── Derives PBKDF2 keys (600k iterations)└── Performs XChaCha20-Poly1305 encrypt/decryptWorkspace Shell
features/app/components/NotesWorkspace.tsx arranges the note list, editor, and responsive mobile toggles. State derives from stores/authStore.ts and stores/shareLinksStore.ts.
Editors
components/RichTextEditor.tsx wraps Lexical with Markdown + attachment support. features/app/components/TemplateSelectorModal.tsx lazy-loads templates to keep initial bundle small.
Collaboration
features/common/collaboration hooks maintain WebSocket connections via websocketService. Incoming payloads trigger optimistic UI updates in collaborationStore.ts.
Authentication UI
features/auth screens coordinate MFA prompts, backup code entry, and password resets through SecureAPI.
stores/authStore.ts: tracks JWT token state, current user metadata, and theme preference persisted in localStorage.stores/collaborationStore.ts: manages active collaborators per note, dispatched by WebSocket events.stores/shareLinksStore.ts: caches share-link metadata to avoid redundant API calls when toggling visibility.stores/templatesStore.ts (within templates feature): keeps decrypted templates after first load.All stores enforce decrypted data stays in memory; only identifiers or encrypted payloads persist to storage.
SecureAPI service methods (e.g., services/templatesService.ts) that return typed responses validated by Zod schemas under lib/schemas.SecureAPI.handleUnauthorized() clears keys, tokens, and salts, then redirects to /login.attachmentService.ts, which includes the decrypted note ID and uses FormData to avoid JSON encoding large payloads.const api = new SecureAPI(cryptoService, '/api/v1')const templates = await templatesService.listTemplates(api)// templates arrive encrypted -> decrypt client-side before rendering*.test.tsx) render against mocked Zustand stores for deterministic behavior.CryptoService.test.js uses the real libsodium WASM bundle to guarantee encryption compatibility.e2e.test.tsx exercises the full login + note flow with MSW mocks for backend endpoints.