209 lines
12 KiB
Markdown
209 lines
12 KiB
Markdown
---
|
||
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]].
|