# Architecture ## Stack - Next.js (App Router) - TypeScript - next-intl - Prisma + PostgreSQL - Tailwind CSS - Radix UI (via local primitives) - framer-motion - nodemailer --- # Application Structure ## Public application Localized public pages live under: app/[locale]/(site) Locale routing and configuration are defined in: i18n/routing.ts The public layout checks the maintenance status and redirects visitors to: /coming-soon when maintenance mode is enabled. --- ## Admin application Admin pages are implemented under: app/_admin Internal admin routing is rewritten to: app/admin-internal Development alias routes also exist under: app/root Routing decisions and host/path-based rewrites are implemented in: lib/admin-routing.ts The `_admin` structure should be treated as the canonical admin source. --- # Core Modules Application logic lives primarily in `lib/*`. Important modules include: lib/portfolio.ts Handles portfolio queries and localized mapping. lib/app-config.ts Provides application-level configuration values. lib/media.ts Handles media library queries and media bindings. lib/mail.ts Handles SMTP delivery via nodemailer. These modules act as the primary server-side application layer. --- # UI Layer Shared UI primitives live in: components/ui These primitives wrap Radix UI components and define the shared design system. Public site UI components live in: components/site components/layout Admin UI components live in: components/admin components/dashboard Shared primitives must always originate from `components/ui`. Feature-level UI should reuse these primitives rather than reimplementing them. --- # Persistence Layer Database access is implemented using Prisma. Prisma client lives in: lib/prisma.ts Configuration values are stored in the database via: AppConfig which acts as a key-value store for runtime configuration values. Database access should always occur through server-side modules. Client components must never access Prisma directly. --- # Architectural Boundaries The following boundaries must be respected: - Client components must not access Prisma. - Business logic must not live inside UI components. - Shared UI must originate from `components/ui`. - Public site UI belongs in `components/site`. - Admin UI belongs in `components/admin` or `components/dashboard`. - Server actions act as request entry points for form submissions. - Server actions may call modules in `lib/*`. Database queries should not be implemented directly inside route-level UI files. --- # Request Flow Examples ## Contact submission 1. User submits the form on app/[locale]/(site)/contact/page.tsx 2. Server action validates the input using Zod. 3. Email is sent through: lib/mail.ts 5. The user is redirected to: /success or back to the form with an error state. --- ## Portfolio publishing 1. Admin edits a project form. 2. Server action validates categories, fields, sections, and assets. 3. Media selections are resolved via: lib/media.ts 4. Project data, sections, assets, and media usage are persisted via Prisma. 5. Public and admin paths are revalidated. --- # Canonical Sources The following files should be treated as canonical sources for specific domains: Routing i18n/routing.ts Admin routing lib/admin-routing.ts Prisma access lib/prisma.ts Application configuration lib/app-config.ts Portfolio logic lib/portfolio.ts Media handling lib/media.ts --- # Proposed Future Improvements (Not Implemented) These ideas are **not currently implemented** but may be introduced later: - Split `app-config` concerns into smaller modules if additional domains are added. - Introduce dedicated models instead of expanding the `AppConfig` key-value store. - Introduce explicit service boundaries if the application grows significantly.ڑ