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

63 KiB
Raw Blame History

Frontend Architecture

Overview

The frontend is a Next.js 15 application with React 19, TypeScript, Redux Toolkit, and Tailwind CSS. It uses the Pages Router with client-side rendering (CSR), optimized for complex admin/builder interactions and PWA offline capabilities.

Location: frontend/src/

Total Files: 408 TypeScript/TSX files across 14 directories


Tech Stack

Technology Version Purpose
Next.js 15.3.1 React framework with Pages Router
React 19.0.0 UI library
TypeScript 5.x Type safety
Redux Toolkit 2.1.0 State management
MUI X DataGrid 7.0.0 Data tables
Tailwind CSS 3.4.1 Utility-first styling
Formik 2.4.x Form management
Axios 1.x HTTP client
Serwist 9.x PWA service worker
Dexie.js 4.x IndexedDB wrapper

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────────┐
│                           ENTRY LAYER                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ pages/_app.tsx                                                          │ │
│  │   • Redux Provider (store.ts)                                           │ │
│  │   • DownloadContext (PWA progress)                                      │ │
│  │   • Axios interceptors (JWT refresh, error handling)                    │ │
│  │   • PWA service worker registration (Serwist)                           │ │
│  │   • ErrorBoundary wrapper                                               │ │
│  │   • i18n initialization                                                 │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           LAYOUT LAYER                                       │
│  ┌───────────────────────────────────┐  ┌─────────────────────────────────┐ │
│  │ Authenticated.tsx                 │  │ Guest.tsx                       │ │
│  │   • JWT validation (client-side)  │  │   • Public routes only          │ │
│  │   • Permission checking per route │  │   • Login, Register, Forgot     │ │
│  │   • Project existence guard       │  │   • Minimal layout              │ │
│  │   • NavBar, AsideMenu, FooterBar  │  │                                 │ │
│  │   • Tour guide (IntroGuide)       │  │                                 │ │
│  └───────────────────────────────────┘  └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           PAGE LAYER (99 pages)                              │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ Entity CRUD Pages (78 pages = 13 entities × 6 pages each)               │ │
│  │   • [entity]-list.tsx   → createListPage factory                        │ │
│  │   • [entity]-new.tsx    → Formik forms with validation                  │ │
│  │   • [entity]-edit.tsx   → useEditPageSync hook                          │ │
│  │   • [entity]-view.tsx   → Read-only display                             │ │
│  │   • [entity]-table.tsx  → Embedded table view                           │ │
│  │   • [entityId].tsx      → Dynamic route handler                         │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ Special Pages (21 pages)                                                │ │
│  │   • constructor.tsx     → Visual tour builder (47KB)                    │ │
│  │   • dashboard.tsx       → Admin home with entity counts                 │ │
│  │   • p/[slug]/index.tsx  → Public production presentation                │ │
│  │   • p/[slug]/stage.tsx  → Stage preview presentation                    │ │
│  │   • login.tsx, forgot.tsx, password-reset.tsx → Auth flows              │ │
│  │   • profile.tsx         → User profile management                       │ │
│  │   • element-type-defaults.tsx → Global element defaults                 │ │
│  │   • project-element-defaults.tsx → Project element overrides            │ │
│  │   • search.tsx          → Global search                                 │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                        COMPONENT LAYER (193 components)                      │
│  ┌────────────────────────┐  ┌────────────────────────┐  ┌────────────────┐ │
│  │ Entity Components (78) │  │ Constructor (15)       │  │ Runtime (5)    │ │
│  │  • Table[Entity]       │  │  • ElementEditorPanel  │  │  • Runtime-    │ │
│  │  • configure*Cols      │  │  • CanvasElement       │  │    Presentation│ │
│  │  • Card[Entity]        │  │  • CanvasBackground    │  │  • Runtime-    │ │
│  │  • List[Entity]        │  │  • ConstructorMenu     │  │    Element     │ │
│  │  • Form fields         │  │  • PageSelector        │  │  • UiElement-  │ │
│  └────────────────────────┘  │  • TransitionPreview   │  │    Renderer    │ │
│  ┌────────────────────────┐  └────────────────────────┘  │                │ │
│  │ ElementSettings (23)   │  ┌────────────────────────┐  └────────────────┘ │
│  │  • StyleSettings       │  │ Offline/PWA (5)        │  ┌────────────────┐ │
│  │  • NavigationSettings  │  │  • DownloadProgress    │  │ Generic (50+)  │ │
│  │  • EffectsSettings     │  │  • OfflineToggle       │  │  • CardBox*    │ │
│  │  • CarouselSettings    │  │  • StorageUsage        │  │  • FormField*  │ │
│  │  • MediaSettings       │  │  • OfflineStatus       │  │  • NavBar*     │ │
│  │  • TooltipSettings     │  └────────────────────────┘  │  • AsideMenu*  │ │
│  └────────────────────────┘                              │  • BaseButton  │ │
│  ┌────────────────────────┐                              │  • Pagination  │ │
│  │ Factories (2)          │                              │  • Search      │ │
│  │  • createTableComp     │                              └────────────────┘ │
│  │  • configBuilderFact   │                                               │
│  └────────────────────────┘                                               │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           HOOKS LAYER (32 hooks)                             │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ Runtime/Preloading (8 hooks)                                            │ │
│  │   usePreloadOrchestrator ──→ usePageSwitch ──→ useBackgroundTransition  │ │
│  │          │                         │                                    │ │
│  │          ▼                         ▼                                    │ │
│  │   useNeighborGraph          useTransitionPlayback ──→ useReversePlayback│ │
│  │          │                                                              │ │
│  │          ▼                                                              │ │
│  │   usePageDataLoader ──→ usePreloadProgress                              │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ Constructor (7 hooks)                                                   │ │
│  │   useConstructorElements ──→ useConstructorPageActions                  │ │
│  │          │                                                              │ │
│  │          ▼                                                              │ │
│  │   useCanvasElementDrag ──→ useCanvasElapsedTime                         │ │
│  │          │                                                              │ │
│  │          ▼                                                              │ │
│  │   useTransitionPreview ──→ useIconPreload ──→ useMediaDurationProbe     │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
│  ┌────────────────────────┐  ┌────────────────────────┐  ┌────────────────┐ │
│  │ Offline/PWA (4)        │  │ Forms/Tables (4)       │  │ Utility (8)    │ │
│  │  • useOfflineMode      │  │  • useFormSync         │  │  • useCSV-     │ │
│  │  • usePWAPreload       │  │  • useEntityTable      │  │    Handling    │ │
│  │  • useStorageQuota     │  │  • useFilterItems      │  │  • useElement- │ │
│  │  • useNetworkAware     │  │  • useEditPageSync     │  │    Effects     │ │
│  └────────────────────────┘  └────────────────────────┘  │  • useOutside- │ │
│                                                          │    Click       │ │
│                                                          │  • useDraggable│ │
│                                                          └────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           STATE LAYER                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ Redux Store (stores/store.ts)                                           │ │
│  │  ┌─────────────────────────────────────────────────────────────────┐    │ │
│  │  │ Entity Slices (13) - via createEntitySlice factory              │    │ │
│  │  │   users, roles, permissions, projects, project_memberships,     │    │ │
│  │  │   assets, asset_variants, presigned_url_requests, tour_pages,   │    │ │
│  │  │   project_audio_tracks, publish_events, pwa_caches, access_logs │    │ │
│  │  └─────────────────────────────────────────────────────────────────┘    │ │
│  │  ┌─────────────────────────────────────────────────────────────────┐    │ │
│  │  │ Core Slices (3)                                                 │    │ │
│  │  │   • authSlice    - JWT token, current user, permissions         │    │ │
│  │  │   • mainSlice    - UI state (sidebar, dark mode)                │    │ │
│  │  │   • styleSlice   - Theme configuration                          │    │ │
│  │  └─────────────────────────────────────────────────────────────────┘    │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ React Context                                                           │ │
│  │   • DownloadContext - PWA download progress tracking                    │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           LIBRARY LAYER (20 files)                           │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ lib/offline/ - PWA Storage                                              │ │
│  │   • StorageManager.ts   - Cache API + IndexedDB dual storage            │ │
│  │   • DownloadManager.ts  - Asset download orchestration                  │ │
│  │   • DownloadEventBus.ts - Progress event system (Observer pattern)      │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ lib/offlineDb/ - IndexedDB Persistence                                  │ │
│  │   • OfflineDbManager.ts - Dexie.js wrapper for large assets             │ │
│  │   • schema.ts           - Database schema definition                    │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │ lib/ - Utilities                                                        │ │
│  │   • assetUrl.ts         - Presigned URL management, expiry handling     │ │
│  │   • elementDefaults.ts  - Default element configurations (17KB)         │ │
│  │   • elementStyles.ts    - Element CSS generation                        │ │
│  │   • elementEffects.ts   - Element animation effects                     │ │
│  │   • constructorHelpers.ts - Canvas manipulation utilities               │ │
│  │   • navigationHelpers.ts - Link resolution, transition detection        │ │
│  │   • extractPageLinks.ts - Parse navigation links from ui_schema         │ │
│  │   • imagePreDecode.ts   - Image pre-decoding for smooth transitions     │ │
│  │   • mediaDuration.ts    - Audio/video duration extraction               │ │
│  │   • mediaHelpers.ts     - Media URL handling                            │ │
│  │   • parseJson.ts        - Safe JSON parsing with fallbacks              │ │
│  │   • logger.ts           - Structured logging (dev/prod modes)           │ │
│  │   • slugHelpers.ts      - URL slug generation                           │ │
│  │   • tourFlowHelpers.ts  - Page ordering utilities                       │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           SUPPORT LAYER                                      │
│  ┌────────────────────┐  ┌────────────────────┐  ┌────────────────────────┐ │
│  │ factories/ (3)     │  │ schemas/ (6)       │  │ types/ (12)            │ │
│  │  • createListPage  │  │  • userSchema      │  │  • constructor.ts      │ │
│  │  • createFormPage  │  │  • assetSchema     │  │  • entities.ts         │ │
│  │  • index           │  │  • projectSchema   │  │  • runtime.ts          │ │
│  └────────────────────┘  │  • tourPageSchema  │  │  • preload.ts          │ │
│  ┌────────────────────┐  │  • roleSchema      │  │  • presentation.ts     │ │
│  │ helpers/ (6)       │  └────────────────────┘  │  • offline.ts          │ │
│  │  • dataFormatter   │  ┌────────────────────┐  │  • permissions.ts      │ │
│  │  • textFormatters  │  │ config/ (2)        │  │  • forms.ts            │ │
│  │  • userPermissions │  │  • preload.config  │  │  • filters.ts          │ │
│  │  • notifyState     │  │  • offline.config  │  │  • api.ts              │ │
│  │  • humanize        │  └────────────────────┘  │  • redux.ts            │ │
│  │  • fileSaver       │                          └────────────────────────┘ │
│  └────────────────────┘                                                      │
└─────────────────────────────────────────────────────────────────────────────┘

Directory Structure

frontend/src/
├── pages/                    # 99 files - Next.js pages
│   ├── _app.tsx              # App entry point
│   ├── api/                  # API routes (logError.ts, hello.js)
│   ├── p/[projectSlug]/      # Public presentation routes
│   │   ├── index.tsx         # Production presentation
│   │   └── stage.tsx         # Stage preview
│   ├── constructor.tsx       # Visual tour builder
│   ├── dashboard.tsx         # Admin home
│   ├── [entity]/             # 13 entity directories
│   │   ├── [entityId].tsx    # Dynamic route
│   │   ├── [entity]-list.tsx # List page
│   │   ├── [entity]-new.tsx  # Create page
│   │   ├── [entity]-edit.tsx # Edit page
│   │   ├── [entity]-view.tsx # View page
│   │   └── [entity]-table.tsx# Embedded table
│   └── ...                   # Auth, profile, search, etc.
│
├── components/               # 193 files - React components
│   ├── [Entity]/             # 13 entity component directories
│   │   ├── Table[Entity].tsx # DataGrid wrapper
│   │   ├── configure[Entity]Cols.tsx # Column config
│   │   ├── Card[Entity].tsx  # Card view
│   │   └── List[Entity].tsx  # List view
│   ├── Constructor/          # 15 files - Tour builder components
│   ├── ElementSettings/      # 23 files - Element configuration
│   ├── UiElements/           # 16 files - Unified element rendering (shared by Constructor + Runtime)
│   ├── Offline/              # 5 files - PWA components
│   ├── Generic/              # 3 files - Reusable table/form
│   ├── DataGrid/             # 1 file - Column config factory
│   ├── Factory/              # 1 file - Table component factory
│   ├── Uploaders/            # 1 file - Upload service
│   └── *.tsx                 # ~50 standalone components
│
├── hooks/                    # 32 files - Custom React hooks
│   ├── index.ts              # Re-exports
│   ├── usePreloadOrchestrator.ts  # Asset preloading (26KB)
│   ├── useTransitionPlayback.ts   # Video transitions (23KB)
│   ├── usePageSwitch.ts           # Page navigation (14KB)
│   ├── useConstructorElements.ts  # Element CRUD (12KB)
│   └── ...                        # 26 more hooks
│
├── stores/                   # Redux state
│   ├── store.ts              # Store configuration
│   ├── hooks.ts              # useAppSelector, useAppDispatch
│   ├── createEntitySlice.ts  # Entity slice factory (10KB)
│   ├── authSlice.ts          # Authentication state
│   ├── mainSlice.ts          # UI state
│   ├── styleSlice.ts         # Theme state
│   └── [entity]/             # 13 entity slice directories
│       └── [entity]Slice.ts  # Generated via factory
│
├── lib/                      # 20 files - Utility libraries
│   ├── offline/              # PWA storage layer
│   │   ├── StorageManager.ts # Cache API + IndexedDB
│   │   ├── DownloadManager.ts# Download orchestration
│   │   └── DownloadEventBus.ts # Progress events
│   ├── offlineDb/            # IndexedDB layer
│   │   ├── OfflineDbManager.ts # Dexie wrapper
│   │   └── schema.ts         # DB schema
│   ├── assetUrl.ts           # Presigned URL management
│   ├── elementDefaults.ts    # Default element configs
│   ├── elementStyles.ts      # CSS generation
│   ├── elementEffects.ts     # Animation effects
│   ├── constructorHelpers.ts # Canvas utilities
│   ├── navigationHelpers.ts  # Link resolution
│   ├── extractPageLinks.ts   # Parse links from schema
│   ├── imagePreDecode.ts     # Image pre-decoding
│   ├── mediaDuration.ts      # Media duration extraction
│   ├── mediaHelpers.ts       # Media URL handling
│   ├── parseJson.ts          # Safe JSON parsing
│   ├── logger.ts             # Structured logging
│   ├── slugHelpers.ts        # Slug generation
│   └── tourFlowHelpers.ts    # Page ordering
│
├── types/                    # 12 files - TypeScript definitions
│   ├── constructor.ts        # Canvas/element types
│   ├── entities.ts           # Entity interfaces
│   ├── runtime.ts            # Presentation runtime
│   ├── preload.ts            # Preloading state
│   ├── presentation.ts       # Navigation/transitions
│   ├── offline.ts            # PWA/cache types
│   ├── permissions.ts        # RBAC types
│   ├── forms.ts              # Form field types
│   ├── filters.ts            # Data filtering
│   ├── api.ts                # API response types
│   ├── redux.ts              # Store types
│   └── index.ts              # Re-exports
│
├── factories/                # 3 files - Page generators
│   ├── createListPage.tsx    # List page factory
│   ├── createFormPage.tsx    # Form page factory
│   └── index.ts              # Re-exports
│
├── schemas/                  # 6 files - Validation schemas
│   ├── userSchema.ts         # User validation
│   ├── assetSchema.ts        # Asset validation
│   ├── projectSchema.ts      # Project validation
│   ├── tourPageSchema.ts     # Tour page validation
│   ├── roleSchema.ts         # Role validation
│   └── index.ts              # Re-exports
│
├── helpers/                  # 6 files - Utility functions
│   ├── dataFormatter.js      # Data formatting
│   ├── textFormatters.ts     # Text formatting
│   ├── userPermissions.ts    # Permission checking
│   ├── notifyStateHandler.ts # Toast notifications
│   ├── humanize.ts           # Human-readable strings
│   └── fileSaver.ts          # File download
│
├── layouts/                  # 2 files - Page layouts
│   ├── Authenticated.tsx     # Auth layout with nav
│   └── Guest.tsx             # Public layout
│
├── config/                   # 2 files - Configuration
│   ├── preload.config.ts     # Preload settings
│   └── offline.config.ts     # PWA settings
│
├── context/                  # 1 file - React Context
│   └── DownloadContext.tsx   # PWA download progress
│
├── interfaces/               # 1 file - Shared interfaces
│   └── index.ts              # Common UI interfaces
│
└── css/                      # Stylesheets
    └── _theme.css            # Tailwind theme customization

Module Details

1. Pages Module (99 files)

Entity CRUD Pages (78 files)

Each of the 13 entities has 6 standardized pages:

Page Pattern Purpose Factory/Hook
[entity]-list.tsx List with filters, pagination, CSV export createListPage factory
[entity]-new.tsx Create form with validation Formik + entity schema
[entity]-edit.tsx Edit form with data sync useEditPageSync hook
[entity]-view.tsx Read-only display Direct entity fetch
[entity]-table.tsx Embedded table view createTableComponent
[entityId].tsx Dynamic route redirect Redirects to -view

Entities: users, roles, permissions, projects, project_memberships, assets, asset_variants, presigned_url_requests, tour_pages, project_audio_tracks, publish_events, pwa_caches, access_logs

Special Pages (21 files)

Page Size Description
index.tsx 1KB Root redirect to login or projects list
constructor.tsx 47KB Visual tour builder with canvas, drag-drop, element editing
dashboard.tsx 6KB Admin home with entity counts, quick actions
p/[projectSlug]/index.tsx 2KB Public production presentation (wraps RuntimePresentation)
p/[projectSlug]/stage.tsx 2KB Stage preview presentation
_app.tsx 11KB App entry, providers, interceptors
login.tsx 8KB Authentication with OAuth options
forgot.tsx 3KB Password reset request
profile.tsx 6KB User profile management
element-type-defaults.tsx 4KB Global element defaults editor
project-element-defaults.tsx 6KB Project-level element overrides
search.tsx 3KB Global search results

2. Components Module (193 files)

Entity Components (78 files, 13 directories)

Each entity directory contains:

File Pattern Purpose
Table[Entity].tsx MUI DataGrid wrapper with actions
configure[Entity]Cols.tsx Column definitions using configBuilderFactory
Card[Entity].tsx Card view for single entity
List[Entity].tsx List view variant
useAssetUploader.ts (Assets only) Upload hook
ProjectSelector.tsx (Assets only) Project filter

Constructor Components (15 files)

Component Size Description
ElementEditorPanel.tsx 22KB Right panel for element editing
ConstructorToolbar.tsx ~19KB Floating main toolbar with mode, Page actions, Elements actions, save/stage/exit controls
ConstructorMenu.tsx 5KB Legacy/collapsible constructor menu component
ConstructorControlsPanel.tsx 2KB Legacy/secondary constructor controls
CanvasElement.tsx 3KB Draggable element on canvas
CanvasBackground.tsx 3KB Background image/video layer
CreateTransitionForm.tsx 3KB Transition configuration modal
TransitionPreviewOverlay.tsx 1KB Transition video preview
PageSelector.tsx 1KB Page dropdown selector
InteractionModeToggle.tsx 2KB Edit/interact mode toggle
AssetSelectCompact.tsx 2KB Compact asset picker
BackgroundSettingsEditor.tsx 2KB Background configuration
ElementEditorHeader.tsx 1KB Editor panel header
MenuActionButton.tsx 1KB Menu button component
types.ts 7KB Constructor type definitions
index.ts 0.3KB Re-exports

ElementSettings Components (23 files)

Settings panels for different element aspects:

Component Description
StyleSettingsSection.tsx Position, size, colors, borders
StyleSettingsSectionCompact.tsx Compact version for constructor
NavigationSettingsSection.tsx Link targets, transitions
NavigationSettingsSectionCompact.tsx Compact version
EffectsSettingsSection.tsx Animations, hover effects
EffectsSettingsSectionCompact.tsx Compact version
CarouselSettingsSection.tsx Gallery/carousel configuration
GallerySettingsSection.tsx Image gallery settings
MediaSettingsSection.tsx Video/audio player settings
MediaSettingsSectionCompact.tsx Compact version
TooltipSettingsSection.tsx Tooltip configuration
TooltipSettingsSectionCompact.tsx Compact version
DescriptionSettingsSection.tsx Text content settings
DescriptionSettingsSectionCompact.tsx Compact version
CommonSettingsSection.tsx Shared element settings
CommonSettingsSectionCompact.tsx Compact version
GallerySettingsSection.tsx Gallery settings
GallerySettingsSectionCompact.tsx Compact version
GalleryCarouselSettingsSectionCompact.tsx Gallery carousel settings
ElementSettingsTabs.tsx Tab navigation
useElementSettingsForm.ts Form state management hook
types.ts Type definitions
index.ts Re-exports

UiElements Components (16 files)

Unified element rendering shared by both Constructor (CanvasElement) and Runtime (RuntimeElement):

Component Description
UiElementRenderer.tsx Main entry point - delegates to per-type components
shared/useElementWrapperStyle.ts Shared hook for consistent wrapper styling
elements/NavigationElement.tsx Navigation button (next/prev)
elements/GalleryElement.tsx Image gallery grid
elements/TooltipElement.tsx Tooltip with icon
elements/DescriptionElement.tsx Title + text block
elements/CarouselElement.tsx Image carousel with navigation
elements/LogoElement.tsx Logo display
elements/SpotElement.tsx Hotspot/clickable area
elements/VideoPlayerElement.tsx Embedded video player
elements/AudioPlayerElement.tsx Embedded audio player
elements/PopupElement.tsx Popup/modal dialog
GalleryCarouselOverlay.tsx Gallery/carousel fullscreen overlay
ElementPreview.tsx Preview element in constructor
defaults.ts Default element configurations
types.ts Element type definitions

Offline Components (5 files)

Component Description
DownloadProgressPanel.tsx Shows download progress for PWA
OfflineToggle.tsx Enable/disable offline mode
StorageUsageDisplay.tsx Shows storage quota usage
OfflineStatusIndicator.tsx Online/offline status badge
index.ts Re-exports

Factory Components (2 files)

Component Description
createTableComponent.tsx Factory that generates table wrapper components
configBuilderFactory.tsx Factory that generates DataGrid column configurations

Generic Components (3 files)

Component Size Description
GenericTable.tsx 14KB Reusable DataGrid with filters, pagination
GenericFormField.tsx 6KB Reusable form field component
index.ts 0.2KB Re-exports

Standalone Components (~50 files)

Category Components
Layout NavBar, NavBarItem, FooterBar, AsideMenu, AsideMenuItem, AsideMenuLayer, AsideMenuList
Cards CardBox, CardBoxModal, CardBoxComponentBody, CardBoxComponentTitle, CardBoxComponentFooter, CardBoxComponentEmpty
Forms FormField, FormFieldCompact, FormFilePicker, FormImagePicker, FormCheckRadio, FormCheckRadioGroup
Buttons BaseButton, BaseButtons, BaseIcon, BaseDivider
Data DataGridMultiSelect, SelectField, SelectFieldMany, SwitchField, RichTextField, ImageField
Sections SectionMain, SectionFullScreen, SectionTitle, SectionTitleLineWithButton
User UserAvatar, UserAvatarCurrentUser, UserCard, IconRounded
Utils Pagination, Search, SearchResults, LoadingSpinner, NotificationBar, OverlayLayer, ClickOutside
Auth PasswordSetOrReset
Features TourFlowManager, RuntimePresentation, RuntimeElement, DevModeBadge, IntroGuide, LanguageSwitcher, ErrorBoundary, DragDropFilePicker, ListActionsPopover

3. Hooks Module (32 files)

Runtime/Preloading Hooks (8 hooks)

Hook Size Description Used By
usePreloadOrchestrator 26KB Coordinates asset preloading with priority queue, blob URL caching RuntimePresentation
useTransitionPlayback 23KB Manages video transition playback (forward/reverse) RuntimePresentation
usePageSwitch 14KB Handles page navigation with preloaded assets RuntimePresentation
useReversePlayback 11KB Reverse video playback for back navigation useTransitionPlayback
useNeighborGraph 8KB Builds navigation graph for preload prioritization usePreloadOrchestrator
usePageDataLoader 7KB Loads project and pages data with caching RuntimePresentation
usePreloadProgress 6KB Tracks preload progress percentages RuntimePresentation
useBackgroundTransition 5KB Fade-out animation during page transitions RuntimePresentation

Constructor Hooks (7 hooks)

Hook Size Description Used By
useConstructorElements 12KB Element CRUD operations on canvas constructor.tsx
useConstructorPageActions 10KB Page management (create, delete, reorder) constructor.tsx
useMediaDurationProbe 6KB Extracts duration from video/audio files constructor.tsx
useTransitionPreview 6KB Previews transition videos constructor.tsx
useDraggable 6KB Generic drag functionality CanvasElement
useIconPreload 5KB Preloads icon assets constructor.tsx
useCanvasElementDrag 4KB Canvas-specific element dragging CanvasElement
useCanvasElapsedTime 3KB Animation timing for canvas constructor.tsx

Offline/PWA Hooks (4 hooks)

Hook Size Description Used By
useOfflineMode 11KB Detects and manages offline state _app.tsx, Offline components
usePWAPreload 5KB Preloads assets for PWA mode RuntimePresentation
useNetworkAware 5KB Network quality detection usePreloadOrchestrator
useStorageQuota 3KB Monitors storage usage StorageUsageDisplay

Form/Table Hooks (4 hooks)

Hook Size Description Used By
useEntityTable 8KB Table state management (pagination, sorting, filters) All entity tables
useEditPageSync 5KB Syncs form data with Redux on edit pages All -edit pages
useFilterItems 5KB Filter state management createListPage
useFormSync 3KB Form state synchronization Form components

Utility Hooks (8 hooks)

Hook Size Description Used By
useDashboardCounts 8KB Fetches entity counts for dashboard dashboard.tsx
useElementEffects 3KB Applies element animation effects RuntimeElement
useCSVHandling 4KB CSV import/export List pages
useOutsideClick 3KB Detects clicks outside element Modals, dropdowns
usePageNavigation 5KB Page navigation state RuntimePresentation
useProjectAssets 3KB Fetches and manages project assets Projects pages
useDevCompilationStatus 1KB Hot reload status indicator DevModeBadge

4. Stores Module (22 files)

Store Configuration

File Description
store.ts Redux store configuration with all slices
hooks.ts Typed hooks: useAppSelector, useAppDispatch
createEntitySlice.ts Factory for generating entity slices
introSteps.ts Tour guide step definitions

Core Slices

Slice Size State
authSlice.ts 4KB { token, currentUser, permissions, loading, error }
mainSlice.ts 1KB { isAsideMobileExpanded, isAsideLgActive, darkMode }
styleSlice.ts 3KB { asideStyle, navBarStyle, footerStyle, ... }
usersSlice.ts 3KB Extended user slice with password reset actions

Entity Slices (13)

Generated via createEntitySlice factory, each provides:

interface EntityState<T> {
  rows: T[];
  row: T | null;
  loading: boolean;
  error: string | null;
  count: number;
  filters: FilterState;
}

// Async thunks
fetch({ query: string })     // GET /api/[entity]?...
findById(id: string)         // GET /api/[entity]/:id
create(data: T)              // POST /api/[entity]
update({ id, data })         // PUT /api/[entity]/:id
deleteItem(id: string)       // DELETE /api/[entity]/:id

5. Library Module (20 files)

Offline Storage (lib/offline/)

File Size Description
StorageManager.ts 7KB Dual storage abstraction (Cache API < 5MB, IndexedDB >= 5MB)
DownloadManager.ts 12KB Download orchestration with retry, progress
DownloadEventBus.ts 5KB Event system for download progress (Observer pattern)

IndexedDB (lib/offlineDb/)

File Size Description
OfflineDbManager.ts 8KB Dexie.js wrapper for large asset storage
schema.ts 1KB IndexedDB schema: assets { url, blob, size, timestamp }

Element Utilities

File Size Description
elementDefaults.ts 18KB Default configurations for all 11 element types
elementStyles.ts 3KB Generates inline CSS from element config
elementEffects.ts 6KB Animation effect definitions and application
fonts.ts 2KB Font family definitions and mappings

Asset Utilities

File Size Description
assetUrl.ts 10KB Presigned URL management, expiry tracking, refresh
imagePreDecode.ts 6KB Pre-decodes images for smooth transitions
mediaDuration.ts 3KB Extracts duration from video/audio elements
mediaHelpers.ts 4KB Media URL normalization, type detection

Navigation Utilities

File Size Description
navigationHelpers.ts 4KB resolveNavigationTarget(), isTransitionBlocking()
extractPageLinks.ts 6KB Parses navigation links from ui_schema_json

Constructor Utilities

File Size Description
constructorHelpers.ts 8KB Canvas manipulation, element positioning
slugHelpers.ts 2KB URL slug generation for pages
tourFlowHelpers.ts 3KB Page ordering, drag-drop reordering

General Utilities

File Size Description
parseJson.ts 3KB Safe JSON parsing with fallbacks
logger.ts 4KB Structured logging (console in dev, silent in prod)

6. Types Module (12 files)

File Size Description
constructor.ts 10KB Canvas element, page, selection types
entities.ts 7KB All 13 entity interfaces
runtime.ts 2KB Runtime presentation state types
preload.ts 1KB Preload queue, progress types
presentation.ts 2KB Navigation, transition types
offline.ts 4KB PWA cache, download types
permissions.ts 4KB RBAC permission types
forms.ts 2KB Form field, validation types
filters.ts 2KB Data filter types
api.ts 1KB API response types
redux.ts 1KB Store, dispatch types
index.ts 0.3KB Re-exports

7. Factories Module (3 files)

Factory Size Description
createListPage.tsx 6KB Generates list pages with filters, CSV, pagination
createFormPage.tsx 9KB Generates form pages with validation
index.ts 0.1KB Re-exports

createListPage Usage:

export default createListPage({
  entityName: 'assets',
  entityNamePlural: 'Assets',
  permissionPrefix: 'ASSETS',
  columns: configureAssetsCols,
  filterFields: ['name', 'type', 'status'],
});

createFormPage Usage:

export default createFormPage({
  entityName: 'assets',
  schema: assetSchema,
  fields: ['name', 'file', 'project'],
});

8. Schemas Module (6 files)

Formik/Yup validation schemas:

Schema Fields Validated
userSchema.ts email, firstName, lastName, password, role
assetSchema.ts name, file, type, project
projectSchema.ts name, slug, description
tourPageSchema.ts name, slug, order, background
roleSchema.ts name, permissions
index.ts Re-exports

9. Helpers Module (6 files)

Helper Description
dataFormatter.js Format dates, numbers, booleans for display
textFormatters.ts Truncate, capitalize, slugify text
userPermissions.ts hasPermission(), canAccess() utilities
notifyStateHandler.ts Toast notification triggers
humanize.ts Convert snake_case to readable text
fileSaver.ts Trigger file downloads

10. Layouts Module (2 files)

Layout Description
Authenticated.tsx Full layout with JWT validation, permission checks, NavBar, AsideMenu, FooterBar, IntroGuide
Guest.tsx Minimal layout for public pages (login, password reset, public presentations)

Per-Page Layout Pattern:

UsersListPage.getLayout = (page: ReactElement) => (
  <LayoutAuthenticated permission="READ_USERS">
    {page}
  </LayoutAuthenticated>
);

11. Config Module (2 files)

Config Settings
preload.config.ts Priority weights, batch sizes, concurrent limits
offline.config.ts Cache names, storage thresholds, expiry times

Preload Priority Weights:

export const PRELOAD_PRIORITY = {
  TRANSITION_VIDEO: 150,  // Highest - needed for navigation
  IMAGE: 100,
  AUDIO: 50,
  VIDEO: 30,              // Lowest - large files
};

12. Context Module (1 file)

Context Description
DownloadContext.tsx PWA download progress tracking, shared across components

Usage:

const { progress, isDownloading, startDownload, cancelDownload } = useDownloadContext();

Design Patterns

1. Factory Pattern

Eliminates ~80% boilerplate code:

Factory Generates Files Eliminated
createEntitySlice Redux slices with CRUD thunks 13 × 200 LOC = 2600 LOC
createListPage List pages with filters, pagination 13 × 150 LOC = 1950 LOC
createFormPage Form pages with validation 13 × 180 LOC = 2340 LOC
createTableComponent Table wrapper components 13 × 50 LOC = 650 LOC
configBuilderFactory Column configurations 13 × 80 LOC = 1040 LOC

Total: ~8500 LOC eliminated through factories

2. Custom Hook Pattern

Hooks are composed hierarchically:

usePreloadOrchestrator
    ├── useNeighborGraph (build priority queue)
    ├── useNetworkAware (adjust batch size)
    └── Internal: presigned URL fetching, blob caching

usePageSwitch
    ├── usePreloadOrchestrator.getReadyBlobUrl()
    └── useBackgroundTransition (fade animation)

useTransitionPlayback
    ├── useReversePlayback (back navigation)
    └── Internal: video element management

3. HOC via getLayout

Per-page layout injection without wrapper components:

// Page defines its layout
MyPage.getLayout = (page) => (
  <LayoutAuthenticated permission="READ_ASSETS">
    {page}
  </LayoutAuthenticated>
);

// _app.tsx applies it
const getLayout = Component.getLayout ?? ((page) => page);
return getLayout(<Component {...pageProps} />);

4. Repository Pattern

Entity slices abstract all API calls:

// Component only knows about Redux actions
dispatch(fetch({ query: '?limit=100' }));
dispatch(create(newAsset));
dispatch(update({ id, data: changes }));
dispatch(deleteItem(id));

// Slice handles API communication
const fetch = createAsyncThunk('assets/fetch', async ({ query }) => {
  const response = await axios.get(`/api/assets${query}`);
  return response.data;
});

5. Observer Pattern

Download progress events:

// DownloadEventBus.ts
class DownloadEventBus {
  private listeners: Map<string, Set<Callback>>;

  emit(event: 'progress' | 'complete' | 'error', data: any) {
    this.listeners.get(event)?.forEach(cb => cb(data));
  }

  on(event: string, callback: Callback) {
    this.listeners.get(event)?.add(callback);
  }
}

// Consumer
downloadEventBus.on('progress', ({ url, percent }) => {
  setProgress(prev => ({ ...prev, [url]: percent }));
});

6. Strategy Pattern

Storage selection based on file size:

// StorageManager.ts
class StorageManager {
  async store(url: string, blob: Blob) {
    if (blob.size < 5 * 1024 * 1024) {  // < 5MB
      return this.cacheApiStore(url, blob);  // Fast, limited
    } else {
      return this.indexedDbStore(url, blob); // Slow, unlimited
    }
  }
}

Key Flows

1. Runtime Presentation Flow

User navigates to /p/[slug]
           │
           ▼
┌─────────────────────────────────────┐
│ usePageDataLoader                   │
│   • Fetch project by slug           │
│   • Fetch pages for environment     │
│   • Determine initial page          │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ usePreloadOrchestrator              │
│   • Build neighbor graph            │
│   • Calculate priorities            │
│   • Request presigned URLs          │
│   • Download assets to cache        │
│   • Pre-decode images               │
│   • Store blob URLs                 │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ RuntimePresentation renders         │
│   • Background (image/video)        │
│   • RuntimeElement for each element │
│     └── UiElementRenderer           │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ User clicks navigation element      │
│   • resolveNavigationTarget()       │
│   • isTransitionBlocking()          │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ usePageSwitch                       │
│   • Get blob URL from cache (O(1))  │
│   • useBackgroundTransition()       │
│   • If transition video:            │
│     useTransitionPlayback()         │
│   • Switch to new page              │
└─────────────────────────────────────┘

2. Constructor Flow

User opens /constructor?projectId=X
           │
           ▼
┌─────────────────────────────────────┐
│ Fetch project and pages             │
│   • Redux: projects.findById()      │
│   • Redux: tour_pages.fetch()       │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ useConstructorElements              │
│   • Parse ui_schema_json            │
│   • Initialize element state        │
│   • Provide CRUD methods            │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ Canvas renders                      │
│   • CanvasBackground                │
│   • CanvasElement for each element  │
│   • useCanvasElementDrag            │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ User edits element                  │
│   • ElementEditorPanel opens        │
│   • useElementSettingsForm          │
│   • Settings sections render        │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ Save changes                        │
│   • Update ui_schema_json           │
│   • Redux: tour_pages.update()      │
│   • API: PUT /api/tour_pages/:id    │
└─────────────────────────────────────┘

3. Offline/PWA Flow

User enables offline mode
           │
           ▼
┌─────────────────────────────────────┐
│ DownloadManager.startDownload()     │
│   • Get asset manifest              │
│   • Request presigned URLs          │
│   • Queue downloads                 │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ For each asset:                     │
│   • Fetch with progress tracking    │
│   • DownloadEventBus.emit()         │
│   • StorageManager.store()          │
│     - Cache API (< 5MB)             │
│     - IndexedDB (>= 5MB)            │
└─────────────────────────────────────┘
           │
           ▼
┌─────────────────────────────────────┐
│ Service worker intercepts           │
│   • Check Cache API                 │
│   • Check IndexedDB                 │
│   • Return cached response          │
└─────────────────────────────────────┘

Entity Architecture

Each entity follows a consistent structure:

[Entity] (e.g., Assets)
│
├── pages/assets/
│   ├── [assetsId].tsx          # Dynamic route → view
│   ├── assets-list.tsx         # List with filters
│   ├── assets-new.tsx          # Create form
│   ├── assets-edit.tsx         # Edit form
│   ├── assets-view.tsx         # Read-only view
│   └── assets-table.tsx        # Embedded table
│
├── components/Assets/
│   ├── TableAssets.tsx         # DataGrid wrapper
│   ├── configureAssetsCols.tsx # Column definitions
│   ├── CardAssets.tsx          # Card view
│   ├── ListAssets.tsx          # List view
│   ├── useAssetUploader.ts     # Upload hook (assets only)
│   └── ProjectSelector.tsx     # Filter component
│
├── stores/assets/
│   └── assetsSlice.ts          # Redux slice via factory
│
└── schemas/
    └── assetSchema.ts          # Validation schema

13 Entities:

  • users, roles, permissions
  • projects, project_memberships
  • assets, asset_variants, presigned_url_requests
  • tour_pages, project_audio_tracks
  • publish_events, pwa_caches, access_logs

Configuration

Next.js Config (next.config.mjs)

const nextConfig = {
  reactStrictMode: true,

  typescript: {
    ignoreBuildErrors: false,  // Enforce type checking
  },

  eslint: {
    ignoreDuringBuilds: false, // Enforce linting
  },

  images: {
    domains: ['cdn.platform.com', 's3.amazonaws.com'],
  },

  // PWA via Serwist
  // Turbopack enabled for dev
};

Tailwind Config

Theme customization in css/_theme.css:

/* Sidebar styling */
#asideMenu {
  @apply bg-gray-900 text-white;
}

/* Theme variants */
.theme-pink .card {
  @apply border-pink-500;
}

Performance Optimizations

1. Asset Preloading

  • Priority Queue: Transition videos > Images > Audio > Video
  • Batch Fetching: Max 50 presigned URLs per request
  • Network Awareness: Reduce batch size on slow connections
  • Blob URL Caching: O(1) lookup during navigation

2. Image Pre-Decoding

// imagePreDecode.ts
export async function preDecodeImage(blobUrl: string): Promise<void> {
  const img = new Image();
  img.src = blobUrl;
  await img.decode();  // Decode before display
}

3. Lazy Loading

  • Route-based code splitting (Next.js automatic)
  • Dynamic imports for large components

4. Redux Optimization

  • Normalized entity state
  • Selective re-renders via useAppSelector
  • Memoized selectors where needed

Document Description
hooks-reference.md Detailed hook documentation
runtime-presentation.md Runtime presentation architecture
constructor-page-editor.md Constructor page documentation
assets-preloading.md Asset preloading strategy
offline-pwa-mode.md PWA offline capabilities
ui-elements.md UI element types and configuration

File Reference by Size

Largest Files (> 10KB)

File Size Description
pages/constructor.tsx 47KB Visual tour builder
hooks/usePreloadOrchestrator.ts 26KB Asset preloading
hooks/useTransitionPlayback.ts 23KB Video transitions
components/Constructor/ElementEditorPanel.tsx 22KB Element editor
components/RuntimePresentation.tsx 19KB Tour playback
lib/elementDefaults.ts 18KB Element defaults
components/TourFlowManager.tsx 17KB Page management
hooks/usePageSwitch.ts 14KB Page navigation
components/Generic/GenericTable.tsx 14KB Reusable table
hooks/useConstructorElements.ts 12KB Element CRUD
lib/offline/DownloadManager.ts 12KB Download management
hooks/useReversePlayback.ts 11KB Reverse video
hooks/useOfflineMode.ts 11KB Offline detection
pages/_app.tsx 11KB App entry
lib/assetUrl.ts 10KB Presigned URLs
stores/createEntitySlice.ts 10KB Slice factory
types/constructor.ts 10KB Constructor types

Summary

The frontend architecture demonstrates several strong patterns:

Strengths:

  • Factory patterns eliminate ~8500 LOC of boilerplate
  • 32 custom hooks provide clean separation of concerns
  • Dual storage strategy (Cache API + IndexedDB) enables robust offline
  • Per-page layout pattern with permission checking
  • Strong TypeScript typing across 12 type definition files

Architecture Decisions:

  • CSR-only approach (appropriate for admin/builder app)
  • Pages Router (stable, full-featured)
  • Redux Toolkit for predictable state management
  • MUI X DataGrid for complex data tables
  • Tailwind CSS for utility-first styling

Total Codebase:

  • 408 TypeScript/TSX files
  • ~80,000 LOC estimated
  • 14 distinct modules
  • 13 entity CRUD implementations