This section is for contributors working inside the Referenta monorepo. The root README.md is the short version — clone, install, run. This section is the long version: it explains how product changes move from isolated local development to reviewed production delivery, and why the workflow is shaped the way it is.
Repository Layout
Referenta is a Turborepo-managed monorepo. The high-level shape is:
See Architecture for what each app and service does, what port it runs on, and which ones the root pnpm dev orchestrates together. The repo root supabase/ directory is the only supported Supabase CLI project.
Environment Model
Referenta uses a structured Supabase workflow with clear separation between local work, shared validation, and the live product. There are four environments in play:
- Local — Supabase CLI + Docker on your machine.
- Shared hosted dev — the existing hosted Supabase project (
rieddfnddpsbdlmmalwk) for manual development and shared testing. Not auto-promoted. - Staging — auto-deployed from the
devbranch. - Production — auto-deployed from the
mainbranch.
dev is the only branch that deploys to staging. main is the only branch that deploys to production.
Local
Local development runs through the Supabase CLI and Docker. Each developer can start a full Supabase stack on their own machine, including the database, authentication, storage, and APIs.
Product impact:
- developers can experiment safely without changing shared data,
- schema changes can be validated before the team sees them, and
- iteration is faster because local reset, seeding, and testing are under the developer's control.
Technical impact:
- the repo root
supabase/directory is the supported Supabase CLI project, - local schema work is generated into migrations,
- the dashboard can be pointed at
http://127.0.0.1:54321, and - local-only test users are created during reset for role-based testing.
Shared Validation
After local work is ready, migrations move into shared hosted environments for integration and team validation.
In practice, the repo distinguishes between:
- shared hosted development for linked remote work and manual testing,
- staging as the remote validation layer for approved
devbranch changes, and - production as the live environment used by customers.
This separation keeps collaboration predictable: local work stays isolated, while staging becomes the place where the team validates the same migration history together.
Production
Production only receives stable changes that have already been reviewed and validated. Direct edits in the dashboard or ad hoc schema changes are avoided in favor of committed migrations.
That gives Referenta:
- a traceable database history,
- repeatable environment setup,
- lower production risk, and
- clearer operational ownership over what changed and why.
Deploy Automation
Three systems collaborate to ship changes; each owns one slice and they don't overlap:
- GitHub Actions (
.github/workflows/ci.yml) validates pull requests and pushes tomain. It runs builds, type checks, Biome quality, vitest, the Playwright e2e suite (runs only on the Release Candidate PR and blocks there — day-to-day PRs skip it), Presidio service tests, and migration hygiene checks (filename pattern, duplicate timestamps, stray files). It also creates the release tag + GitHub Release when aRelease Candidate:/Release:PR merges intomain. CI does not deploy anything; there are no longerdeploy-dashboard.ymlorpreview-dashboard.ymlworkflows. See Continuous Integration for the full job-by-job breakdown and Release Automation for the release flow. - Vercel deploys
apps/dashboardandapps/wwwdirectly through its GitHub integration. Every open PR gets a preview deploy,devdeploys to staging,maindeploys to production. No GitHub Actions workflow is involved in dashboard or marketing deploys. - Supabase Branching deploys database migrations end to end. Every PR against
devautomatically gets a preview Supabase branch,devis connected to the Supabase staging branch, andmainis connected to production. Migrations don't go through GitHub Actions — Supabase manages the branching and apply flow on its side.
At a glance, the chain is:
- Preview — opening a PR against
devproduces a Vercel preview deploy and a Supabase preview branch. The Supabase preview validates that your local schema is in sync with the migration history; if your local DB has drifted, the preview fails to provision and the check on the PR goes red. Resolve it before requesting review (see Database Workflow for what drift looks like). dev— merging a PR rolls Vercel staging forward and applies the migration on the Supabase staging branch.main— merging an RC PR rolls Vercel production forward and applies the migration on the Supabase production branch.
Direct pushes to dev should be avoided when the change contains schema files — dev is connected to staging, and bypassing the PR loop bypasses the preview-branch validation that catches drift before staging gets a bad migration. See Git Workflow for the full direct-push rule.
Migration-First Workflow
The expected progression is:
- Build and test locally with the Docker-managed Supabase stack.
- Generate or sync migrations from the local schema changes.
- Commit those migrations into the repo.
- Apply and validate them in shared remote environments.
- Promote reviewed changes through staging and then production.
This is both a product workflow and an engineering guardrail. Product-wise, it prevents unreviewed infrastructure drift. Technically, it makes the repo history the source of truth for database evolution. See Database Workflow for the schema file layout and standard migration commands.
Contributor Setup
Prerequisites
Make sure you have the following installed:
- Node.js 24.x
- pnpm 11.9.0 — pinned by
packageManagerin the rootpackage.json;corepack enablegets you the right version - Vercel CLI, for
pnpm env:pull - Docker, for the local Supabase stack and the supporting services
The Supabase CLI and Turborepo are workspace devDependencies, so pnpm install provides both. Don't install them globally — a global version that drifts from the pinned one is a source of confusing schema and build differences.
Clone And Install
git clone https://github.com/Referenta/referenta
cd referenta
git checkout dev
pnpm installThe dev branch is the default starting point because staging deploys from it and most active work lands there first.
Environment Variables From Vercel
To run the applications locally you'll need the hosted environment variables from Vercel.
- Link the local repository to the Vercel project:
vercel link --repoThis command will guide you through connecting the monorepo to the corresponding project on Vercel.
- Pull the development environment variables:
pnpm env:pullThis downloads the development environment variables from Vercel and creates .env files in the respective application directories.
Local Supabase Setup
Use the root supabase/ directory as the only supported Supabase CLI project for this repo. Bringing up a local stack is two commands:
pnpm db:start
pnpm db:resetpnpm db:reset applies the committed migration history, runs the seed files, and creates the local-only test accounts. Password for all of them: Referenta!2024#
| Role | Use it for | |
|---|---|---|
role0-user1@local.referenta.test | Member | Non-privileged paths |
role1-user1@local.referenta.test | Admin | Most work — the default |
role2-user1@local.referenta.test | Superadmin | Organization management |
logout-user1@local.referenta.test | Admin | Nothing — reserved for the e2e logout spec |
These accounts exist only in the local Docker-managed Supabase stack. They are not used for shared dev, staging, or production. Leave logout-user1 alone: signOut() defaults to global scope and revokes every refresh token on the account, which invalidates the persisted sessions the Playwright suite runs against.
Onboarding does not involve pulling a schema baseline. The migration history is already committed to supabase/migrations/, so pnpm db:reset is all a fresh clone needs. Running pnpm db:pull against hosted dev manufactures a duplicate baseline and creates exactly the drift the Supabase preview-branch check exists to catch — see Database Workflow.
Linking Hosted Dev (Optional)
Only needed to push migrations to, or generate types from, the shared hosted dev project — not for local development:
pnpm supabase:login
pnpm supabase:link:devThis links the repo to shared dev project rieddfnddpsbdlmmalwk, and requires a logged-in Supabase CLI session plus the remote database password.
Point The Dashboard To Local Supabase
pnpm dev does this for you. The root script orchestrates @referenta/supabase, which starts the local Supabase stack and writes apps/dashboard/.env.development.local with the local Supabase URL, keys, and supporting service endpoints. Next.js picks the file up on the next start, so a fresh clone needs no manual env wiring to point the dashboard at local Supabase.
The auto-generated file contains:
- The four Supabase keys (
NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_ANON_KEY,NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY,SUPABASE_SERVICE_ROLE_KEY), read fromsupabase status -o env. - URLs for the supporting services
pnpm devalso starts:REDIS_PUBLIC_URL,KREUZBERG_BASE_URL,PRESIDIO_BASE_URL,GOTENBERG_BASE_URL.
The file is marked # Auto-generated by supabase/dev.sh at the top and gets rewritten every time pnpm dev boots. Don't hand-edit it. Persistent local overrides belong in apps/dashboard/.env.local, which still wins over .env.development.local in Next.js precedence.
Wiring The Dashboard Without pnpm dev
If you'd rather run the dashboard alone (pnpm dev:dashboard) without spinning up the rest of the local services, start Supabase yourself and provide the env manually. Copy apps/dashboard/.env.local.example to apps/dashboard/.env.local, then fill the Supabase values from pnpm db:status:env:
API_URL->NEXT_PUBLIC_SUPABASE_URLANON_KEY->NEXT_PUBLIC_SUPABASE_ANON_KEYPUBLISHABLE_KEY->NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYSERVICE_ROLE_KEY->SUPABASE_SERVICE_ROLE_KEY
This same approach is how you selectively override individual keys from the auto-written file, for example pointing one service URL at a remote host while the rest of the stack stays local.
Env File Precedence
A normal local checkout has several env files coexisting. Next.js loads them in this order, highest priority first:
.env.local(persistent local overrides, always wins except in test mode)..env.development.local(whatpnpm devauto-writes, points at local Supabase plus local services)..env.development.env(whatpnpm env:pullwrites, holds the hosted dev credentials from Vercel).
In practice:
- Fresh clone after
pnpm dev:.env.development.localexists and beats.env, so the dashboard hits local Supabase automatically. .env.localoverrides everything else. Use it sparingly, only for keys you specifically want to change.- Restart matters. Next.js reads env at process start. After editing
.env.local, deleting.env.development.local, or re-runningpnpm env:pull, restart the dev server before expecting changes to take effect. - Verify the wiring. The first Supabase request in your browser's network tab should hit
127.0.0.1:54321. If it's hitting the hosted host, the dev server didn't pick up the auto-written file; restart and check that.env.development.localexists.
To switch the dashboard back to remote Supabase: delete apps/dashboard/.env.development.local and don't re-run pnpm dev (which would recreate it). Next.js falls back to .env from Vercel.
.env, .env.development.local, and .env.local are all gitignored, so none of them leak into the repo. But .env still contains hosted dev credentials even when the dashboard is pointed locally. Be careful copying values out of it for one-off shell commands like psql; those will hit shared Supabase, not your local stack.
Run The App
Start the full local stack with:
pnpm devThis boots local Supabase (and auto-writes apps/dashboard/.env.development.local), the dashboard, www, docs, and the supporting Docker services in parallel. The dashboard is served on http://localhost:3000. See Architecture for the full list of apps, ports, and what each filter starts.
If you only need the dashboard and have already wired up the env manually (see Wiring The Dashboard Without pnpm dev), run:
pnpm dev:dashboardpnpm dev only stops the Supabase containers it started; if Supabase was already running (for example via pnpm db:start), it stays running after Ctrl+C. pnpm db:stop cleans up leaked containers after a hard exit.
Included Pages
Commands
Reference the current monorepo and Supabase workflow commands.
Git Workflow
Branch hygiene against dev, when direct pushes are allowed, and why Release Candidate branches stay stable.
Delivery Pipeline
An interactive map of how code reaches production — branch, PR checks and previews, staging on dev, the Release Candidate gate, and the automated release on main.
Database Workflow
See how declarative schemas in supabase/schemas/ become migrations and how they reach hosted environments.
Continuous Integration
What ci.yml validates on every PR, the gate-and-concurrency pattern, and a job-by-job breakdown.
Release Automation
See how release tags and release notes are generated from merged Release Candidate pull requests.