Launch NowDocs

Installation

Set up Launch Now locally, from cloning the repository to signing in to your first account.

This page walks you through running Launch Now on your machine: install the dependencies, configure the environment, create the database tables, seed the plans and start the development server.

System requirements

Before you start, make sure you have:

  • Node.js 22. This is the version the CI workflow uses (.github/workflows/ci.yml).
  • pnpm 12.4.1. The version is pinned in the packageManager field of package.json. If you have Corepack enabled (corepack enable), the right version is picked up automatically.
  • A PostgreSQL database. Neon works out of the box, as does any local or hosted Postgres.
  • A Stripe account in test mode, and optionally the Stripe CLI to receive webhooks locally.
  • A Resend account to send sign-in codes and other emails.
  • An S3-compatible bucket for avatars and logos (Cloudflare R2, AWS S3, MinIO…).
  • GitHub and Google OAuth apps for social sign-in.

Good to know: The environment is validated at startup, and every service above has required variables. See Environment variables for what each one does and how to get it.

Set up the project

Clone the repository

Clone the repository into a new folder and move into it:

git clone https://github.com/anthonyRanivoarison/app.launch.now.git my-saas
cd my-saas

Install dependencies

pnpm install

pnpm-workspace.yaml allows the build scripts of esbuild, simple-git-hooks and unrs-resolver to run. simple-git-hooks installs the Git hooks defined in package.json: pnpm lint before each commit and commitlint on each commit message.

Create your .env file

Copy the example file and fill in real values:

cp .env.example .env

Use .env rather than .env.local: the database and Stripe scripts load variables with dotenv/config, which only reads .env.

At minimum, set DATABASE_URL, BETTER_AUTH_SECRET, the Resend, OAuth, S3 and Stripe keys. Generate the auth secret with:

openssl rand -base64 32

The full list is in Environment variables.

Run the database migrations

Create the tables by applying the SQL migrations in drizzle/:

pnpm db:migrate

This runs drizzle/migrate.ts, which uses Drizzle's migrator against DATABASE_URL.

Do not use pnpm db:push. It is disabled on purpose and only prints a message: Neon does not support drizzle-kit push. Change the schema, then run pnpm db:generate and pnpm db:migrate.

Create the Stripe products

With STRIPE_SECRET_KEY set to a test key, create the Pro and Ultra products and their monthly prices:

pnpm stripe:products

The script is idempotent: it looks prices up by their lookup key (pulse-pro-monthly and pulse-ultra-monthly, built from siteConfig.slug) and only creates what is missing. At the end it prints the price IDs to copy into .env:

=== Copy these into your .env ===
STRIPE_PRO_PRICE_ID=price_...
STRIPE_ULTRA_PRICE_ID=price_...

A plan without a price ID is not offered for checkout, so set both.

Seed the plans

Insert the Free, Pro and Ultra plans into the plan table. The pricing page and the Stripe plugin read them from there:

pnpm db:seed:plans

It upserts by plan name, so you can run it again after editing scripts/seed-plans.ts.

Seed the demo account (optional)

If you set DEMO_EMAIL and DEMO_PASSWORD (at least 8 characters), you can create a shared demo account:

pnpm db:seed:demo

This creates a verified demo user, a "Demo Workspace" organization owned by it, three fake members and a few pending invitations. When both variables are set, the sign-in page shows a demo sign-in button, and destructive actions (deleting the account, changing the password, leaving or deleting the organization…) are blocked for that account.

Skip this step for a real product. pnpm reset-project removes the demo account code entirely.

Forward Stripe webhooks (optional)

To test checkout locally, forward Stripe events to the webhook route with the Stripe CLI:

stripe listen --forward-to localhost:3000/api/webhook/stripe

Copy the whsec_... signing secret it prints into STRIPE_WEBHOOK_SECRET, then restart the dev server.

Start the development server

pnpm dev

Open http://localhost:3000. You should see the Pulse marketing homepage.

Sign in for the first time

Go to /auth/signup and create an account with an email one-time code, GitHub or Google. New accounts land on /auth/onboarding, then on /dashboard.

Public password sign-up is disabled (emailAndPassword.disableSignUp in lib/auth.ts): the password flow only exists for the shared demo account. Your users sign in with a code sent by email or with OAuth.

Good to know: Sign-in codes are sent through Resend. Until you verify a domain in Resend, it only delivers to the address of your own Resend account, so sign up with that address first.

Make yourself a platform admin

The admin panel at /admin is only available to users whose role column is admin. For the first admin, set it directly in the database, for example with Drizzle Studio:

pnpm db:studio

Open the user table, set role to admin on your user and reload the app. From then on, you can promote other users from the admin panel.

Useful scripts

CommandWhat it does
pnpm devStart the Next.js dev server.
pnpm checkRun ESLint, the TypeScript compiler and Knip.
pnpm formatFormat the code with Prettier.
pnpm db:generateGenerate a migration from changes to drizzle/auth-schema.ts.
pnpm db:migrateApply pending migrations.
pnpm db:studioOpen Drizzle Studio to browse the database.
pnpm email:devPreview the React Email templates in emails/.
pnpm legal:checkList legal config fields that still hold a TODO.
pnpm resource:generateScaffold a CRUD feature from a spec.
pnpm reset-projectRemove the demo code and start from a clean slate.

See Scripts for the full reference.

Next steps