--- 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: `Routes.ts`, `Controller.ts`, `Service.ts`, sometimes a `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//Routes.ts` (or a new domain folder) | | A new database table | `backend/src/db/schema/.ts` (Drizzle) + add a migration via `drizzle-kit generate` | | A reusable UI component | `frontend/src/components//` with `index.ts` + `component.tsx` + `types.ts` | | A page-specific block | `frontend/src/sections//` | | A new dashboard page | `frontend/src/app/dashboard//page.tsx` | | A shared hook | `frontend/src/hooks/use-.ts` | | A one-shot ops script | `backend/scripts/.sh` (operational) or `backend/src/scripts/.ts` (touches DB) | | A seed script | `backend/src/seeds/.ts` and add an `npm run seed:` entry | For the architectural rationale behind these splits see [[Backend Architecture]] and [[Frontend Architecture]].