# 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.ڑ