Deployment
Deployment
Documented production path: Vercel or Netlify + hosted Supabase. Self-hosting a Node server is possible; static export is not (the app needs Server Actions, cookies, and SSR).
A hosted demo can run on Netlify. Your own install may use Vercel or Netlify. netlify.toml pins Node 24 and pnpm build. Netlify injects its Next.js adapter at build time — do not add @netlify/plugin-nextjs unless you intend to pin and skip automatic adapter updates.
Before you deploy
- A hosted Supabase project with all migrations applied (
pnpm supabase:setupordb push). - Auth Site URL and Redirect URLs set to the production origin (see Supabase setup).
- Optional: Resend domain +
pnpm supabase:smtpso real clients receive reset mail. - Optional:
pnpm supabase:seedonly on a demo project, never on a client’s production data.
Environment variables (either host)
| Name | Value |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | https://<ref>.supabase.co |
NEXT_PUBLIC_SUPABASE_ANON_KEY | anon / publishable key |
RESEND_API_KEY | optional |
RESEND_FROM | optional, verified domain |
DEMO_MODE | true only on the public demo deployment |
Do not add SUPABASE_SERVICE_ROLE_KEY to the host unless you are deliberately running admin scripts in that environment. The Next.js app does not read it.
Vercel
- Create a Vercel project from the repository.
- Framework preset: Next.js. Node 24.
- Paste the variables above. Redeploy after changing
NEXT_PUBLIC_*values. - Open
/loginand create the owner account (or use Harbor logins on a demo project). - Confirm
/auth/confirmcompletes signup and password reset.
Netlify
- Create a site from the Git remote. Framework: Next.js. Node 24 (
netlify.tomlsetsNODE_VERSION). - pnpm comes from
package.json"packageManager". Build command ispnpm build. - Site configuration → Environment variables: paste the table above. Scope them to Production (and Preview if you want Harbor on deploy previews).
- Trigger a deploy. Open
/login. - Confirm
/auth/confirmcompletes signup and password reset.
DEMO_MODE belongs in the Netlify UI, not in netlify.toml, so a normal install on Netlify is not read-only by default.
Public demo
Use a separate Supabase project for a public demo. Do not point that demo at a project that holds real client work.
Create or re-seed that project (does not write .env.local):
pnpm supabase:demoThen in Netlify → Environment variables (Production):
- Paste
supabase/.temp/netlify-demo.env(gitignored): URL, anon key,DEMO_MODE=true,NEXT_PUBLIC_DEMO_MODE=true - After the site URL exists, set
NEXT_PUBLIC_DEMO_URLand add that origin to this project's Auth Site URL + Redirect URLs
The public demo offers one-click Owner and Client access while DEMO_MODE=true. The seeded Harbor password remains Harbor-Demo-24 for manual testing and local installs. Reset later with pnpm supabase:demo again.
Self-hosting
pnpm build then pnpm start on Node 24. You need:
- HTTPS (Auth cookies and callbacks)
- The same env vars as the table above
- A process manager (systemd, Docker, etc.)
This repo does not ship a Docker workflow for local Supabase. A production Docker image of the Next.js app is your operations choice; keep service-role keys out of the image layers.
Limitations
- One visible workspace per user (oldest membership). Invite accept can add another; there is no switcher.
- Invoices are records and a print stylesheet. Paid means recorded off-platform.
- File size cap is 10 MB; logos 512 KB.
- Email confirmation depends on Auth SMTP. Without it, you can confirm users in the dashboard for development only.