Thanks for your interest! dForms is built to be easy to hack on: clone and run it with zero infrastructure.
pnpm install
pnpm dev # SQLite is created and seeded automaticallyRequirements: Node >= 20.9 and pnpm >= 10. No Docker or database needed.
- Ports.
pnpm devbinds the web app to 3000 and the API to 4000. To move the API, setAPI_PORTand point the web app at it withNEXT_PUBLIC_API_URL. To move the web app, runpnpm --filter @quill/web exec next dev -p <port>. - Postgres parity.
pnpm dev:pgruns everything against Postgres in Docker. The container maps host port 5432; if you already run Postgres locally, setPG_PORT(read by bothdocker-compose.ymland the script):PG_PORT=5433 pnpm dev:pg
- Windows. Run the
pnpmscripts from git-bash or WSL. They use POSIX shell syntax (${PG_PORT:-5432}) thatcmd.exeand PowerShell do not expand. - Starting an app by hand.
pnpm devmigrates and seeds before it starts the apps. If you start them yourself against a fresh database (for examplepnpm --filter @quill/api devandpnpm --filter @quill/web devin two terminals), runpnpm db:migratefirst. Without it the outbox worker fails on every poll withno such table: outbox.
See the architecture section of README.md. In short: apps/{web,api}
plus packages/{engine,types,db,destinations,notifications,shared,config}, a
Turborepo and pnpm-workspaces monorepo. The packages use the @quill/* scope;
Quill is the codename, the product is dForms.
- Create a branch off
develop. - Make your change with a test. Run:
pnpm typecheck && pnpm lint && pnpm test
- If your change affects a published package's behavior, add a changeset:
pnpm changeset
- Commit with a Conventional Commit message and a DCO sign-off (below).
- Open a PR against
develop. CI runs lint, typecheck, tests on SQLite and a Postgres parity job (which exercises the submission-integrity unique-index path), builds both apps, runs the publish-gate secret scan and checks the punctuation of user-facing text (bash scripts/dash-check.sh).
- Conventional Commits:
feat:,fix:,docs:,refactor:,test:,chore:and so on (enforced by commitlint). - DCO sign-off: we use the Developer Certificate of Origin,
not a CLA. Sign every commit:
This appends a
git commit -s -m "feat: add ..."Signed-off-by:line certifying you wrote the code (or have the right to submit it). A CI check enforces it.
- TypeScript strict. Validate untrusted input with zod at every boundary.
- Prettier owns formatting (
pnpm format). - Frontend: semantic Tailwind theme tokens only (no arbitrary values or raw hex), RSC by default, client components only for interactive islands.
- Every user-facing string lives in the i18n catalog, in both English and Spanish. No em dashes in user-facing text.
- Keep the public/adapter split: public packages depend only on ports
(
EmailProvider,SubmissionDestination, the DB factory). Concrete third-party adapters are wired by configuration, never imported by public code.
Use the issue templates. For security issues, do not open a public issue: see
SECURITY.md.
