Deployment
Deploy a Nextly application to Vercel (recommended) or self-host on Node.js. Production checklist, environment variables, and database migrations.
A Nextly application is a standard Next.js app, so anywhere Next.js runs is fair game. This guide covers the two paths Nextly is built around:
- Vercel (recommended) -- the default target. Zero-config Next.js, first-class Vercel Blob storage, build-step migrations.
- Self-host -- Node.js 20+ behind a process manager and reverse proxy. Linked out for the operator-side details rather than reproduced here.
Whichever you choose, run database migrations on a CI/CD step (or your laptop) before the new app code takes traffic. The deployed app never touches schema -- see Production migrations for why.
Production checklist (the short list)
Before you ship, set the following:
| Variable | Required | Purpose |
|---|---|---|
NODE_ENV | yes | Set to production. |
DB_DIALECT | yes | postgresql, mysql, or sqlite. PostgreSQL recommended. |
DATABASE_URL | yes (Postgres / MySQL) | Database connection string. |
NEXTLY_SECRET | yes | JWT signing secret, at least 32 characters. Generate with openssl rand -base64 32. |
NEXT_PUBLIC_APP_URL | yes | The public URL of your deployment (used in client code and email links). |
NEXTLY_ALLOWED_ORIGINS | optional | Comma-separated additional CSRF origins (e.g. a separate frontend domain). |
Plus storage env vars if you're using cloud storage (see Media & Storage) and email env vars if you're using a real provider (see Email).
Note: Boot-time validation refuses to start in production unless
NEXTLY_SECRETis at least 32 characters andNEXT_PUBLIC_APP_URLis set.
Deploy to Vercel
Vercel is the recommended platform for Nextly. Next.js detection is automatic, the Vercel Blob adapter is the easiest storage option, and the build step doubles as a migration runner.
1. Push to GitHub and import
- Push the project to GitHub, GitLab, or Bitbucket.
- Open the Vercel Dashboard, import the repository.
- Vercel detects Next.js and configures the build pipeline. Override only if you've customised the build script (see step 3 below).
2. Configure environment variables
In Project Settings -> Environment Variables, add everything from the production checklist above, plus storage and email variables you intend to use.
Set them for Production and Preview environments separately if you want preview deployments to talk to a staging database.
3. Build command
A scaffolded Nextly project ships this build script in package.json:
{
"scripts": {
"build": "nextly migrate && next build"
}
}The nextly migrate step runs against the database referenced by DATABASE_URL during the Vercel build, so pending migrations are applied as part of every deploy. Migrations are forward-only -- to undo, write a new corrective migration. See Production migrations for the deeper trade-offs (build-time vs. CI-step migrations) and recovery patterns.
If you'd rather run migrations in a separate CI job before the Vercel deploy promotes (recommended once you have multiple developers / preview deploys), wire it into a GitHub Actions workflow as described in the migrations guide and remove nextly migrate from build.
4. Storage on Vercel
The default zero-config local-disk adapter does not work on Vercel -- serverless function instances are ephemeral, so ./public/uploads/ is wiped on cold start. Pick one of:
-
Vercel Blob (easiest) -- install
@nextlyhq/storage-vercel-blob, setBLOB_READ_WRITE_TOKEN. The auto-detection picks it up:// nextly.config.ts import { defineConfig } from "@nextlyhq/nextly/config"; import { getStorageFromEnv } from "@nextlyhq/nextly/storage"; export default defineConfig({ storage: await getStorageFromEnv(), }); -
S3 / R2 / DigitalOcean Spaces / etc. -- install
@nextlyhq/storage-s3, setS3_BUCKET+S3_REGION+AWS_ACCESS_KEY_ID+AWS_SECRET_ACCESS_KEY(andS3_ENDPOINT+S3_FORCE_PATH_STYLEfor non-AWS providers).
Vercel's serverless functions also have a 4.5MB request-body limit. Enable client-side direct uploads on storage collections that need to accept larger files:
// nextly.config.ts
import { defineConfig } from "@nextlyhq/nextly/config";
import { vercelBlobStorage } from "@nextlyhq/storage-vercel-blob";
export default defineConfig({
storage: [
vercelBlobStorage({
token: process.env.BLOB_READ_WRITE_TOKEN,
collections: {
media: {
clientUploads: true,
},
},
}),
],
});See Media & Storage for the full storage reference.
5. Database
Use a managed PostgreSQL service that's reachable from Vercel's IP ranges:
- Vercel Postgres
- Neon
- Supabase
- PlanetScale (MySQL)
SQLite is not suitable for Vercel deployments -- the file would be wiped on every cold start. See Database for adapter-specific guidance.
Self-host with Node.js
Run Nextly on any host that supports Node.js 20+. The deployment shape is intentionally boring: build the app, run it under a process manager, put a reverse proxy in front for SSL.
Requirements
- Node.js 20+ (matches the
serverExternalPackagesandsharpABI requirements). - A process manager -- pm2, systemd, Docker, or similar. Keep the Node process supervised so crashes auto-restart.
- A reverse proxy -- nginx or Caddy in front for TLS termination, HTTP/2, and access logging.
Build and start
pnpm install --frozen-lockfile
pnpm build
pnpm startThe scaffolded build script runs nextly migrate && next build, and pnpm start is next start. If you'd rather run migrations as a separate step (recommended for production with zero-downtime deploys), drop nextly migrate from build and run it via your CI pipeline before promoting the new release.
Environment variables
Configure the same variables listed in the production checklist above. On most hosts that means a .env file outside the repo (loaded by your process manager) or a secrets manager.
Process manager and reverse proxy
Use a process manager (pm2, systemd, Docker, etc.) and a reverse proxy (nginx, Caddy, etc.) -- consult their documentation for setup specific to your distribution. The Nextly process is a plain Next.js server; nothing about it requires special configuration beyond ensuring the proxy forwards Host and X-Forwarded-Proto so callbacks resolve correctly.
If your reverse proxy is on a separate IP and you rely on rate-limiting / refresh-token IP binding, set security.trustProxy: true in nextly.config.ts and populate the TRUSTED_PROXY_IPS env var with the proxy's CIDR ranges. Otherwise Nextly ignores X-Forwarded-For and treats every request as coming from a single bucket, which is the safe default for direct-internet deployments.
Migrations on deploy
For self-hosted deploys, the same forward-only model applies. Run nextly migrate against the production database before the new app binary takes traffic. See Production migrations for GitHub Actions, Railway, Render, Fly.io, and AWS examples.
Final checklist
Before going live, verify:
-
NODE_ENV=production. -
NEXTLY_SECRETis at least 32 characters (generated withopenssl rand -base64 32). -
DATABASE_URLpoints to a production database (not localhost / SQLite). -
NEXT_PUBLIC_APP_URLis the public URL of your deployment. -
NEXTLY_ALLOWED_ORIGINSlists any additional CSRF origins (separate frontend domain, mobile bundle, etc.). - Storage adapter is configured for non-ephemeral filesystems (no local disk on serverless).
- An email provider is configured (Resend, SMTP, or SendLayer) -- without one, password-reset and verification tokens are returned in the API response as a development fallback.
- All pending migrations have been applied (
nextly migrate:statusreports zero pending). - The reverse proxy / load balancer terminates TLS and forwards real client headers.
- Database backups are configured (your hosting provider's snapshots, point-in-time recovery, etc.).
- Monitoring / error reporting is wired up (Sentry, Datadog, etc.).
-
.env*files are not committed to version control.
Next steps
- Production migrations -- forward-only migration model, GitHub Actions and other CI examples.
- Authentication -- session, RBAC, and API key configuration.
- Media & Storage -- adapter-specific configuration for S3, Vercel Blob, Uploadthing, local disk.
- Email -- provider setup and local Mailpit testing.
- Environment Variables -- full environment variable reference.
- Database -- adapter setup and connection options.
Database support and version requirements
Minimum supported database versions, cloud-provider compatibility, and the warn-and-proceed policy for MySQL-compatible variants.
Production migrations
Ship database schema changes to production safely with the Nextly migration CLI. Forward-only model, GitHub Actions, Vercel build step, and other-platform patterns.