Install CentraKit, start the local Supabase stack and the apps with or without Portless, and sign in with the seeded personas.
package.json..env.local. With the repository linked to Vercel, pnpm env:pull writes .env.local (development) and .env.production.local (production). Without a link, copy .env.example to .env.local and fill in the required values.Install dependencies from the repository root:
pnpm installEvery app reads the root env files through loadMonorepoEnv, so there are no per-app .env files. See Environment variables.
Keep local-only values in .env.development.local. pnpm env:pull rewrites .env.local but leaves this file alone.
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=<publishable key from pnpm exec supabase status>
# Leave NEXT_PUBLIC_SITE_URL unset, or set it to https://localhost,
# so the apps resolve to https://app.localhost and https://api.localhost.
# NEXT_PUBLIC_SITE_URL=https://localhostStart the local stack, then apply the schema and seeds:
pnpm supabase:start
pnpm supabase:syncpnpm supabase:start generates a local JWT signing key if needed and starts the Supabase containers. pnpm supabase:sync pushes pending migrations and seeds to the local database, falls back to a full reset when the push fails, and then seeds the Storage buckets.
Use pnpm supabase:reset only when you want a clean database. It drops all local data and replays every migration and seed. After a reset, sign in again, because existing browser sessions refer to the previous auth database.
The local stack runs Postgres, Auth, Storage, Realtime and imgproxy, so Storage /render/image URLs behave like hosted image transforms. The pooler service is intentionally stopped. More detail is in Supabase local dev.
| Command | Starts |
|---|---|
pnpm dev:portless | SaaS and API on https://app.localhost and https://api.localhost. |
pnpm dev | SaaS and API with plain next dev on localhost ports. |
pnpm dev:api:portless | Only the API, on https://api.localhost. |
pnpm dev:api | Only the API, with plain next dev. |
pnpm dev:docs:portless | The API and the docs site on https://docs.localhost. |
pnpm dev:marketing:portless | The API and the marketing site. |
pnpm dev:showcase:portless | Only the showcase. |
pnpm dev:all:portless | Every app that has a dev:portless task. |
Use the Portless commands for browser testing. The SaaS app calls the API for chat, inbox, AI suggestions and other features, which is why pnpm dev and pnpm dev:portless always start both. The plain next dev commands are useful in cloud and container environments where Portless is not available. Each of the docs, marketing and showcase commands also has a variant without :portless.
pnpm dev:oauth starts the SaaS app on a localtest.me host for testing Google sign-in. See Authentication.
Every seeded user has the password Password123!. test@example.com (Lieke Hofstra) owns the four shop organizations, and each one covers its own industry:
| Organization | Business |
|---|---|
tractor-service | Tractor and garden machinery repair. The deepest seed, with every domain state. |
auto-garage | Car garage with APK inspections, tyre storage and courtesy cars. |
bike-scooter-shop | Bicycle and scooter shop with retail sales, repairs and a webshop. |
equestrian-center | Riding school and livery stable with boarders, lessons and farrier visits. |
| Access | |
|---|---|
test@example.com | Owner of all four shop organizations, the seeded system admin, and a portal contact of De Haan Landscaping. |
test1@example.com | Member of tractor-service, set up in People as a field service mechanic (Jeroen Bakker). |
test2@example.com | Viewer in bike-scooter-shop (Sanne Visser). |
test3@example.com | Portal-only private customer of both tractor-service and auto-garage (Pieter Brouwer). |
test4@example.com | Portal-only contact for the business customer Green Acre Farms BV in tractor-service (Hendrik van Laar). |
test5@example.com | Portal-only boarder at equestrian-center (Charlotte Veenstra). |
The seed also creates role-specific accounts for permission testing:
| Access | |
|---|---|
support@example.com | The system-support system role, with no organization membership. |
owner@example.com | Finance and settings role in all four shop organizations. |
operator@example.com | Admin in tractor-service and auto-garage. |
team.lead@example.com | Service planner in tractor-service and auto-garage. |
crm.editor@example.com | Sales advisor in tractor-service and bike-scooter-shop. |
assets.editor@example.com | Parts manager in tractor-service and bike-scooter-shop. |
viewer@example.com | Read-only custom role in tractor-service. |
bike.mechanic@example.com | Mechanic in bike-scooter-shop. |
bike.retail@example.com | Sales advisor in bike-scooter-shop. |
garage.apk@example.com | Mechanic and APK inspector in auto-garage. |
garage.advisor@example.com | Service advisor in auto-garage. |
stable.manager@example.com | Admin in equestrian-center. |
stable.instructor@example.com | Instructor with the service planner role in equestrian-center. |
stable.viewer@example.com | Read-only custom role in equestrian-center. |
disabled@example.com | A mechanic in tractor-service whose profile is disabled. |
external@example.com | Owner of harbor-marine-service and of cedar-hvac-rental, which is disabled. No access to the shop organizations. |
Each shop organization has customers, contacts, customer assets, products and inventory, tasks, agenda items, quotes, invoices and orders in every status, plus files, inbox threads, chat history, notifications, employees, time, expenses, hiring, workflows, audit logs and billing data. Seed files live in supabase/seeds/, and each one starts with a -- Covers: comment that lists the scenarios it seeds.
pnpm supabase:sync warns about unset Google OAuth variables. Google sign-in is optional locally, so the warning is safe to ignore..env.local are placeholders, so billing flows do not work locally. Everything else does..localhost hosts and sign in again.Last updated on