Files
nick-doc/07 - Development/Project Structure.md
2026-05-23 20:35:34 +03:30

201 lines
11 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 (sometimes) its own models. Cross-cutting concerns live in `src/shared/` and `src/infrastructure/`.
```
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/ # Mongoose schemas (single source of truth for data)
│ ├── infrastructure/
│ │ ├── database/ # Mongo connection + admin bootstrap
│ │ └── 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)
├── mongo-init/ # Mongo initdb.d JS (one-time bootstrap)
├── 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 + mongo + redis
├── docker-compose.production.yml # Prod stack: nginx + backend + frontend + mongo + 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/`
Each `.ts` file is a Mongoose model — see [[Data Models]] for full schema docs. Highlights:
- `User`, `Address`, `Category` — identity & taxonomy
- `PurchaseRequest`, `SellerOffer`, `RequestTemplate` — marketplace core
- `Payment`, `PointTransaction`, `LevelConfig` — money + reputation
- `Chat`, `Notification`, `Dispute`, `Review`, `BlogPost`, `ShopSettings`, `TempVerification` — supporting domains
### `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 + DePay 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 Mongo schema | `backend/src/models/<Name>.ts` + export from `models/index.ts` |
| 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]].