Local Development

Complete step-by-step guide to running the Nebutra-Sailor monorepo on your local machine — from installing Node.js through seeding the database.

Prerequisites

Make sure the following are installed before you begin:

Step-by-step setup

# With nvm (recommended)
nvm install 22
nvm use 22

# Verify
node --version   # v22.x.x
npm install -g pnpm@latest

# Verify
pnpm --version   # 10.32.x or higher
git clone https://github.com/nebutra/nebutra-sailor.git
cd nebutra-sailor
pnpm install

This installs all workspace dependencies across apps and packages. It may take 2–3 minutes on first run.

pnpm infra:up

This starts three containers via docker-compose.infra.yml:

  • PostgreSQL 16 on port 5432
  • Redis 7 on port 6379
  • ClickHouse 24 on port 8123

If you only need the database (no Redis or ClickHouse), run pnpm infra:lite instead.

Copy the example files for each app you plan to run:

cp apps/web/.env.example           apps/web/.env.local
cp backends/gateway/.env.example   backends/gateway/.env.local
cp apps/landing/.env.example  apps/landing/.env.local

Then open each .env.local and fill in your secrets. See the Environment variables section below for a full reference.

pnpm db:generate

This runs prisma generate using the schema at packages/platform/db/prisma/schema.prisma.

pnpm db:migrate

This applies all pending Prisma migrations to your local PostgreSQL instance.

pnpm db:seed

Seeds the database with a test organization, users, and sample data so you can log in immediately.

pnpm dev

Starts all apps in parallel using Turborepo.

pnpm dev:dashboard

Starts apps/web (port 3000) and backends/gateway (port 3001).

pnpm dev:marketing

Starts apps/landing (port 3002) and apps/studio (port 3333).

All apps support Hot Module Replacement (HMR). Changes to source files apply instantly without a full page reload.

Port map

ServiceURLNotes
SaaS dashboardhttp://localhost:3000Requires Clerk auth
API gatewayhttp://localhost:3001REST API + OpenAPI docs at /doc
Landing pagehttp://localhost:30027 locales, default is /en
Design docshttp://localhost:3004Internal only
Storybookhttp://localhost:6006Component library
Sanity Studiohttp://localhost:3333Content management
PostgreSQLlocalhost:5432Database
Redislocalhost:6379Cache and queue
ClickHouselocalhost:8123Usage metering

Environment variables

backends/gateway

VariableRequiredDescription
DATABASE_URLYesPostgreSQL connection string, e.g. postgresql://postgres:postgres@localhost:5432/nebutra
REDIS_URLYesRedis connection string, e.g. redis://localhost:6379
AUTH_PROVIDERNoAuth provider: better-auth, nextauth, clerk, supabase, or dev
NEXT_PUBLIC_AUTH_PROVIDERNoClient-visible auth provider; keep aligned with AUTH_PROVIDER
CLERK_SECRET_KEYIf using ClerkClerk backend API key — from the Clerk dashboard
CLERK_PUBLISHABLE_KEYIf using ClerkClerk publishable key
STRIPE_SECRET_KEYYesStripe secret key
STRIPE_WEBHOOK_SECRETYesStripe webhook signing secret
CLERK_WEBHOOK_SECRETIf using Clerk webhooksClerk webhook signing secret
CLICKHOUSE_URLYesClickHouse HTTP interface URL
QUEUE_PROVIDERNoqstash, bullmq, or memory (auto-detected)
PERMISSIONS_PROVIDERNocasl (default) or openfga

apps/web

VariableRequiredDescription
AUTH_PROVIDERNoAuth provider selected for server routes
NEXT_PUBLIC_AUTH_PROVIDERNoAuth provider selected for client code and landing One Tap
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYIf using ClerkClerk publishable key
CLERK_SECRET_KEYIf using ClerkClerk backend API key
BETTER_AUTH_SECRETIf using Better AuthSelf-hosted Better Auth signing secret
AUTH_SECRETIf using NextAuthAuth.js / NextAuth signing secret
GOOGLE_CLIENT_IDIf using Google OAuthGoogle OAuth web client id
GOOGLE_CLIENT_SECRETIf using Google OAuthGoogle OAuth web client secret
NEXT_PUBLIC_API_URLYesBase URL of the API gateway, e.g. http://localhost:3001
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYYesStripe publishable key for client-side billing
DATABASE_URLYesPostgreSQL connection string (for Server Actions)

apps/landing

VariableRequiredDescription
NEXT_PUBLIC_SANITY_PROJECT_IDYesSanity project ID
NEXT_PUBLIC_SANITY_DATASETYesSanity dataset name, e.g. production
NEXT_PUBLIC_AUTH_PROVIDERNoAuth provider used to choose landing One Tap behavior
NEXT_PUBLIC_GOOGLE_CLIENT_IDIf Better Auth or NextAuth One Tap is enabledPublic Google OAuth web client id
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYIf Clerk One Tap is enabledClerk publishable key
SANITY_API_TOKENNoSanity read token (required for draft previews)

All environment variables are validated by @nebutra/config at startup. If a required variable is missing the process will crash immediately with a descriptive error message — there are no silent failures.

Common first-run issues

"Cannot find module '@prisma/client'"

You need to generate the Prisma client first:

pnpm db:generate

"Error: connect ECONNREFUSED 127.0.0.1:5432"

PostgreSQL is not running. Start the infrastructure containers:

pnpm infra:up

"Error: connect ECONNREFUSED 127.0.0.1:6379"

Redis is not running. Use pnpm infra:up (not pnpm infra:lite, which skips Redis).

Port already in use

Another process is using the port. Find and kill it:

lsof -ti:3000 | xargs kill   # free port 3000
lsof -ti:3001 | xargs kill   # free port 3001

pnpm version mismatch

The repo requires pnpm 10.32+. Update:

npm install -g pnpm@latest

Running individual commands

pnpm typecheck          # TypeScript check across all packages
pnpm lint               # Biome lint
pnpm lint:fix           # Biome lint with auto-fix
pnpm test               # Vitest unit tests
pnpm test:coverage      # Unit tests with coverage report
pnpm test:arch          # Architecture boundary tests
pnpm e2e                # Playwright E2E (headless)
pnpm e2e:ui             # Playwright E2E with interactive UI
pnpm build              # Production build (all apps)

How is this guide?

Edit on GitHub

Last updated on

On this page