--- title: Local Setup tags: [development] --- # Local Setup This guide walks you through running both repositories of the marketplace stack on your workstation. The platform is split into two services: - **Backend** — Node.js 22+ / Express 5 / PostgreSQL 16 / Redis 8 / Socket.IO, served on port `5001`. - **Frontend** — Next.js 16 / React 19 / MUI v7, served on port `8083` (or `3000` in Docker dev). By the end of this page you will have the API running locally with PostgreSQL + Redis containers, a seeded set of test accounts, and the Next.js dashboard talking to it through your browser. For ongoing reference see [[Environment Variables]], [[Project Structure]], and [[Scripts]]. --- ## 1. Prerequisites Install the following before you start: | Tool | Version | Why | |------|---------|-----| | Node.js | `>= 22` (backend), `>= 20` (frontend) | Runtime | | Yarn | `1.22.22` (Classic) | Pinned via `packageManager` field | | Docker Desktop | latest | Runs PostgreSQL + Redis + (optionally) backend/frontend | | Git | `>= 2.40` | SSH-based clone from Gitea | | OpenSSL | system default | For generating local secrets | | `ngrok` (optional) | latest | For webhook testing — see [[Scripts#start-ngrok-sh]] | > [!tip] Use a single Node version manager (`nvm`, `fnm`, or `volta`) and pin to `22`. Yarn Classic is required — do **not** upgrade to Berry, the lockfiles are incompatible. You also need an SSH key registered with Gitea. The Git server runs on a non-standard port (`222`), so add an entry to `~/.ssh/config`: ```ssh Host git.manko.yoga HostName git.manko.yoga Port 222 User git IdentityFile ~/.ssh/id_ed25519 ``` Verify connectivity: ```bash ssh -T git@git.manko.yoga -p 222 ``` You should see a Gitea welcome line. If you see "Permission denied (publickey)", upload your public key to your Gitea profile first. --- ## 2. Clone the repos The two repos are siblings — keep them next to each other (the production compose file references `../frontend` from the backend folder): ```bash mkdir -p ~/code && cd ~/code git clone ssh://git@git.manko.yoga:222/nick/backend.git git clone ssh://git@git.manko.yoga:222/nick/frontend.git ``` Switch each repo to the active integration branch for the stack you are testing. As of 2026-05-31, the dev stack work is on `integrate-main-into-development`: ```bash cd ~/code/backend && git checkout integrate-main-into-development cd ~/code/frontend && git checkout integrate-main-into-development ``` > [!warning] `main`/`master` is the production branch and is consumed by the Watchtower auto-update flow. Never push WIP commits there. See [[Git Workflow]]. --- ## 3. Install dependencies Backend uses **npm** for scripts but `yarn install` for lockfile parity with Docker, while the frontend is pure Yarn: ```bash # Backend cd ~/code/backend yarn install --frozen-lockfile # Frontend cd ~/code/frontend yarn install --frozen-lockfile ``` Both installs take 2–5 minutes on a cold cache. If `node-gyp`/`sharp` fail on macOS, install Xcode CLT (`xcode-select --install`). --- ## 4. Configure `.env` files Each repo ships example files. Copy them and fill in secrets — full reference is in [[Environment Variables]]. ### Backend (`/Users/mojtabaheidari/code/backend/.env.local`) `docker-compose.dev.yml` reads `.env.local`. The container expects at minimum: ```bash NODE_ENV=development PORT=5001 PG_URL=postgresql://postgres:postgres@postgres:5432/marketplace REDIS_URI=redis://redis:6379 JWT_SECRET=$(openssl rand -hex 32) JWT_EXPIRES_IN=1h REFRESH_TOKEN_EXPIRES_IN=30d FRONTEND_URL=http://localhost:8083 MAX_FILE_SIZE=10485760 UPLOAD_PATH=/app/uploads RATE_LIMIT_WINDOW_MS=900000 RATE_LIMIT_MAX_REQUESTS=100 ``` > [!note] `MONGODB_URI` / `MONGO_URI` / `MONGO_CONNECT_MODE` are **no longer used**. MongoDB has been fully removed from the backend runtime (v2.9.12+). The only database layer is PostgreSQL + Drizzle ORM. `PG_URL` is required. For payments, OpenAI, SMTP, etc., refer to [[Environment Variables]]. ### Frontend Three env files already exist; pick the one that matches your scenario: | File | When to use | |------|-------------| | `.env.local` | Local Next dev (`yarn dev`) — points at `http://localhost:5001` | | `.env.development` | Docker compose dev — points at `dev.amn.gg` via Nginx | | `.env.production` | Production build — points at `amn.gg` | Next.js automatically picks `.env.local` for `next dev`. Do **not** check this file in if you change secrets. --- ## 5. Start the backend You have two equivalent paths. ### Option A — All-in-Docker (recommended) Builds the backend image, brings up PostgreSQL + Redis + backend on `nickapp-network`, and mounts `./src` for hot reload: ```bash cd ~/code/backend npm run docker:dev ``` Follow logs: ```bash npm run docker:dev:logs ``` Stop: ```bash npm run docker:dev:down ``` ### Option B — Local Node + Docker datastores Run only the datastores in Docker and the API on the host: ```bash cd ~/code/backend docker compose -f docker-compose.dev.yml up -d postgres redis npm run dev # ts-node + nodemon on port 5001 ``` Override `PG_URL=postgresql://postgres:postgres@localhost:5432/marketplace` in `.env` if you take this route, since `postgres` only resolves inside the compose network. > [!tip] If port `5001` is already in use, set `PORT=5002` in `.env.local` and update `NEXT_PUBLIC_API_URL` in the frontend env to match. --- ## 5a. Apply database migrations After starting the PostgreSQL container (and before seeding), apply all Drizzle migrations to create the 32-table schema: ```bash cd ~/code/backend npx drizzle-kit migrate ``` This runs the 19 migration files (0000–0019) and brings the database schema up to date. You only need to run this once on a fresh database, or after pulling commits that include new migration files. > [!note] If you are using Option A (All-in-Docker), run this from the host after the `postgres` container is healthy but before the backend service connects. --- ## 6. Seed test data Once PostgreSQL is healthy and migrations have been applied, populate it with default users, categories, addresses, and templates: ```bash cd ~/code/backend npm run seed:all # users + addresses (clears existing) npm run seed:categories # marketplace taxonomy ``` `seed:all` creates the canonical test accounts (password `Moji6364` for all): | Role | Email | |------|-------| | Admin | `admin@marketplace.com` | | Buyer | `buyer@marketplace.com` | | Seller | `seller@marketplace.com` | | Seller (alt) | `seller2@marketplace.com` | You can also enable auto-seeding on container start by adding `AUTO_SEED_ON_START=true` to `.env.local`. Auto-seed runs only when the `users` table has no non-admin entries — safe to leave on. See [[Scripts#seed-scripts]] for the full list (`seed:users`, `seed:addresses`, `seed:categories`, `seed:all`, plus `createSupportUser.ts`, `createTestRequest.ts`, etc.). --- ## 7. Start the frontend ```bash cd ~/code/frontend yarn dev ``` Next.js starts on **port 8083** (`next dev -p 8083 --turbopack`). The dashboard is at: - http://localhost:8083 — landing - http://localhost:8083/auth/jwt/sign-in — login - http://localhost:8083/dashboard — authenticated area If you used the Docker compose dev workflow with the production-mode container, port `3000` may also be exposed; check the compose output. --- ## 8. Verify Run these smoke checks before you start coding: ```bash # Backend health (should return JSON with success: true) curl -s http://localhost:5001/health | jq . # API root curl -s http://localhost:5001/ | jq . # Login (returns JWT) curl -s -X POST http://localhost:5001/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@marketplace.com","password":"Moji6364"}' | jq . ``` In the browser, open http://localhost:8083, log in with `admin@marketplace.com / Moji6364`, and confirm the dashboard loads. If chat or notification badges show up, sockets connected too. > [!tip] Tail backend logs in a separate terminal: `npm run docker:dev:logs`. Look for `Connected to PostgreSQL`, `User connected`, and `Server running on port 5001`. --- ## 9. Common issues | Symptom | Fix | |---------|-----| | `EADDRINUSE :::5001` | Another process owns the port — `lsof -i :5001` then `kill`, or change `PORT`. | | `ECONNREFUSED 127.0.0.1:5432` | PostgreSQL container is down — `docker compose -f docker-compose.dev.yml ps` to check. | | `ECONNREFUSED 127.0.0.1:6379` | Redis container is down — `docker compose -f docker-compose.dev.yml ps` to check. | | `relation "users" does not exist` | Migrations have not been applied — run `npx drizzle-kit migrate` from the backend folder. | | CORS errors in the browser | `FRONTEND_URL` in backend `.env.local` must exactly match the origin you open in the browser (scheme + host + port). | | `yarn install` hangs on `sharp` | Run `yarn config set network-timeout 600000` and retry. | | `next dev` fails with module-not-found after a `git pull` | Run `yarn install` again — Next 16 is sensitive to drift in `react`/`react-dom`. | | Sockets do not connect | Confirm `NEXT_PUBLIC_SOCKET_URL` matches the backend origin and that no browser extension blocks WebSockets. | --- ## 10. Quick reset If your local state gets weird, the backend ships a one-shot reset script: ```bash cd ~/code/backend ./scripts/reset-server.sh ``` This stops the dev compose stack, restarts it, runs health checks against PostgreSQL / Redis / `/health`, and probes the login endpoint with the seeded admin user. Output is colourised and ends with the canonical test credentials. See [[Scripts#reset-server-sh]] for details. > [!warning] `reset-server.sh` does **not** drop volumes by default. To wipe the database, uncomment the `down -v` line in the script or run `docker compose -f docker-compose.dev.yml down -v` first. You will need to re-run `npx drizzle-kit migrate` and `npm run seed:all` after a volume wipe. --- ## Next steps - Walk the codebase via [[Project Structure]]. - Read [[Coding Standards]] before opening your first PR. - Run the test suites — [[Testing]]. - Inspect what runs in each container — [[Docker Setup]] (Operations). - For shipping changes through CI, see [[CI-CD Pipeline]] (Operations).