---
title: Project Structure
tags: [development]
---

# Project Structure

A bird's-eye view of both repos. For deep dives, follow the cross-links to [[Backend Architecture]] and [[Frontend Architecture]].

---

## Backend — `/Users/mojtabaheidari/code/backend`

A service-oriented Express 5 app. Each business domain owns a folder under `src/services/` containing its routes, controllers, services, and repositories. Cross-cutting concerns live in `src/shared/` and `src/infrastructure/`. PostgreSQL + Drizzle ORM is the sole database layer as of v2.9.12 (Mongoose fully removed).

```
backend/
├── src/
│   ├── app.ts                  # Express bootstrap: middleware, routes, Socket.IO, startup
│   ├── config/                 # Sentry init (loaded before anything else)
│   ├── controllers/            # Thin HTTP controllers for orphan endpoints (disputes, points)
│   ├── routes/                 # Router exports for orphan controllers above
│   ├── models/                 # (removed — Mongoose models deleted; schemas now in src/db/schema/)
│   ├── db/                     # PostgreSQL + Drizzle ORM — SOLE database layer (19 migrations, 32 tables)
│   │   ├── schema/             # Drizzle table definitions (single source of truth for data)
│   │   ├── migrations/         # SQL migration files (0000–0019)
│   │   └── repositories/       # Drizzle-backed repository implementations
│   ├── infrastructure/
│   │   ├── database/           # (removed — Mongoose connection code deleted)
│   │   └── socket/             # Socket.IO server adapter & emitter helpers
│   ├── services/               # Domain services — see breakdown below
│   ├── shared/
│   │   ├── config/             # Typed `config` object (env loader)
│   │   ├── middleware/         # auth, errorHandler, rate limit, request logger
│   │   ├── types/              # Cross-domain type aliases
│   │   └── utils/              # Helpers reused across services
│   ├── utils/                  # logger, currencyUtils, videoHelpers
│   ├── seeds/                  # Idempotent data seeders
│   └── scripts/                # One-off operational scripts (TS + sh)
├── __tests__/                  # Jest suites (see Testing)
├── scripts/                    # Shell scripts (build/push, version, ngrok, reset)
├── nginx/                      # Nginx conf (production compose)
├── uploads/                    # User uploads — mounted as volume
├── Dockerfile.dev              # Hot-reload image (ts-node + nodemon)
├── Dockerfile.prod             # Multi-stage build image (compiled JS, non-root user)
├── docker-compose.dev.yml      # Local stack: backend + postgres + redis
├── docker-compose.production.yml # Prod stack: nginx + backend + frontend + postgres + redis
├── .gitea/workflows/           # Gitea Actions CI
├── healthcheck.js              # Container HEALTHCHECK probe
├── eslint.config.js            # Flat ESLint config (TS strict)
├── jest.config.js              # ts-jest preset
└── package.json
```

### `src/services/` folders

Each service folder follows the same shape: `<service>Routes.ts`, `<service>Controller.ts`, `<service>Service.ts`, sometimes a `<service>Repository.ts` and an `index.ts` barrel.

| Folder | Purpose |
|--------|---------|
| `address/` | CRUD for buyer/seller addresses (max 3 per user) |
| `admin/` | Admin-only data-cleanup + diagnostic endpoints |
| `ai/` | OpenAI-backed assistants (offer suggestions, content moderation) |
| `auth/` | Login, signup, refresh, Google OAuth, passkey/WebAuthn, temp verification |
| `blockchain/` | Generic wallet/chain helpers shared by payment providers |
| `blog/` | Public blog posts, comments, video helpers |
| `chat/` | Realtime messaging between buyers & sellers |
| `delivery/` | Delivery tracking + shipping events |
| `dispute/` | Dispute opening, evidence upload, arbitration |
| `email/` | Nodemailer service + transactional templates |
| `file/` | Multer uploads + Sharp image processing |
| `marketplace/` | Purchase requests, seller offers, accept/reject, categories |
| `notification/` | In-app notifications + delivery (socket + email) |
| `payment/` | Payment orchestration; sub-folders `shkeeper/`, `depay/`, `web3/` |
| `points/` | Reputation points + level config |
| `redis/` | Redis client wrapper (caching, rate counters) |
| `user/` | Profile, settings, role management |

### `src/models/` (removed)

This directory no longer exists. All Mongoose models have been deleted. Data schemas are now defined as Drizzle table objects in `src/db/schema/`. See [[Data Models]] for the current PostgreSQL schema docs.

### `src/db/`

PostgreSQL + Drizzle ORM — the **sole** database layer (no Mongoose, no dual-write, no Mongo fallback). Highlights:

- `schema/` — Drizzle table definitions covering all 32 tables across 19 migrations (0000–0019)
- `migrations/` — SQL migration files applied via `drizzle-kit`
- `repositories/` — Drizzle-backed repository implementations returned exclusively by the repository factory
- All domain stores use `PG_URL` (required); `MONGO_URI` / `MONGODB_URI` / `MONGO_CONNECT_MODE` are obsolete
- IDs are PostgreSQL UUIDs (`.id` string field); `legacy_object_id` column preserves the original MongoDB ObjectId for `User` only

### `src/seeds/`

Idempotent, runnable via `npm run seed:*`. See [[Scripts#seed-scripts]].

---

## Frontend — `/Users/mojtabaheidari/code/frontend`

Next.js 16 App Router with the `src/` layout. The structure follows the Minimal v7 template: pages in `app/`, page-level UI in `sections/`, reusable atoms in `components/`, and a strong split between server data fetchers (`actions/`) and client UI.

```
frontend/
├── src/
│   ├── app/                    # Next.js App Router — route groups: (auth) (dashboard) post shop
│   │   ├── layout.tsx          # Root layout (providers, font, metadata)
│   │   ├── page.tsx            # Landing page
│   │   ├── auth/               # /auth/* routes
│   │   ├── dashboard/          # /dashboard/* routes (authenticated)
│   │   ├── post/               # Public blog posts
│   │   ├── shop/               # Public shop pages
│   │   ├── error/              # Custom error route
│   │   ├── loading.tsx         # Global loading skeleton
│   │   └── not-found.tsx       # 404
│   ├── sections/               # Page-level UI grouped by domain
│   │   ├── account/ address/ blog/ chat/ dispute/ error/
│   │   ├── overview/ payment/ points/
│   │   ├── request/ request-template/ shop-settings/ user/
│   ├── components/             # Reusable UI atoms & molecules (MUI-based)
│   │   ├── hook-form/          # RHF-wrapped MUI inputs (RHFTextField, RHFSelect, …)
│   │   ├── iconify/            # The single icon component (use only this)
│   │   ├── animate/ carousel/ chart/ custom-* / nav-section/
│   │   ├── upload/ file/ image/ markdown/ editor/ map/ video-player/
│   │   └── …                   # see full list in the codebase
│   ├── contexts/               # Top-level React contexts (socket-context.tsx)
│   ├── hooks/                  # Generic hooks: useBoolean, useSetState, useSnackbar, useSocket
│   ├── lib/                    # axios.ts — singleton API client with interceptors
│   ├── locales/                # i18n: langs/, i18n-provider, server.ts, use-locales
│   ├── layouts/                # AppShell variants: auth-centered, auth-split, dashboard, main, simple
│   ├── theme/                  # MUI theme (core + with-settings overrides)
│   ├── settings/               # Theme-switcher drawer + persisted user settings
│   ├── actions/                # Server-side / shared async API calls (axios)
│   ├── auth/                   # JWT / OAuth / passkey context, guards, hooks, services
│   ├── socket/                 # Socket.IO client, hooks, components, contexts
│   ├── web3/                   # WalletConnect + Alchemy + Request Network checkout glue
│   ├── routes/                 # Static path constants (paths object)
│   ├── utils/                  # logger, format-number, format-time, localStorage, …
│   ├── types/                  # Shared TS types (mirrors backend models where useful)
│   ├── assets/                 # SVGs, illustrations
│   ├── _mock/                  # Mock data for storybooks / tests
│   ├── global-config.ts        # Read-only app config (name, version, paths)
│   └── global.css              # Tailwind-less global styles
├── public/                     # Static assets served at /
├── e2e/                        # Playwright specs
├── __tests__/                  # Jest + RTL specs (organised by domain)
├── scripts/                    # Shell scripts (deploy, debug, version, console-log migration)
├── docs/                       # In-repo design notes (not the Obsidian vault)
├── doc/                        # Legacy docs folder
├── Dockerfile                  # Production multi-stage Next.js build
├── Dockerfile.dev              # Dev image (yarn dev on port 3000)
├── next.config.ts              # Standalone output, image domains, Sentry integration
├── playwright.config.ts        # E2E test config
├── jest.config.js              # Jest + jsdom + RTL
├── eslint.config.mjs           # Flat ESLint with perfectionist sorting
├── prettier.config.mjs         # Prettier config
├── .commitlintrc.json          # Conventional commits enforcement
├── sentry.client.config.ts     # Browser Sentry init
├── sentry.server.config.ts     # Server runtime Sentry init
└── sentry.edge.config.ts       # Edge runtime Sentry init
```

### `src/sections/` vs `src/components/`

A common confusion when first navigating the codebase:

- **components/** — generic, reused everywhere, no business logic. (e.g. `Iconify`, `RHFTextField`, `EmptyContent`.)
- **sections/** — page-level UI bound to a domain. (e.g. `sections/payment/CheckoutSummary.tsx`.) Sections may import from `components/` but not the other way around.

### `src/auth/` vs `src/socket/` vs `src/web3/`

These are feature-bundles that ship their own context, hooks, services, and components together. Treat each like an internal package — import only from its `index.ts` barrel.

### Routes & API

- `routes/paths.ts` — every URL the app navigates to, expressed as a typed object.
- `lib/axios.ts` — the single axios instance with auth interceptor and base URL from `NEXT_PUBLIC_API_URL`.
- `actions/*.ts` — async functions wrapping axios calls; consumed by both server components and client components.

---

## Repository layout (top-level)

```
~/code/
├── backend/        # this repo
├── frontend/       # this repo
└── docs/           # this Obsidian vault
```

The production `docker-compose.yml` lives in `backend/` but references `../frontend` for the frontend build context — keep both folders as siblings.

---

## Where to add new things

| You want to add… | Put it under… |
|---|---|
| A new public API route | `backend/src/services/<domain>/<domain>Routes.ts` (or a new domain folder) |
| A new database table | `backend/src/db/schema/<name>.ts` (Drizzle) + add a migration via `drizzle-kit generate` |
| A reusable UI component | `frontend/src/components/<kebab-name>/` with `index.ts` + `component.tsx` + `types.ts` |
| A page-specific block | `frontend/src/sections/<domain>/` |
| A new dashboard page | `frontend/src/app/dashboard/<route>/page.tsx` |
| A shared hook | `frontend/src/hooks/use-<name>.ts` |
| A one-shot ops script | `backend/scripts/<name>.sh` (operational) or `backend/src/scripts/<name>.ts` (touches DB) |
| A seed script | `backend/src/seeds/<name>.ts` and add an `npm run seed:<name>` entry |

For the architectural rationale behind these splits see [[Backend Architecture]] and [[Frontend Architecture]].
