# Contributing to Petdex ## Three paths for local dev Pick the one that matches what you want to change. | Goal | Command | Setup | |---|---|---| | Tweak UI / copy / i18n / CSS | `bun run dev:mock` | 0 credentials | | Test DB queries / auth / submit / likes | `bun run dev:docker` | Docker Desktop or Podman, ~30s | | Run against real petdex services | `bun run dev` | `.env.local` filled in (maintainers only) | `dev:docker` is the new recommended path for almost everyone. It boots a real Postgres + Redis + Clerk dev instance so the app behaves the same way it does in production, without any of the in-process shims that `dev:mock` ships. ## bun run dev:mock Zero credentials, zero containers, in-process Postgres (PGlite) and a stubbed Clerk session. Slower HMR, no real auth, but boots in 5 seconds. ```bash bun install bun run dev:mock ``` Open . You're auto-signed in as `contributor@petdex.local`. What works: gallery, pet detail pages, search, the `/u/` profile dashboard, status badges. Sign-in flows are bypassed and the DB is in-memory. What does NOT work: real OAuth, real R2 uploads, outbound emails, the auto-tag and pet-sound jobs (need API keys). If your change touches any of those, use `dev:docker` instead. ## bun run dev:docker Real Postgres, real Redis, real Clerk OAuth. Same stack as production but pointed at a shared OSS dev instance and local containers. ```bash bun install bun run dev:docker ``` That single command will: 1. Detect `docker compose` or `podman compose` (works with either) 2. Boot Postgres 16 + Redis 7 + a Redis-over-HTTP shim on `127.0.0.1` 3. Push the drizzle schema with `drizzle-kit push --force` 4. Seed ~20 approved pets so the gallery is not empty 5. Launch `next dev` (turbopack) on Sign in with GitHub or Google through Clerk. The publishable key for the shared "Petdex OSS Dev" Clerk app is committed in `.env.dev` so contributors don't need their own Clerk account. When you're done: `bun run docker:down` to stop the containers. `bun run docker:nuke` if you want to wipe the database too. ### Engine compatibility `docker-compose.dev.yml` is engine-agnostic. The wrapper script probes `docker compose` first and falls back to `podman compose`, so: ```bash docker compose -f docker-compose.dev.yml up -d podman compose -f docker-compose.dev.yml up -d ``` Both work without editing the file. ### What works in docker mode - Real Clerk sign-in (GitHub, Google, email magic link) - Real Postgres planner. Bugs that only repro in production stop hiding behind in-memory quirks. - Rate limits actually rate-limit (Upstash REST + local Redis) - Real schema migrations via drizzle-kit - Likes, profile edits, pinned reorder, collections, takedowns ### What does NOT work in docker mode (yet) - R2 uploads: without R2 credentials, presign returns a non-routable host so an accidental upload errors out fast. Set `R2_*` in your own `.env.local` if you actually want to test uploads against a bucket. - Outbound emails: `RESEND_API_KEY` is empty, so notification emails are skipped. In-app notifications still fire. - AI features (auto-tag, vibe search, pet sound): these need `OPENAI_API_KEY` / `ELEVENLABS_API_KEY` in your `.env.local`. ### Becoming a dev admin Some routes (`/admin`, takedown, manual approval) require your Clerk user id to be in `PETDEX_ADMIN_USER_IDS`. After signing in: 1. Open while signed in 2. Open browser devtools → Application → Cookies and find `__session`. Your Clerk user id is in the JWT payload, prefixed `user_`. Or copy it from the dashboard at . 3. Add it to your `.env.local`: ``` PETDEX_ADMIN_USER_IDS=user_xxxxxxxxxxxxxxxxxxxxxxxx NEXT_PUBLIC_PETDEX_ADMIN_USER_IDS=user_xxxxxxxxxxxxxxxxxxxxxxxx ``` 4. Restart `bun run dev:docker`. ## bun run dev (full real services) For maintainers who have credentials for the production-grade staging stack. Copy `.env.example` to `.env.local`, fill in the values, run `bun dev`. No containers, no Clerk dev shim, no seed. ## Conventions - **Runtime**: Bun (never `npm install`). - **Lint/format**: `bun run check` / `bun run format` (Biome). - **Tests**: `bun test`. DB-backed search integration tests are explicit: `DATABASE_URL=... bun run test:db`. - **Commit style**: conventional commits (`feat:`, `fix:`, `docs:`, etc.). ## Where to look - UI: `src/components/`, `src/app/[locale]/` - API routes: `src/app/api/` - DB schema: `src/lib/db/schema.ts` - i18n strings: `src/i18n/messages/` - Docker compose: `docker-compose.dev.yml` - Dev seed: `scripts/seed-dev.ts`