Quick Start: From Clone to Running in 5 Minutes
This is the fastest path from a fresh clone to a running Agency site with EN/FR/ES seeded content. If you prefer a deeper dive, read Architecture first, then come back.
Prerequisites
| Tool | Why | How to check |
|---|---|---|
| Docker 24+ with Compose v2 | Runs the full stack (Next.js, Directus, Postgres, Redis) | docker --version && docker compose version |
| Node.js 20+ | Frontend dev server and tooling | node --version |
| npm | Frontend package manager (the frontend uses plain npm, not pnpm) | npm --version |
| Git | Clone the repo | git --version |
You do not need Postgres, Redis, or Directus installed locally: they run in containers.
Step 1: Clone and configure
git clone <your-fork-url> saasforge-agency
cd saasforge-agency
cp .env.example .env
Open .env and change at minimum:
DIRECTUS_ADMIN_EMAIL/DIRECTUS_ADMIN_PASSWORD: your admin login.POSTGRES_PASSWORD: database password.DIRECTUS_KEYandDIRECTUS_SECRET: generate random UUIDs (uuidgenon macOS/Linux).
Local dev works with the defaults. Never ship the defaults to production.
Step 2: Boot the CMS stack
docker compose up -d --build
What happens on first boot:
- Postgres + Redis start and pass healthchecks.
- Directus builds from a custom Dockerfile that vendors
@directus-labs/seo-plugin. - A one-shot
directus-initsidecar runsbootstrap.mjs(creates 18 collections, fields, relations, permissions, and theen/fr/eslanguage rows), thenseed.mjs(fills every collection with EN/FR/ES content). - The sidecar exits; Directus keeps running.
Watch the init output:
docker compose logs -f directus-init
When you see Seed complete the CMS is ready. Log into the admin at http://localhost:8055.
Step 3: Boot the frontend
cd frontend
npm install
cp .env.local.example .env.local # if present, otherwise create it
Create frontend/.env.local with:
NEXT_PUBLIC_DIRECTUS_URL=http://localhost:8055
NEXT_PUBLIC_SITE_URL=http://localhost:3000
NEXT_PUBLIC_DEFAULT_LOCALE=en
No token needed: the Directus Public role has read access on every content collection.
Start the dev server:
npm run dev
Open http://localhost:3000 → English homepage.
/fr → French. /es → Spanish.
Step 4: Verify the loop works
- In Directus admin, open Marketing → Services and edit the first service's English title.
- Save.
- Wait up to 60 seconds (Next.js cache revalidation window) and refresh the frontend.
- Your edit appears without a rebuild.
If it does: your stack is wired correctly end-to-end.
Common first-run issues
| Symptom | Fix |
|---|---|
directus-init exits with ECONNREFUSED | Directus wasn't healthy yet. docker compose up -d directus-init re-runs it. |
| Frontend shows fallback copy on every page | NEXT_PUBLIC_DIRECTUS_URL is wrong or Directus isn't reachable from the host. Check curl http://localhost:8055/server/health. |
| Collections exist but are empty | seed.mjs didn't run. Re-run it: docker compose run --rm directus-init. |
| CORS errors in the browser | Set CORS_ORIGIN=http://localhost:3000 in .env, recreate Directus. |
| Ports 3000 / 8055 / 5432 busy | Stop the conflicting process, or change the port mappings in docker-compose.yml. |
What to do next
- UI Components: customize the look without rewriting the design system.
- Content Management: edit copy like a non-developer would.
- Working with Directus: add fields, new collections, or extensions.
- Hosting & Deployment: ship to production.