Documentation
Démarrage

Development Guide

Pour les développeurs

Everyday commands, the database lifecycle (schema changes, seed, reset, backups), the seeded accounts, tests and troubleshooting.

The rules behind these commands live in AGENTS.md; this page is the how-to.

First run

git clone https://github.com/krizaka/orochia.git && cd orochia
npm install
npm run setup        # .env + PostgreSQL 16 + migrations + seed
npm run dev          # http://localhost:3000

npm run setup is idempotent: run it again after pulling, or whenever the databases were stopped.

Clone the admin console and the design system next to this repository with npm run workspace -- clone, then npm run workspace -- status shows the three repositories at a glance.

AppDirectoryPortStart
Web app & APIorochia/3000npm run dev
Admin console../orochia-admin/3001OROCHIA_API_URL=http://localhost:3000 npm run dev -- -p 3001
Design system showcase../orochia-design-system/3002npm run dev

Accounts of the development seed

RoleE-mailPasswordNotes
Administratoradmin@orochia.orgadmin1234signs in to the admin console
Creatorelena@orochia.orgelena1234verified; public, paid and followers-only videos; payout in progress
Creatormia@orochia.orgmia1234verified; public, contacts-only and encoding videos
Creatornova@orochia.orgnova1234not verified — waits in the 2257 queue
Memberalex@sanctuary.ioalex1234approved follower of Elena, contact of Mia, two unlocks
Membersam@sanctuary.iosam1234pending follow of Elena, pending contact request to Mia

The database

PostgreSQL runs in the orochia-postgres-dev container (deploy/docker/docker-compose.dev.yml, data in a named Docker volume).

I want to…Command
start / stop the databasesnpm run db:up / npm run db:down
see applied and pending migrations, row countsnpm run db:status
browse and edit datanpm run db:studio (Drizzle Studio) or npm run db:psql
start over from a clean statenpm run db:reset -- --yes
keep a copy before an experimentnpm run db:dump → backups/orochia-<date>.sql
come back to that copynpm run db:restore -- backups/orochia-<date>.sql

db:reset, db:restore and db:psql work only on the local container: they refuse NODE_ENV=production and any DATABASE_URL that does not point at this machine.

Changing the schema

  1. Edit the tables in packages/db/src/schema/*.ts (and their relations in schema/index.ts).
  2. npm run db:generate -- --name short_description writes packages/db/drizzle/NNNN_short_description.sql.
  3. Read the SQL. Renames are generated as drop + add — rewrite them as ALTER … RENAME by hand when data must survive.
  4. npm run db:migrate, then npm run db:check.
  5. npm run docs:generate — docs/DATABASE.md follows the schema.
  6. Commit the schema, the migration and the docs together. Never edit a migration that was already applied anywhere.

The seed

packages/db/src/seed.ts builds a small, coherent platform that exercises every feature. It is idempotent (rows are keyed by e-mail, Bunny video id, gateway reference…), so npm run db:seed can run any time; it writes ledger rows exactly as settlement does (10 % platform fee) and refuses to run with NODE_ENV=production.

Tests

npm run check                    # lint + types + unit tests + generated docs up to date
npm run db:reset -- --yes        # the scenarios change data: start them from the seed
npm run test:e2e                 # needs the app running (npm run dev); OROCHIA_URL to target another one

Environment

One .env at the repository root (created by npm run setup from .env.example). Everything starts without any external account: the feed, profiles, followers, contacts, collections, comments, image stories and the seeded videos' pages work on the local database, files are stored on disk (STORAGE_DRIVER=local), e-mail is logged instead of sent, and with OROCHIA_DEMO_MODE=true unlocks settle immediately when no gateway is configured. In production every secret is mandatory (see Deployment).

Video features locally (Bunny Stream)

Uploading and playing videos, video stories and editor drafts need a Bunny Stream library — video never passes through the app. A free trial library is enough:

  1. Create a Stream library; in API, copy the library id, the API key and the Read-Only key; note the CDN hostname (vz-….b-cdn.net).
  2. In Security, turn on CDN token authentication (copy its key) and add localhost to the allowed domains.
  3. In Encoding, keep Keep original files on (drafts reopen from the original).
  4. Fill BUNNY_STREAM_API_KEY, BUNNY_STREAM_LIBRARY_ID, BUNNY_STREAM_HOSTNAME, BUNNY_STREAM_TOKEN_AUTH_KEY and BUNNY_WEBHOOK_SECRET (the Read-Only key), then restart npm run dev.

Bunny cannot call localhost, and a library has one webhook URL — a library shared by several environments (local and dev) notifies only one of them. Without the webhook, video stories still go live: the stories rail asks the Stream API about any video story unsettled for 20 s (reconcileStoryVideos, lib/stories.ts) and settles it as the webhook would, and the author sees their story as Processing meanwhile. Videos and drafts still wait for the webhook: to exercise it, expose the app with a tunnel (cloudflared tunnel --url http://localhost:3000, ngrok http 3000) and set the library's webhook to <tunnel>/api/webhooks/bunny. The in-browser editor (ffmpeg.wasm) needs nothing: its engine is fetched once from a CDN.

E-mail templates

Every e-mail is a template in apps/web/mail-templates/<id>/<locale>/ (subject.txt, body.html, body.txt), inside the shared _layout/ (rules: AGENTS.md §3.G). Locally they are read from those files (MAIL_TEMPLATES_SOURCE=local) and the messages go to the log; MAIL_DELIVERY=on with a Resend or Mailgun key really sends them.

npm run mail:templates:preview   # apps/web/.mail-preview/index.html — every template, en and fr
npm run mail:templates:push      # dry run against Bunny Storage; -- --apply publishes (production credentials)

Troubleshooting

SymptomFix
port 5432 is already allocatedAnother PostgreSQL is running: stop it, or change the published port in the dev compose file and DATABASE_URL
Too many attempts at sign-inLogin attempts are rate-limited per account, in memory: restart npm run dev
Pages show empty statesThe database is empty — npm run db:seed
relation … does not existPending migrations — npm run db:status, then npm run db:migrate
Docs check fails in CInpm run docs:generate and commit the regenerated files
A page reloads again and againA stale build cache (often after npm run build): stop the server, rm -rf apps/web/.next, npm run dev
Thumbnails or draft clips answer 403Bunny's allowed domains do not include localhost (library → Security)
Uploaded videos stay "processing"Bunny's webhook cannot reach localhost — use a tunnel (see Video features locally). Video stories catch up on their own (the rail asks Bunny)

Présentation du produit →

Sur cette page