39948-vm/AGENTS.md
2026-07-03 16:11:24 +02:00

448 lines
32 KiB
Markdown

# AGENTS.md
This file provides guidance to CODEX when working with code in this repository.
**MAIN RULE:** DON'T MADE UP ANYTHING!!! IF YOU NOT SURE - DOUBLECHECK IT VIA PROJECT DOCUMENTATION, TOOL DOCUMENTATION, APPROPRIATE MCP, WEB SEARCH OR JUST ASK FOR ME TO CLARIFY.
## Project Overview
Tour Builder Platform - a web application for building and managing interactive virtual tours. Built with:
- **Frontend**: Next.js 15 with React 19, TypeScript, Redux Toolkit, Tailwind CSS
- **Backend**: Node.js/Express with Sequelize ORM
- **Database**: PostgreSQL
## System Requirements
### Required Software
- **Node.js** 24.x for backend runtime and TypeScript migration work
- **PostgreSQL** 14+
### FFmpeg
FFmpeg is bundled with the backend via `ffmpeg-static` and `ffprobe-static` npm packages. No manual installation is required.
**How it works:**
- Pre-compiled binaries are downloaded during `npm install`
- `fluent-ffmpeg` is configured to use bundled binaries in `backend/src/services/videoProcessing.js`
- Works across all platforms (Linux, macOS, Windows) and Docker environments
**Supported use case:**
- Reversed video generation for back navigation transitions
## Important Rules
- **Never change global app configs casually** - Do not modify `.env` or database configuration without verifying the target environment. These configs are shared across environments and incorrect changes can break production.
- **Centralize environment variables** - Do not read new app/runtime environment variables directly from services, routes, components, hooks, or feature modules. Backend app env vars must be added to `backend/src/utils/env-validation.ts`, typed in `backend/src/types/env.ts` / `backend/src/types/config.ts`, exposed through `backend/src/config.ts`, and consumed via `config`. Frontend public env vars must be centralized in `frontend/src/config.ts`. Direct `process.env` access is acceptable only in bootstrap/config entrypoints (`load-env`, logger bootstrap, DB/Umzug config, Next config), scripts, migrations, seeders, and tests.
- **Backend async handlers** must be wrapped with `wrapAsync` helper for error propagation.
- **Use Passport JWT** for protected routes: `passport.authenticate('jwt', { session: false })`. Secure routes must read the authenticated user through `getCurrentUser(req)` from `backend/src/utils/request-context.ts`; if absent, return `ForbiddenError`.
- **Access model** - Keep the current permission model: effective permissions are `app_role.permissions + user.custom_permissions`. `Administrator`, `Platform Owner`, and `Account Manager` are platform-wide internal roles. Other internal users currently have all-project scope by default unless a future explicit override system is implemented. `Public` users must not have admin API permissions and can only access public production pages plus explicitly granted private production presentations.
- **Public role hardening** - Do not grant RBAC permissions or custom permissions to `Public` users. Do not represent private production presentation grants as `READ_PROJECTS`, `READ_TOUR_PAGES`, or other admin permissions; use `production_presentation_access`.
- **Centralize access decisions** - New authorization logic must go through an `AccessPolicy`-style helper/service rather than ad hoc checks in routes/components. Keep admin API permissions separate from runtime presentation access.
## Mandatory Rules For New Code
These rules are required for new code and for touched code when practical.
### Backend Boundaries
- **Routes/controllers**: only authenticate, read runtime context, validate request input, call a service, and map the response. Do not put business logic in routes.
- **Services/domain**: own business logic, transactions, permission decisions, and orchestration.
- **DB API/repository**: only data access, filters, includes, pagination, and persistence mapping.
- **Policy**: all role/permission/runtime access decisions belong in policy/helper services, not scattered across routes.
- **Validation**: all new external `body`, `query`, and `params` inputs must be validated before service calls. `Joi` is already available in backend and should be preferred unless there is a clear reason to use another validator.
- **ID handling**: route params are canonical. For `PUT/PATCH/DELETE /:id`, use `req.params.id`; reject mismatched body ids.
- **Query safety**: new list/autocomplete endpoints must define max `limit`, default pagination, allowed sort fields, and allowed sort directions.
- **Service contracts**: new service/DB API methods should use object/options signatures, e.g. `Service.update({ id, data, currentUser, transaction, runtimeContext })` and `DBApi.findAll(filter, { currentUser, transaction, runtimeContext })`.
- **Logging**: use the project logger in runtime backend code (`services`, `routes`, `middlewares`, `db/api`, `utils`, app/bootstrap/config). Do not add new `console.*` calls outside migrations, seeders, scripts, or explicit debug-only CLI tooling.
### Backend Typing
- New backend pure helpers, validators, and policy modules should use TypeScript or JSDoc/checkJs-compatible types.
- Define shared shapes for `currentUser`, `runtimeContext`, service options, and validation results when touching related code.
- Do not add global `Express.Request` augmentation for project request fields. Use `backend/src/utils/request-context.ts` helpers for request-scoped `currentUser`, `runtimeContext`, logging, runtime-public flags, and permission overrides.
- Keep active backend source in strict TypeScript/ESM.
### Frontend State And API
- **Redux is for client/app state only**: auth/session UI, theme/style, layout/sidebar, constructor UI state, and app preferences.
- **TanStack Query is for server state**: API reads, entity lists/details, mutations, invalidation, and background refetch.
- Do not create new entity CRUD Redux slices or new Redux thunks for server reads/mutations.
- Centralize API access through query hooks or a shared API client. Avoid direct `axios` calls inside feature UI components unless there is a clear existing local pattern.
- New feature-specific code should live near the feature/domain it belongs to. Do not put feature logic into generic `components`, `hooks`, or `lib` folders when a feature-local module is clearer.
### Frontend TypeScript And React
- Do not add new `any` without a specific reason. Prefer existing domain types or add a narrow local type.
- Avoid new `eslint-disable`, `@ts-ignore`, and hook dependency suppressions. If unavoidable, add a short reason.
- New hooks must follow React hook rules and should be structured so `react-hooks/exhaustive-deps` can be enabled.
- Do not add new client usage of `jsonwebtoken`; use `jwt-decode` or `/auth/me` for client-side identity.
### Database And Migrations
- Do not add indexes speculatively. Add indexes after checking query patterns or explaining the expected query.
- Migrations must be reversible or include an explicit rollback/backup plan.
- Do not drop columns/tables in the same change that stops using them unless explicitly requested and production data safety is covered.
- Do not normalize `ui_schema_json` into new tables unless there is a concrete current need; prefer validation/extraction helpers first.
- Do not rewrite, rename, or reformat already applied backend migration files. Add new migrations only for new schema changes.
## Disabled Features
The following features are implemented but currently disabled with `false &&` conditions:
- **Navigation blocking while preloading** - Navigation buttons can be disabled until neighbor page backgrounds are preloaded. Currently disabled to allow instant navigation response. To re-enable, remove `false &&` in:
- `frontend/src/components/RuntimePresentation.tsx` (isForwardNavDisabled, handleElementClick)
- `frontend/src/pages/constructor.tsx` (handleElementClick, isNavDisabled calculation)
## Documentation Workflow
- **Before each task**: Research relevant documentation in `documentation/` to understand existing implementations, patterns, and conventions.
- **After each task**: Update affected documentation to reflect changes (API changes, new fields, modified workflows).
- **After implementing new features/modules**: Create new documentation file in `documentation/` following the existing format, and add reference to the Feature Documentation table in this file.
## Quick Start
```bash
# Terminal 1 - Backend (port 3000)
cd backend && npm run start-dev
# Terminal 2 - Frontend (port 3001)
cd frontend && npm run dev
```
## Common Commands
### Backend (run from `backend/` directory, runs on port 3000 in the default dev_stage flow)
```bash
npm install # Install dependencies
npm run start-dev # Start server (loads .env, migrates, seeds, watches)
npm run lint # ESLint check
npm run typecheck # Strict TypeScript check for migrated backend scope
npm run test # Unit tests (Node test runner)
npm run test:integration # Integration tests; DB tests skip when Postgres is unavailable
npm run test:e2e # E2E HTTP tests with a local listener
npm run test:all # Unit, integration, and e2e suites
npm run build # Compile migrated TypeScript files
npm run db:migrate # Run migrations only
npm run db:migrate:undo # Undo last migration
npm run db:seed # Seed database only
npm run db:reset # Drop, create, migrate, and seed
```
**Creating new migrations:** Add new migration files deliberately under `backend/src/db/migrations/` only when a schema change is required. Keep them reversible and preserve already applied migration files unchanged.
**Note:** Backend `.env` is loaded centrally by `backend/src/load-env.ts` for app and DB entrypoints. If `NODE_ENV` is absent, it defaults to `dev_stage`, matching the standard VM backend flow and using the `.env` DB settings. Do not add `NODE_ENV=production` to local startup unless a task explicitly requires the production config.
The backend defaults to port `3000` in `dev_stage` and `8080` otherwise; set `PORT` explicitly when a task needs a different port.
### Frontend (run from `frontend/` directory)
```bash
npm install # Install dependencies
npm run dev # Start dev server with Turbopack (port 3001)
npm run typecheck # TypeScript check without production build
npm run verify # Typecheck, lint, and production build
npm run build # Production build
npm run lint # ESLint check (.ts, .tsx files)
npm run format # Format code with Prettier
```
### Standard VM Environment
The standard VM port split is:
- **Frontend PM2 app `frontend-dev`**: Next.js production server on port `3001`
- **Backend PM2 app `backend-dev`**: `npm run start` with `NODE_ENV=dev_stage` on port `3000`
- **Apache**: public entrypoint and reverse proxy on port `80`
Direct VM backend health checks should target `http://127.0.0.1:3000/api/...`. A protected endpoint returning `401 Unauthorized` without JWT means the backend is reachable.
### Docker (run from `docker/` directory)
```bash
chmod +x start-backend.sh && chmod +x wait-for-it.sh # First time setup
docker-compose up # Start all services
rm -rf data && docker-compose up # Start with fresh database
```
## Architecture
### Backend Structure (`backend/src/`)
- **routes/**: Express route handlers (RESTful endpoints)
- **db/api/**: Database access layer (CRUD operations per model)
- **db/models/**: Sequelize model definitions
- **db/migrations/**: Database migrations
- **db/seeders/**: Seed data
- **auth/**: Passport.js authentication (JWT, Google OAuth, Microsoft OAuth)
- **services/**: Business logic services (emails, notifications, publishing, file storage)
- **factories/**: Router and service generation (`router.factory.js`, `service.factory.js`)
- **middlewares/**: Permission checking, runtime context handling
- **helpers/**: Utility functions (e.g., `wrapAsync` for async error handling)
### Frontend Structure (`frontend/src/`)
- **pages/**: Next.js pages (each entity has `-list`, `-edit`, `-new`, `-view`, `-table` variants)
- **components/**: React components (PascalCase naming)
- **stores/**: Redux Toolkit slices (per entity + auth, main, style slices)
- **layouts/**: Page layouts (Authenticated, Guest)
- **hooks/**: Global custom hooks (`usePreloadOrchestrator`, `useNeighborGraph`, etc.)
- **lib/**: Utility libraries (`elementStyles`, `imagePreDecode`, `mediaDuration`, `parseJson`)
- **types/**: TypeScript type definitions (`constructor.ts`, `runtime.ts`, `preload.ts`)
- **helpers/**: Utility functions
- **styles/**: Global CSS with Tailwind (`_theme.css` uses `@apply`)
### Key Domain Models
Projects, Tour Pages, Assets, Asset Variants, Permissions, Roles, Users, Publish Events, PWA Caches, Element Type Defaults, Project Element Defaults
**Note:** Page elements, navigation links, and transitions are stored directly in `tour_pages.ui_schema_json`.
### Element Defaults Hierarchy
The system has a two-level defaults cascade for UI elements:
1. **element_type_defaults** - Global platform-wide defaults (11 predefined types)
2. **project_element_defaults** - Project-specific overrides (auto-snapshotted from global on project creation)
When creating new elements, defaults cascade: global → project. Instance-specific settings are stored in `tour_pages.ui_schema_json`.
### Special Pages
- **`constructor.tsx`**: Tour builder/editor with drag-drop, element positioning, page management
- **`runtime.tsx`**: Tour playback with transitions, preloading, navigation
- **`p/[slug].tsx`**: Public tour pages with PWA offline support
### State Management
- **Redux Toolkit is the default only for client/app state** (auth/session UI, style/theme, layout/sidebar, constructor UI state, app preferences)
- **TanStack Query is the default for server state** (API reads, entity lists/details, mutations, invalidation, background refetch)
- Do not create new entity CRUD Redux slices in `stores/[entity]/[entity]Slice.ts`.
- Core slices: `authSlice.ts` (auth), `mainSlice.ts` (UI), `styleSlice.ts` (theming), `constructorSlice.ts` (editor)
- Use `useAppSelector` and `useAppDispatch` hooks from `stores/hooks.ts`
- **Local hooks acceptable** for ephemeral, component-scoped state (e.g., `usePageNavigation` for session-scoped page history)
- See [stores-module.md](frontend/docs/stores-module.md#state-management-guidelines) for decision tree
## Code Conventions
### Backend
- ES6+ with arrow functions, const/let
- Document endpoints with Swagger JSDoc comments
- Lowercase filenames (e.g., `auth.js`, `projects.js`)
### Frontend
- Functional components with TypeScript
- PascalCase for components and types, camelCase for variables/functions
- Custom hooks prefixed with `use` (e.g., `useAuth`)
- Tailwind CSS with theme customization in `_theme.css`
### Styling
- Theme customization uses `@apply` directive in `_theme.css`
- **Sidebar styles**: Target `#asideMenu` (defined in `AsideMenuLayer.tsx`) for sidebar overrides
- Use highly specific selectors when overriding Tailwind utilities to avoid conflicts
- Themed blocks (`.theme-pink`, `.theme-green`) standardize UI appearance - ensure custom overrides integrate cleanly
### Error Handling
- Backend: Use centralized `commonErrorHandler` middleware for uniform error responses
- Frontend: Use React error boundaries for runtime errors
## API Patterns
Routes follow pattern: `/api/[entity]/` with standard CRUD operations
- `POST /api/auth/signin/local` - Login
- `GET /api/auth/me` - Current user (requires JWT)
- Self-registration is disabled. New users are created by Administrator, Platform Owner, or Account Manager through the Users flow and receive an invitation/setup link.
All entity routes support: list, findOne, create, update, destroy operations with pagination and filtering.
## Backend Factory Patterns
### Router Factory (`factories/router.factory.js`)
Generates standard CRUD routes for entities:
```javascript
module.exports = createEntityRouter('assets', AssetsService, AssetsDBApi, {
permissionEntity: 'assets',
});
```
### Service Factory (`factories/service.factory.js`)
Generates service classes with transaction handling:
```javascript
module.exports = createEntityService('assets', AssetsDBApi);
```
### Base DB API (`db/api/base.api.js`)
All entity APIs extend `GenericDBApi` and override:
- `MODEL` - Sequelize model reference
- `SEARCHABLE_FIELDS` - Fields for text search
- `RANGE_FIELDS` - Fields for range filtering
- `ENUM_FIELDS` - Fields for exact match filtering
- `getFieldMapping(data)` - Transform input data before save
## File Storage
Controlled by `FILE_STORAGE_PROVIDER` env var or auto-detected from credentials:
- `s3` - AWS S3 (requires `S3_BUCKET`, `S3_REGION`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`)
- `gcloud` - Google Cloud Storage
- `local` - Local filesystem (default)
## Publishing Workflow
Three-tier **content environment** model (distinct from `NODE_ENV` server environment):
- **Dev** (constructor editing) → **Stage** (preview) → **Production** (public)
**Route-based environment access:**
- `/p/[slug]` - Production presentation
- `/p/[slug]/stage` - Stage presentation
- `/constructor?projectId=` - Dev editing (always dev environment)
Key endpoints:
- `POST /api/publish/save-to-stage` - Dev → Stage (body: `{ projectId }`)
- `POST /api/publish` - Stage → Production (body: `{ projectId }`)
**Environment isolation:** Pages have `environment` field (`dev`, `stage`, `production`). The `X-Runtime-Environment` header (set by frontend) determines which content environment to query. Both frontend (`RuntimePresentation.tsx`) and backend (`runtime-context.js`) filter by this field.
**Server Environment vs Content Environment:**
- `NODE_ENV` controls database config (production/dev_stage/development)
- `tour_pages.environment` controls content visibility (dev/stage/production)
### Private Production Presentations
Production presentations are public by default at `/p/[slug]`. Each project can switch production runtime visibility through `projects.production_presentation_visibility` (`public` default, `private` optional).
- Platform staff users with any RBAC permission can visit every private production presentation
- Customer users with `Public` role can visit only private production presentations granted in `production_presentation_access`
- `Administrator`, `Platform Owner`, and `Account Manager` can create users
- When creating or editing a `Public` user, the form shows a selector for private production presentations and saves DB access grants
- Do not use config files or env vars for customer allowlists
- Do not grant customer viewer users broad permissions such as `READ_PROJECTS` or `READ_TOUR_PAGES`; any RBAC permission makes the user platform staff for private presentation access
See [private-production-presentations.md](documentation/private-production-presentations.md).
## PWA & Offline Support
- **Service Worker**: Generated by Serwist from `frontend/src/sw.ts``public/sw.js`
- **Offline Caching**: PWA_Caches model tracks cached assets per project
- **Runtime Mode**: Middleware distinguishes public vs authenticated access for offline tours
## Asset Preloading Architecture
Runtime presentations use direct S3 downloads via presigned URLs for instant page navigation:
```
1. Request presigned URLs (max 50 per batch, 1-hour expiry)
POST /api/file/presign { urls: ["assets/img.jpg", ...] }
2. Download directly from S3 → Store in Cache API (< 5MB) or IndexedDB (≥ 5MB)
3. Create blob URL → Decode image → Store in readyBlobUrlsRef
4. Instant lookup during navigation (O(1))
const blobUrl = preloadOrchestrator.getReadyBlobUrl(originalUrl);
```
**Preload Priority:** Transition videos (+150) > Images (+100) > Audio (+50) > Video (+30)
**Storage Layers:**
| Layer | Size Limit | Purpose |
|-------|------------|---------|
| Cache API | < 5MB | Fast asset storage |
| IndexedDB (Dexie) | 5MB | Large assets, offline data |
| Blob URLs | Memory | Pre-decoded for instant display |
## Frontend Patterns
### MUI X Data Grid v7
Use new `valueGetter` signature:
```typescript
// For value transformation
valueGetter: (value) => value?.id ?? value
// For row access
valueGetter: (_value, row) => new Date(row.created_at)
```
### Custom Hooks
Hooks are located in three places:
- **`src/hooks/`**: Global hooks (`usePreloadOrchestrator`, `usePageNavigationState`, `useTransitionPlayback`, `usePageNavigation`)
- **`src/hooks/video/`**: Video playback primitives (8 composable hooks for video playback scenarios)
- **Component directories**: Domain-specific hooks (`components/Assets/useAssetUploader.ts`)
Key runtime hooks:
| Hook | Purpose |
|------|---------|
| `usePreloadOrchestrator` | Stream-first asset preloading (current page + transitions only) |
| `usePageNavigationState` | Unified navigation state machine (replaces 6+ hooks) |
| `useTransitionPlayback` | Video transition playback coordination |
| `usePageNavigation` | Page history tracking with browser-like back behavior |
| `useCanvasScale` | Responsive canvas scaling with letterbox mode |
| `useNetworkAware` | Network condition monitoring for adaptive transitions |
| `useBackgroundDimensionSuggestion` | Detect background media dimensions for canvas size suggestions |
**Video Hooks (`src/hooks/video/`):**
| Hook | Purpose |
|------|---------|
| `useVideoBlobUrl` | Resolve video URLs to blob URLs from preload cache |
| `useVideoPlaybackCore` | Core playback logic combining multiple primitives |
| `useVideoPlayer` | Complete UI video player hook |
### Redux Entity Pattern
Use this pattern only when maintaining an existing Redux entity flow; new server-state code should use TanStack Query hooks instead.
```typescript
import { fetch, deleteItem } from '../../stores/assets/assetsSlice';
const dispatch = useAppDispatch();
dispatch(fetch({ query: '?limit=100' }));
```
## Feature Documentation
Detailed feature documentation is available in `documentation/`:
| Document | Description |
|----------|-------------|
| [project-architecture.md](documentation/project-architecture.md) | Overall project structure and architecture |
| [api-reference.md](documentation/api-reference.md) | API endpoints reference |
| [authentication-system.md](documentation/authentication-system.md) | JWT, OAuth (Google, Microsoft) authentication |
| [rbac-system.md](documentation/rbac-system.md) | Role-based access control system |
| [user-management.md](documentation/user-management.md) | User CRUD, roles assignment, account management |
| [project-memberships.md](documentation/project-memberships.md) | Team collaboration, per-project access control |
| [asset-upload-variants.md](documentation/asset-upload-variants.md) | Asset upload pipeline and variant generation |
| [ui-elements.md](documentation/ui-elements.md) | UI Elements stored in `ui_schema_json` (buttons, hotspots, galleries, tooltips, media players) |
| [page-transitions.md](documentation/page-transitions.md) | Video transitions stored on navigation elements |
| [project-transition-settings.md](documentation/project-transition-settings.md) | Environment-aware CSS transition settings (fade, duration, easing) |
| [video-playback.md](documentation/video-playback.md) | Video player implementation, iOS autoplay compatibility |
| [assets-preloading.md](documentation/assets-preloading.md) | Asset preloading and caching strategy |
| [publishing-workflow.md](documentation/publishing-workflow.md) | Dev Stage Production publishing |
| [private-production-presentations.md](documentation/private-production-presentations.md) | Private production presentation allowlist, viewer users, and runtime access flow |
| [offline-pwa-mode.md](documentation/offline-pwa-mode.md) | PWA offline capabilities and caching |
| [email-notification-service.md](documentation/email-notification-service.md) | Nodemailer/SES integration, verification emails, invitations |
| [search-system.md](documentation/search-system.md) | Global full-text search, permission-based filtering |
| [deployment-vm.md](documentation/deployment-vm.md) | Standard VM deployment topology, PM2 recovery, ports, OOM/ffmpeg diagnostics |
| [custom-domains-apache.md](documentation/custom-domains-apache.md) | Customer-owned presentation domains via Apache, DNS A records, Certbot, and host/path routing |
| [page-links-navigation.md](documentation/page-links-navigation.md) | Page navigation using `targetPageSlug` in elements |
| [access-logs-audit-trail.md](documentation/access-logs-audit-trail.md) | Access logging, audit trail, activity tracking |
| [db-cleanup-audit.md](documentation/db-cleanup-audit.md) | Non-destructive DB cleanup audit, orphan checks, legacy schema checks, and soft-delete retention policy |
| [global-ui-controls.md](documentation/global-ui-controls.md) | Configurable fullscreen, sound, and offline system controls with global/project/page cascade |
| [backend/database-schema.md](backend/docs/database-schema.md) | Complete database schema - all models, fields, relationships, indexes, constraints |
| [backend/backend-architecture.md](backend/docs/backend-architecture.md) | Backend architecture - layers, design patterns, middleware, factories, file storage |
| [backend/api-endpoints.md](backend/docs/api-endpoints.md) | Complete API reference - all endpoints, request/response formats, authentication, rate limits |
| [backend/modules/core.md](backend/docs/modules/core.md) | Core module - index.js (entry), config.ts (configuration), helpers.js/utilities |
| [backend/modules/auth.md](backend/docs/modules/auth.md) | Auth module - Passport.js strategies (JWT, Google, Microsoft), login, invitation setup, password reset, email verification |
| [backend/modules/middleware.md](backend/docs/modules/middleware.md) | Middleware module - rate limiting, permissions, runtime context, public access control, file uploads |
| [backend/modules/routes.md](backend/docs/modules/routes.md) | Routes module - 22 route files, factory pattern, CRUD endpoints, Swagger docs, auth/file/search/sql routes |
| [backend/modules/services.md](backend/docs/modules/services.md) | Services module - business logic layer, 34 service files, factory pattern, file storage (S3/GCloud/Local), email, notifications, publishing |
| [backend/modules/email.md](backend/docs/modules/email.md) | Email module - Nodemailer/AWS SES, transactional emails, HTML templates, token management, email verification, password reset, invitations |
| [backend/modules/notifications.md](backend/docs/modules/notifications.md) | Notifications module - error classes (ValidationError, ForbiddenError), i18n message catalog, helper functions |
| [backend/modules/factories.md](backend/docs/modules/factories.md) | Factories module - createEntityRouter and createEntityService functions, code generation patterns for CRUD operations, boilerplate elimination |
| [backend/modules/db-models.md](backend/docs/modules/db-models.md) | DB Models module - 16 Sequelize models, entity definitions, associations, validations, lifecycle hooks, soft delete patterns |
| [backend/modules/db-api.md](backend/docs/modules/db-api.md) | DB API module - GenericDBApi base class, 18 entity APIs, declarative configuration, query filtering, runtime context helpers |
| [backend/modules/db-migrations.md](backend/docs/modules/db-migrations.md) | DB Migrations module - Umzug runner, migration safety rules, schema evolution, data backfill |
| [backend/modules/db-seeders.md](backend/docs/modules/db-seeders.md) | DB Seeders module - Umzug seeders, RBAC setup (7 roles, 54 permissions), sample data opt-in |
| [backend/modules/db-config.md](backend/docs/modules/db-config.md) | DB Config module - typed DB config, environment validation (Joi), Umzug commands, sync/reset scripts |
| [backend/modules/utilities.md](backend/docs/modules/utilities.md) | Utilities module - error classes, Pino logging, env validation, request helpers (wrapAsync, commonErrorHandler), DB utils, i18n messages |
| [backend/testing.md](backend/docs/testing.md) | Backend test strategy - unit, integration, and e2e coverage, helpers, commands, and environment notes |
| [frontend/hooks-reference.md](frontend/docs/hooks-reference.md) | React hooks reference (useFormSync, useEntityTable, useOfflineMode, etc.) |
| [frontend/video-hooks-module.md](frontend/docs/video-hooks-module.md) | Video playback primitive hooks (8 composable hooks for video scenarios) |
| [frontend/constructor-page-editor.md](frontend/docs/constructor-page-editor.md) | Constructor page editor - visual tour builder with drag-drop elements |
| [frontend/runtime-presentation.md](frontend/docs/runtime-presentation.md) | Runtime presentation viewer - full-screen tour playback with transitions |
| [frontend/navigation-smooth-transitions.md](frontend/docs/navigation-smooth-transitions.md) | Navigation & smooth transitions - page switching, transition video playback, last frame preservation, online/offline modes |
| [frontend/ui-adaptivity-system.md](frontend/docs/ui-adaptivity-system.md) | UI Adaptivity System - canvas units (--cu), responsive scaling, letterbox mode, element styling |
| [frontend/ui-element-preloading-analysis.md](frontend/docs/ui-element-preloading-analysis.md) | UI element processing & neighbor preloading - deep analysis of asset extraction, preload flow, offline caching |
| [frontend/asset-upload-preloading-pwa-analysis.md](frontend/docs/asset-upload-preloading-pwa-analysis.md) | Deep analysis of asset upload, preload orchestrator, PWA/offline mode, storage layers, network awareness |
| [frontend/frontend-architecture.md](frontend/docs/frontend-architecture.md) | Frontend architecture - 386 files, 14 modules, factories, hooks, Redux, PWA/offline, design patterns |
| [frontend/pages-module.md](frontend/docs/pages-module.md) | Pages module - 99 pages, _app.tsx entry, entity CRUD pattern, constructor, runtime presentations, layouts |
| [frontend/components-module.md](frontend/docs/components-module.md) | Components module - 183 files, entity tables, factories, constructor, element settings, runtime, PWA/offline |
| [frontend/hooks-module.md](frontend/docs/hooks-module.md) | Hooks module - 52 custom hooks, runtime/preloading, PWA/offline, constructor, tables/forms, UI utilities |
| [frontend/stores-module.md](frontend/docs/stores-module.md) | Stores module - Redux Toolkit, 17 slices (4 core + 13 entity), createEntitySlice factory, typed hooks |
| [frontend/lib-module.md](frontend/docs/lib-module.md) | Lib module - 19 utility files, asset URL management, element defaults/styles/effects, offline storage (Cache API + IndexedDB), download queue |
| [frontend/types-module.md](frontend/docs/types-module.md) | Types module - 18 TypeScript definition files, entity types, constructor/runtime types, API/Redux types, permissions enum, offline/preload types |
| [frontend/factories-module.md](frontend/docs/factories-module.md) | Factories module - 5 factory files (~1,285 LOC), createListPage, createFormPage, createTableComponent, configBuilderFactory, createEntitySlice for 91% boilerplate reduction |
| [frontend/schemas-module.md](frontend/docs/schemas-module.md) | Schemas module - 6 Zod validation schema files (~257 LOC), form validation for User, Asset, Project, TourPage, Role entities with type inference |
| [frontend/helpers-module.md](frontend/docs/helpers-module.md) | Helpers module - 6 utility files (~304 LOC), dataFormatter (entity display), hasPermission (RBAC), notifyStateHandler (Redux), text formatters, file saver |
| [frontend/layouts-module.md](frontend/docs/layouts-module.md) | Layouts module - 2 layout files (~262 LOC), LayoutAuthenticated (JWT auth, permissions, UI chrome), LayoutGuest (public pages), getLayout pattern |
| [frontend/config-module.md](frontend/docs/config-module.md) | Config module - 12 config files (~523 LOC), Next.js/Tailwind/TypeScript build config, runtime settings (config.ts), menu configs, offline/preload configs, ESLint rules |
| [frontend/context-module.md](frontend/docs/context-module.md) | Context module - DownloadContext (~256 LOC) for PWA download progress state, DownloadEventBus integration, useDownloadContext/useDownloadContextOptional hooks |
| [frontend/interfaces-module.md](frontend/docs/interfaces-module.md) | Interfaces module - ~15 type definition files (~2,200+ LOC), entity types, API contracts, Redux state shapes, permissions enum, constructor/runtime/offline/preload interfaces |