Getting Started
Installation
This guide walks you through every step from a blank machine to a running Nestled application.
Want to skip local setup?
If you'd rather go straight to the cloud, use the Nestled Railway template to deploy a fully wired Nestled application — API, web app, PostgreSQL, and Redis — directly to Railway in minutes. See the Deployment guide for details.
Prerequisites
Before you begin, make sure you have the following installed:
- Node.js 20+ — Download from nodejs.org. The template uses Node 22.
- pnpm — Install with
npm install -g pnpm - Git — For cloning the template
- Docker — Required for PostgreSQL, Redis, and Mailhog. Get Docker.
Why pnpm?
Nestled uses pnpm for package management. Its efficient disk usage and strict dependency resolution make it ideal for monorepos with many packages.
Clone the template
git clone https://github.com/nestledjs/nestled-template.git my-app
cd my-app
Remove the existing git history and start fresh:
rm -rf .git
git init
Stay up to date
Nestled evolves over time — auth changes, security patches, new patterns. Because everyone's codebase diverges, we publish AI upgrade specs for major updates: drop the spec into your AI agent and it will intelligently reconcile the changes with your existing code.
Configure your environment
Copy the example environment file:
cp .env.example .env
For local development, the defaults work out of the box — you just need to install dependencies first:
pnpm install
Build approvals
You may need to run pnpm approve --builds to approve libraries that require native compilation (Prisma, SWC, etc.).
Set up your workspace
Run the workspace setup generator to name your project and initialize everything:
nx g @nestledjs/generators:workspace-setup --name my-app
This does several things:
- Renames the workspace — finds and replaces
nestled-templatethroughout the project with your chosen name. All your imports will use@my-app/...going forward. - Preserves updater metadata — skips
.nestled/and.nestled-updates/so future upgrade and doctor commands keep working. - Ensures
.envexists — copies.env.exampleif you skipped that step. - Validates your database URL — refuses to run against non-localhost databases.
- Starts Docker services — spins up PostgreSQL, Redis, and Mailhog, then waits for the database to accept connections.
- Applies Prisma migrations — updates your local database schema.
- Generates the Prisma client — runs
pnpm prisma:generatebefore seed code imports Prisma. - Generates GraphQL types — prepares the API types used by the template.
- Seeds the database — creates an admin user and initial data.
Choosing a name
Use lowercase with dashes for spaces (e.g., my-app, acme-saas, todo-pro). The name must match ^[a-z][a-z0-9-]*$. Keep it short — this becomes the @name/ prefix for every import in your project, so shorter means less typing during development.
Environment variables
The key variables you may want to customize in .env:
Core settings
| Variable | Default | Description |
|---|---|---|
APP_NAME | your-app-name | Application name, used in emails and 2FA |
PORT | 3000 | API server port |
JWT_SECRET | JWT_SECRET | Change this — secret for signing auth tokens |
API_URL | http://localhost:3000 | API origin (scheme + host + port). Origin only — no path and no /api suffix; the app appends /api. An invalid value fails the API at startup |
SITE_URL | http://localhost:4200 | Frontend base URL |
Database
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | postgresql://prisma:prisma@localhost:5432/prisma | PostgreSQL connection string used by the running app |
DIRECT_URL | Not set (falls back to DATABASE_URL) | Optional direct (non-pooled) URL used by the Prisma CLI for migrations. Leave unset locally; set it to point migrations at a remote DB without swapping DATABASE_URL |
| Variable | Default | Description |
|---|---|---|
EMAIL_PROVIDER | Not set (uses SMTP) | Set to mock to skip real emails in CI/testing |
SMTP_HOST | localhost | SMTP server host (Mailhog in local dev) |
SMTP_PORT | 1025 | SMTP server port |
Stripe billing (optional)
| Variable | Description |
|---|---|
STRIPE_SECRET_KEY | Your Stripe secret key (sk_test_...) |
STRIPE_PUBLISHABLE_KEY | Your Stripe publishable key (pk_test_...) |
STRIPE_WEBHOOK_SECRET | Webhook signing secret (whsec_...) |
STRIPE_CURRENCY | Currency code (default: usd) |
OAuth providers (optional)
| Variable | Description |
|---|---|
GOOGLE_OAUTH_CLIENT_ID | Google OAuth client ID |
GOOGLE_OAUTH_CLIENT_SECRET | Google OAuth client secret |
GITHUB_OAUTH_CLIENT_ID | GitHub OAuth client ID |
GITHUB_OAUTH_CLIENT_SECRET | GitHub OAuth client secret |
File storage (optional)
| Variable | Description |
|---|---|
STORAGE_PROVIDER | local, s3, cloudinary, imagekit, or gcs |
Each provider has its own set of keys (AWS keys for S3, Cloudinary API key/secret, etc.). See .env.example for the full list.
Start development
Run these three commands in separate terminals:
# Terminal 1 — API server
nx serve api
# Terminal 2 — Web application
nx serve web
# Terminal 3 — SDK type generation (watches for changes)
pnpm sdk watch
Verify everything works
- Web app: http://localhost:4200 — you should see the login page
- GraphQL playground: http://localhost:3000/graphql
- Mailhog: http://localhost:8025 — emails sent during registration/password reset appear here
- Prisma Studio: Run
pnpm prisma:studioto browse your database visually
Your first schema change
The real power of Nestled is the code generation pipeline. Try adding a model to your schema:
- Edit
libs/api/prisma/src/lib/schemas/schema.prisma - Run
pnpm db-update— regenerates your entire API, types, and SDK - Run
pnpm prisma db push— applies schema changes to the database - Your API now has full CRUD for the new model, and your frontend has typed queries ready to use
See the Commands reference for details on every available script, or read about the Architecture to understand how all the pieces fit together.