# ArchiTools — System Architecture ## 1. Platform Overview ArchiTools is a modular internal web dashboard platform built for a group of architecture, urban design, and engineering companies based in Cluj-Napoca, Romania: - **Beletage SRL** — architecture office - **Urban Switch SRL** — architecture and urban projects - **Studii de Teren SRL** — engineering, surveying, GIS, technical studies The platform centralizes daily operational tools: document registries, generators, templates, inventories, AI-assisted workflows, and technical utilities. It replaces scattered standalone HTML tools and manual processes with a unified, themeable, module-driven dashboard. **Key constraints:** - Internal-first deployment (external/guest access planned for later phases) - Romanian UI labels; English code and comments - On-premise Docker deployment behind reverse proxy - localStorage as initial persistence layer, abstracted for future database/object store migration - Must function as a **module platform**, not a monolithic application --- ## 2. High-Level Architecture ``` ┌─────────────────────────────────────────────────────────────────────┐ │ NGINX PROXY MANAGER │ │ (TLS termination, routing) │ └──────────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ DOCKER CONTAINER (Next.js) │ │ │ │ ┌───────────────────────────────────────────────────────────────┐ │ │ │ PRESENTATION LAYER │ │ │ │ App Shell │ Sidebar │ Theme │ i18n │ Module Routes │ │ │ └──────────────────────────┬────────────────────────────────────┘ │ │ │ │ │ ┌──────────────────────────┴────────────────────────────────────┐ │ │ │ MODULE LAYER │ │ │ │ │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │Registra- │ │ Email │ │ Word XML │ │ Prompt │ ... │ │ │ │ │ tura │ │Signature │ │Generator │ │Generator │ │ │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ │ │ │ │ └───────┼─────────────┼────────────┼─────────────┼──────────────┘ │ │ │ │ │ │ │ │ ┌───────┴─────────────┴────────────┴─────────────┴──────────────┐ │ │ │ CORE SERVICES LAYER │ │ │ │ │ │ │ │ Module Registry │ Feature Flags │ Storage Abstraction │ │ │ │ Tagging System │ i18n Engine │ Theme Provider │ │ │ │ Auth Stub │ Navigation │ Config │ │ │ └──────────────────────────┬────────────────────────────────────┘ │ │ │ │ │ ┌──────────────────────────┴────────────────────────────────────┐ │ │ │ STORAGE LAYER │ │ │ │ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ localStorage │ │ MinIO │ │ Database │ │ │ │ │ │ (current) │ │ (planned) │ │ (planned) │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └───────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ ┌──────────────────┼──────────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │ Authentik │ │ MinIO │ │ N8N │ │ (SSO) │ │ (obj store) │ │ (automation) │ └─────────────┘ └──────────────┘ └──────────────┘ ``` --- ## 3. Core Architecture Principles ### 3.1 Module Platform, Not Monolith The application is a **platform that hosts modules**. The shell (layout, sidebar, theme, navigation) exists to load and present modules. No module is assumed to exist at build time — the system must function with zero modules enabled. ### 3.2 Module Isolation Each module owns its: - Route subtree (`/app/(modules)/[module-name]/`) - Business logic (`/modules/[module-name]/`) - Types, services, hooks, and components - Storage namespace (scoped key prefix) - Configuration entry in the module registry Modules must never import from another module's internal directories. Cross-module communication happens exclusively through core services (tagging system, storage abstraction, shared hooks). ### 3.3 Removability Disabling a module via feature flag must not produce build errors, runtime errors, or broken navigation. This is enforced by: - Config-driven navigation (only enabled modules appear) - Dynamic imports for module routes - No direct cross-module imports - Feature flag guards at route and component boundaries ### 3.4 Storage Independence No module or component may call `localStorage`, `sessionStorage`, or any browser storage API directly. All persistence flows through the storage abstraction layer, which resolves to the active adapter at runtime. ### 3.5 Presentation/Logic Separation UI components receive data via props and hooks. Business logic lives in `services/` (pure functions) and `hooks/` (stateful logic). Components do not contain data transformation, validation, or persistence logic. --- ## 4. Layer Architecture ``` ┌─────────────────────────────────────────────────────┐ │ PRESENTATION LAYER │ │ Next.js App Router pages, layouts, UI components │ │ shadcn/ui primitives, Tailwind styling │ │ Theme provider, i18n labels │ ├─────────────────────────────────────────────────────┤ │ MODULE LAYER │ │ Module-specific components, hooks, services │ │ Module config, types, route pages │ │ Isolated per module, lazy-loadable │ ├─────────────────────────────────────────────────────┤ │ CORE SERVICES LAYER │ │ Module registry, feature flags, navigation │ │ Storage abstraction, tagging, auth stub │ │ i18n engine, theme system, config │ ├─────────────────────────────────────────────────────┤ │ STORAGE / INTEGRATION LAYER │ │ Storage adapters (localStorage, MinIO, DB, API) │ │ External service clients │ │ Environment configuration │ └─────────────────────────────────────────────────────┘ ``` ### Layer Rules | Layer | May Import From | Must Not Import From | |-------|----------------|---------------------| | Presentation | Module Layer, Core Services, Shared | — | | Module Layer | Core Services, Shared | Other modules | | Core Services | Shared, Config | Module Layer, Presentation | | Storage/Integration | Config only | Everything else | --- ## 5. Runtime Architecture ### 5.1 Next.js App Router The application uses Next.js 15 with the App Router. The routing structure: ``` app/ ├── layout.tsx → Root layout: providers, shell wrapper ├── page.tsx → Dashboard home (widget grid) ├── globals.css → Tailwind base + custom tokens └── (modules)/ → Route group (no URL segment) ├── registratura/ │ ├── page.tsx → Module entry page │ └── [id]/ │ └── page.tsx → Detail view ├── email-signature/ │ └── page.tsx └── ... ``` ### 5.2 Client-Side Primary, SSR Where Needed The platform is primarily a client-side interactive application. Most module pages use `"use client"` directives because they: - Manage complex form state - Interact with browser storage - Require immediate user feedback - Handle drag-and-drop, clipboard, and other browser APIs Server-side rendering is used for: - The shell layout (static structure, fast first paint) - Metadata generation - Any future API routes serving data to external consumers ### 5.3 Provider Stack The root layout wraps the application in a provider stack: ``` {children} ``` Each provider is independent and can be replaced or extended without affecting others. --- ## 6. Module Isolation Model ### 6.1 Module Structure Every module follows a standard directory structure: ``` src/modules/[module-name]/ ├── components/ # Module-specific React components ├── hooks/ # Module-specific React hooks ├── services/ # Pure business logic functions ├── types.ts # TypeScript interfaces and types ├── config.ts # Module metadata for the registry └── index.ts # Public API barrel export ``` ### 6.2 Module Registration Each module exports a `ModuleConfig` object: ```typescript interface ModuleConfig { id: string; // Unique identifier (kebab-case) name: string; // Romanian display name description: string; // Romanian description icon: string; // Lucide icon name route: string; // Base route path category: ModuleCategory; // Grouping for navigation enabled: boolean; // Default enabled state featureFlag: string; // Flag key in feature flag system requiredRole?: UserRole; // Minimum role (future use) visibility?: Visibility; // internal | admin | public version: string; // Semver storageNamespace: string; // Storage key prefix } ``` The central module registry (`src/config/modules.ts`) imports all module configs and provides them to the navigation system and feature flag guards. ### 6.3 Module Lifecycle ``` 1. Module config registered in modules.ts 2. Feature flag checked at runtime 3. If enabled: route is accessible, nav item visible 4. Module page loads (dynamic import possible) 5. Module initializes its hooks/services 6. Module reads/writes through storage abstraction 7. If disabled: route returns redirect/404, nav item hidden ``` --- ## 7. Core Systems Overview ### 7.1 Module Registry **Location:** `src/core/module-registry/` Central catalog of all available modules. Provides: - List of all registered modules with metadata - Lookup by ID, route, or category - Filtering by enabled state, visibility, role - Module category grouping for navigation The registry is the single source of truth for what modules exist. Navigation, routing guards, and the dashboard widget grid all read from it. ### 7.2 Feature Flags **Location:** `src/core/feature-flags/` Controls module activation and experimental feature visibility. ```typescript interface FeatureFlag { key: string; enabled: boolean; scope: 'module' | 'feature' | 'experiment'; requiredRole?: UserRole; description: string; } ``` Flag resolution order: 1. Environment variable override (`NEXT_PUBLIC_FLAG_*`) 2. Runtime config (`src/config/flags.ts`) 3. Default from module config Flags are checked via the `useFeatureFlag(key)` hook and the `` component wrapper. ### 7.3 Storage Abstraction **Location:** `src/core/storage/` All data persistence flows through a `StorageService` interface: ```typescript interface StorageService { get(namespace: string, key: string): Promise; set(namespace: string, key: string, value: T): Promise; delete(namespace: string, key: string): Promise; list(namespace: string): Promise; clear(namespace: string): Promise; } ``` **Adapters:** | Adapter | Status | Use Case | |---------|--------|----------| | `LocalStorageAdapter` | Current | Browser-local persistence, demo/dev mode | | `MinIOAdapter` | Planned | File and object storage (signatures, templates) | | `DatabaseAdapter` | Planned | Structured data (registry entries, inventory) | | `APIAdapter` | Planned | External service delegation | The active adapter is resolved at startup from environment configuration. Modules never know which adapter is active. **Namespace isolation:** Each module operates within its own namespace (e.g., `registratura:entries`, `password-vault:credentials`). Modules cannot read or write to another module's namespace without explicit cross-module service mediation. ### 7.4 Tagging System **Location:** `src/core/tagging/` A cross-module tagging service used by multiple modules to categorize and link entities. Tags are structured objects: ```typescript interface Tag { id: string; label: string; // Romanian display label category: TagCategory; // project | client | domain | custom color?: string; metadata?: Record; createdAt: string; } ``` The tagging system provides: - Tag CRUD operations (stored via storage abstraction) - Tag selector component (shared UI) - Tag filtering and search - Tag usage tracking across modules Modules that use tags: Registratura, Prompt Generator, Word Templates, Digital Signatures, IT Inventory, Address Book. ### 7.5 Internationalization (i18n) **Location:** `src/core/i18n/` Current implementation: Romanian-only with structured label access for future multi-language support. Labels are organized by module namespace: ```typescript const labels = { common: { save: 'Salvează', cancel: 'Anulează', delete: 'Șterge', search: 'Caută', // ... }, registratura: { title: 'Registratură', newEntry: 'Înregistrare nouă', // ... }, }; ``` Access pattern: `useLabel('registratura.newEntry')` or `