2026-08-23 23:14:57 +02:00
fix
2026-08-23 23:14:57 +02:00
fix
2026-08-23 23:14:57 +02:00
fix
2026-08-23 20:49:40 +02:00
fix
2026-08-17 21:20:45 +02:00
fix
2026-08-23 20:49:40 +02:00
fix
2026-08-13 21:38:42 +02:00

Descrybe v2

Go API + SvelteKit frontend + PostgreSQL rewrite of Descrybe (no Clerk).

Stack

  • API: Go, chi, pgx, sqlc, goose, River jobs
  • Web: SvelteKit 2, Svelte 5, Tailwind
  • DB: PostgreSQL 16
  • Migrator: MySQL → Postgres ETL with Clerk ID remapping

Local setup (any OS)

Docker Compose runs Postgres only (host :5433). API, web, and worker run on the host via npm run setup + npm run dev (fast reload; no Laragon/XAMPP required). OS-specific Docker notes: docs/docker.md. Ports match docker-compose.yml + scripts/dev-ports.mjs.

After the stack is up: operator path (login → feed → process → export) → docs/getting-started.md.

npm run setup        # .env (if missing) + docker Postgres :5433 + goose migrate
npm install && npm run dev   # API :28471 + web :28472 + worker (needed for /readyz + jobs)

Same on Windows PowerShell, macOS, and Linux (Node scripts; Docker Desktop or Engine + Compose v2). Equivalents: make setup then make targets / npm run ….

Optional: npm run seed (demo login) · npm run health (/healthz + /readyz).

Prerequisites

Tool Version / notes
Docker Docker Engine + Compose v2 (docker compose) — Postgres only on :5433
Node.js ≥ 20 (package.json engines.node)
Go 1.25.0 (apps/api/go.mod)
sqlc (optional) On PATH for migrate regen; scripts fall back to go run …/sqlc if missing
Make (optional) make setup / make up / make migrate — macOS/Linux/WSL; Windows can use npm run …

Local ports (canonical)

Service Host
Postgres localhost:5433 → container 5432 (postgres:16-alpine)
API http://localhost:28471 (HTTP_ADDR=:28471)
Web http://localhost:28472 (Vite strictPort; proxies /api, /healthz, /readyz)

Do not use older docs that mention :8080 / :5174 for day-to-day npm run dev.

Environment (one file)

Use a single root .env (copy from .env.example). Do not create apps/api/.env. npm run setup creates .env from the example and fills empty TOKEN_SIGNING_SECRET / APP_ENCRYPTION_KEY with local random hex (never commit .env).

Variable Local default / note
DATABASE_URL postgres://descrybe:descrybe@localhost:5433/descrybe?sslmode=disable (matches docker-compose.yml)
HTTP_ADDR :28471
WEB_ORIGIN http://localhost:28472
PUBLIC_API_URL http://localhost:28471
APP_ENV development
SESSION_SECURE false locally; true in production
TOKEN_SIGNING_SECRET openssl rand -hex 32 (or let npm run setup generate)
APP_ENCRYPTION_KEY Prefer this for at-rest secrets (CREDENTIALS_ENCRYPTION_KEY is legacy). Same generate rule

Leave OpenAI, Stripe, EPREL, marketing mail, Woo, and Shopify out of .env for day-to-day setup. Configure them in the app after login:

Integration Where
AI (OpenAI-compatible / BYOK) /integrations/ai (tenant) and/or /admin/settings (platform)
Stripe, EPREL, feed private-URL allowlist /admin/settings (GET/PUT /api/admin/settingsvalues.*; env optional fallback)
Marketing email (Resend / SMTP) /integrations/email
Stores (Woo / Shopify / feeds) /stores

Platform set-password / invite SMTP may still use process SMTP_* when you enable live invite mail (see docs/ops-runtime.md). Session/encryption fail-closed rules are in .env.example and docs/production-checklist.md. Production does not require Stripe secrets at boot.

The API/worker load the monorepo-root .env automatically (apps/api/internal/config loadDotEnv).

Manual steps (if you skip npm run setup)

docker-compose.yml defines only Postgres (descrybe-v2-postgres, user/db/password descrybe, volume descrybe_v2_pg, pg_isready healthcheck). OS-specific Docker Desktop / Engine notes: docs/docker.md.

cp .env.example .env          # PowerShell: Copy-Item .env.example .env
docker compose up -d          # or: npm run db:up / make up
npm run migrate               # goose up + sqlc (loads root .env)
npm install && npm run dev

Migrate wrappers: bash scripts/migrate.sh · .\scripts\migrate.ps1 · make migrate (all call scripts/migrate.mjs).

Worker and /readyz

npm run dev starts API + web + worker. Processing jobs and GET /readyz need that worker heartbeat (stale after 60s).

Script What runs
npm run dev / npm run dev:app api + web + worker
npm run dev:backend / make backend api + worker (no web; enough for /readyz)
npm run dev:api api only → /readyz 503 until a worker is started
npm run dev:worker worker only
make worker / .\scripts\run-api.ps1 worker worker only

Verify

npm run health
# or:
curl -sS http://127.0.0.1:28471/healthz
curl -sS http://127.0.0.1:28471/readyz

Open the app: http://localhost:28472. Demo seed: npm run seed.

Split processes (optional)

npm run dev:web      # web only
npm run dev:api      # API only (readyz 503 without worker)
npm run dev:worker   # worker only
npm run dev:backend  # api + worker
npm run dev:ps1      # PowerShell: api + web + worker

OS notes

  • Windows / macOS / Linux Docker details (Desktop vs Engine, WSL2, ports): docs/docker.md.
  • Windows: Docker Desktop running; use npm run setup / npm run migrate / npm run seed (Node) — no Git Bash required. Optional: .\scripts\migrate.ps1, .\scripts\dev.ps1.
  • macOS / Linux: same npm commands; make setup / make migrate work if Make is installed.
  • WSL2: Docker Desktop WSL integration or Linux engine; keep DATABASE_URL on localhost:5433 from the same environment as the API.

Troubleshooting: /readyz returns 503

GET /healthz = process liveness. GET /readyz = Postgres ping and a fresh worker heartbeat (worker_id=processing, stale after 60s). On worker failure the JSON keeps a short error and adds operator reason (how to start the host worker). See also docs/ops-runtime.md and docs/production-checklist.md.

Symptom Meaning Fix
/healthz 200, /readyz 503, checks.worker = missing, error worker heartbeat missing API up, worker never started (or migrations before 039_worker_heartbeats) Use npm run dev (includes worker), or npm run dev:worker / make worker; ensure goose is up through 039. Read JSON reason.
/readyz 503, checks.worker = stale, error worker heartbeat stale Worker was up but heartbeat older than 60s Restart the worker; confirm it stays running. Read JSON reason.
/readyz 503, checks.database = fail / unavailable DB down or bad DATABASE_URL docker compose ps, fix URL (host 5433), re-run migrate
/readyz still 503 after starting worker Heartbeat table missing or wrong DB Re-run migrate; confirm worker and API share the same DATABASE_URL

Expected: API-only local (cmd/api without cmd/worker, or npm run dev:api) → /readyz 503. That is not a broken API binary — start the worker (npm run dev, npm run dev:backend, or npm run dev:worker) before treating readiness as green. Jobs on /processing also need the worker. Compose does not start the worker (Postgres only).

Routes

Path Purpose
/ Public marketing homepage (sell copy, FAQ, pricing teaser; no app shell)
/pricing Public marketing pricing (Free→Enterprise; no client deals)
/features Optional features deep-dive (not primary nav)
/privacy, /terms Legal pages
/login, /register Auth (login success → /dashboard)
/dashboard App home (sidebar shell)
/plans In-app plans (authenticated)
/standard-fields, /feeds, /feeds/{id}/mapping Catalog ingest + mapping
/products, /processing Catalog + background process jobs
/export-feeds Outbound CSV/XML templates + generate
/stores, /stores/shopify Store connectors hub (Woo, Shopify sibling, feed URL, CSV)
/campaigns, /seo, /brand, /marketing/calendar Marketing suite
/reviews Alias to WooCommerce Reviews tab
/admin/* Platform admin

Demo login (migrated staging data)

Alias demo@descrybe.test is also seeded. Platform admin + admin of Platform Demo only (not A1). Default session company: Platform Demo. Act for A1 via Admin → Users → Switch to user (a1-primary@descrybe.local). Details: docs/demo-user.md, docs/safe-test-fixtures.md.

npm run seed
# or: node scripts/seed-local.mjs
# or: pwsh -File .\scripts\seed-local.ps1

Migrations

Prefer the cross-platform script (loads root .env):

npm run migrate
# equivalents: node scripts/migrate.mjs  |  make migrate  |  .\scripts\migrate.ps1

Manual:

cd apps/api
go run github.com/pressly/goose/v3/cmd/goose@v3.24.3 -dir sql/schema postgres "$DATABASE_URL" up
sqlc generate

Migrator

Live MySQL → staging Postgres load succeeded (2026-08-03); production cutover is still NO-GO until emails/roles/SMTP login are proven. Evidence: docs/migration-run-log.md.

cd apps/api
go run ./cmd/migrator -mysql "$MIGRATE_MYSQL_DSN" -postgres "$DATABASE_URL" -dry-run

Docs

S
Description
No description provided
Readme
55 MiB
Languages
TypeScript 39.9%
Go 36.3%
Svelte 14.7%
JavaScript 8.8%
CSS 0.1%