Skip to main content

Deployment Guide

ropa2.0 is deployed as a Next.js application on Vercel with MongoDB Atlas as the database. Tenants are identified by subdomains (<shortName>.rat.gd). Each subdomain must resolve to the same Vercel deployment.


Prerequisites

  • Node.js ≥ 20
  • A MongoDB Atlas cluster (M10 or higher recommended for production)
  • A Clerk application (Business plan for multi-org support)
  • A Cloudflare account with Turnstile enabled
  • A Vercel project connected to this repository
  • A domain with wildcard DNS support

1. MongoDB

1.1 Create a cluster

Use MongoDB Atlas. Recommended: M10 (dedicated) for production; M0 (free shared) is fine for staging.

1.2 Create a database user

Database Access → Add New Database User — grant readWriteAnyDatabase on the target database.

1.3 Allowlist Vercel IPs

Network Access → Add IP Address → Allow Access from Anywhere (0.0.0.0/0).

Vercel serverless functions use dynamic egress IPs that cannot be statically allowlisted.

1.4 Get the connection string

Connect → Drivers → Node.js — copy the connection string:

mongodb+srv://<user>:<password>@<cluster>.mongodb.net/<dbname>?retryWrites=true&w=majority

Replace <dbname> with your target database name (e.g. ropa2).


2. Clerk

2.1 Create a Clerk application

  1. Sign in at https://clerk.com.
  2. Create a new application — enable Email and your required social providers.
  3. Switch to Organizations mode: Settings → Organizations → Enable Organizations.

2.2 Create the demo organization

The demo tenant is special — its clerkOrganizationId is hard-coded in src/lib/mongoose/organizationFromTemplateCreate.js (KNOWN_CLERK_ORG_IDS). Create a Clerk organization with slug demo and copy its ID into that constant before the first deploy.

2.3 Configure the webhook

Webhooks → Add Endpoint:

  • URL: https://<your-domain>/api/webhooks/clerk
  • Events to subscribe: organization.updated, organization.deleted

Copy the Signing Secret — this becomes CLERK_WEBHOOK_SIGNING_SECRET.

2.4 Collect keys

From API Keys:

VariableWhere in Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYPublishable key
CLERK_SECRET_KEYSecret key
CLERK_WEBHOOK_SIGNING_SECRETWebhook signing secret (step 2.3)

3. Cloudflare Turnstile

  1. Sign in at https://dash.cloudflare.com.
  2. Turnstile → Add site — domain: *.rat.gd (wildcard covers all tenants).
  3. Copy the Site Key and Secret Key.
VariableValue
NEXT_PUBLIC_TURNSTILE_SITE_KEYSite key
TURNSTILE_SECRET_KEYSecret key

4. Environment Variables

Set all of the following in Vercel → Settings → Environment Variables. Mark variables starting with NEXT_PUBLIC_ as available to all environments; server-only variables should be Production + Preview only.

Required

VariableDescription
MONGODB_URIFull MongoDB Atlas connection string
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYClerk frontend key
CLERK_SECRET_KEYClerk backend key
CLERK_WEBHOOK_SIGNING_SECRETSvix signature secret for webhook verification
NEXT_PUBLIC_SITE_DOMAINRoot domain without protocol (e.g. rat.gd)
NEXT_PUBLIC_TURNSTILE_SITE_KEYCloudflare Turnstile site key
TURNSTILE_SECRET_KEYCloudflare Turnstile server-side secret

Optional — logging & telemetry

VariableDefaultDescription
LOG_LEVELdebug (dev), info (prod)Pino log level
NEXT_PUBLIC_SENTRY_DSNSentry DSN for browser error tracking
SENTRY_DSNSentry DSN for server error tracking
SENTRY_ORGSentry org slug (for source map upload at build time)
SENTRY_PROJECTSentry project slug
SENTRY_AUTH_TOKENSentry auth token for source map upload
AXIOM_TOKENAxiom ingest token (activates Pino → Axiom transport)
AXIOM_DATASETAxiom dataset name (e.g. ropa2-production)

See telemetry.md for full Sentry + Axiom setup.

Optional — build

VariableDefaultDescription
ANALYZEfalseSet to true to generate bundle analysis report
CISet by Vercel automatically; suppresses Sentry build logs when absent

5. DNS

All tenant subdomains route to the same Vercel deployment. Two DNS records are needed:

TypeNameValue
A / CNAME@Vercel IP / cname.vercel-dns.com
CNAME*cname.vercel-dns.com

The wildcard record catches all <shortName>.rat.gd subdomains. In Vercel → Project Settings → Domains, add:

  • rat.gd
  • *.rat.gd

6. Vercel Deployment

6.1 Connect the repository

New Project → Import Git Repository — select gdpr-labs/ropa2.0.

6.2 Build settings

Vercel auto-detects Next.js. No changes needed.

6.3 Deploy

Push to main (or your production branch). Vercel builds and deploys automatically.

On the first successful deploy, run the demo data seed (step 7).


7. Seed Demo Data

The demo tenant (demo.rat.gd) is created via the admin route:

POST /api/admin/recreate-demo

This is a protected endpoint. Trigger it once after the first deploy to create the demo organization, its ROPAs, and link it to the Clerk org created in step 2.2.


8. Post-Deployment Verification

Check each item after deploying:

  • https://demo.<your-domain> loads without error
  • Clerk sign-in works and redirects back to the subdomain
  • Cloudflare Turnstile challenge appears on protected forms
  • Creating a new ROPA activity saves to MongoDB
  • PDF export generates and downloads correctly
  • Clerk webhook fires on org update (check server logs)
  • Sentry receives a test error (see telemetry.md#verification)
  • Axiom receives structured Pino logs (see telemetry.md#axiom)

9. Development Setup

# Install dependencies
npm install

# Copy env files
cp .env.e2e.example .env.e2e # fill in E2E_CLERK_USER_EMAIL

# Create .env.local with the variables from section 4
# at minimum: MONGODB_URI, CLERK keys, TURNSTILE keys, NEXT_PUBLIC_SITE_DOMAIN

# Run dev server
npm run dev

Local subdomains: demo.localhost:3000, upf.localhost:3000.

For local subdomain routing to work, add entries to /etc/hosts:

127.0.0.1 demo.localhost
127.0.0.1 upf.localhost

Useful scripts

CommandDescription
npm run devStart dev server
npm run buildProduction build
npm testUnit + service tests (Vitest)
npm run test:e2ePlaywright E2E tests
npm run lintESLint
npm run analyzeBundle size analysis (ANALYZE=true)

10. Multi-Environment Strategy

EnvironmentBranchDomainNotes
Productionmain*.rat.gdLive data; all env vars required
PreviewFeature branchesVercel preview URLsUse staging Atlas cluster; Clerk test mode
DevelopmentLocal*.localhost:3000.env.local; mongodb-memory-server optional

Clerk has separate Development and Production instances — use the development instance keys for local and preview environments.