Beginner's Handbook

From zero to running SaaS

Plain language. Every term explained. Expected outcome after every step. If you've bought Already and don't know where to start — start here.

Want a guided walkthrough? Book a 15-min setup call ($49). Screen share with the team, walk through every step together, and get your app running without the guesswork.
Book a slot →

What is Already?

Already is a complete, working web application — built with modern tools — that you can use as the starting point for your own SaaS product.

Think of it like buying a fully furnished apartment instead of an empty one. The structure is there, the plumbing works, the wiring is done. You move in and redecorate — you don't lay pipes.

What is a SaaS?

SaaS stands for "Software as a Service". It means a web app people pay to use — usually with a monthly or yearly subscription. Examples: Notion, Figma, Linear. Already gives you the foundation to build one of these.

Specifically, Already gives you: user login, team accounts, Stripe payments, email sending, a database, an admin panel, and a lot more — all pre-built and production-quality. You add the parts that are unique to your product.

What is a "starter kit"?

A starter kit (also called a boilerplate or template) is a pre-written codebase that solves common, repetitive problems so you can focus on what makes your product unique. Without one, every new project starts with weeks of setting up auth, billing, and email from scratch.

What you'll need

All free to sign up. No credit card required for any of these services to start.

GitHub account
Where your code lives
GitHub stores your code and tracks changes. Already is a public template — you create your own private copy from it after purchasing.
github.com/signup →
Supabase account
Your database + user login
Supabase is your database (where all app data is stored) and handles user accounts and passwords. Free tier covers most small apps.
supabase.com →
Stripe account
Payments
Stripe handles charging your customers. You can develop and test without a live business account — test mode is fully functional.
stripe.com →
Resend account
Sending emails
Resend sends transactional emails — things like "confirm your email address" or "your invoice is ready". Free tier: 3,000 emails/month.
resend.com →
Vercel account
Hosting your app
Vercel puts your app on the internet. It reads your code from GitHub and deploys it automatically every time you push changes. Free tier works.
vercel.com →
~2 hours
First-time setup
Most of this is account setup and copy-pasting keys. Once you've done it once it'll be 15 minutes next time. Don't rush — read each step.

Install the tools

Do this once. Takes about 10 minutes.

What is a terminal?

A terminal (also called command line or shell) is a text-based way to control your computer. You type commands, press Enter, and things happen. On Mac: open Spotlight (⌘ Space), type "Terminal", press Enter. On Windows: install WSL, then use the Ubuntu terminal.

Install Node.js (the JavaScript runtime)

Node.js lets your computer run JavaScript code. Already is built with JavaScript, so this is required.

Go to nodejs.org and download the LTS version (the one that says "Recommended For Most Users"). Install it like a normal app.

Verify it worked — open your terminal and type:

node --version

You should see something like v20.11.0. Any version starting with 20 or higher is fine.

Install pnpm (a package manager)
What is a package manager?

Your app uses thousands of small pieces of code written by other people (called "packages" or "dependencies"). A package manager downloads and manages all of these for you automatically. pnpm is faster and more efficient than the default npm.

In your terminal:

npm install -g pnpm

Verify:

pnpm --version
Install Git (version control)
What is Git?

Git tracks every change you make to your code, like a detailed save history. It also lets you download code from GitHub. On Mac, Git is usually already installed. On Windows, download from git-scm.com.

Check if you have it:

git --version

If you see a version number, you're good.

Install the Supabase CLI

This tool lets you run Supabase (your database) on your own laptop while you're building — so you don't need an internet connection to test things.

On Mac (using Homebrew):

brew install supabase/tap/supabase

Don't have Homebrew? It's the standard Mac package manager. Install it first: paste this into your terminal and press Enter:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

On Windows (WSL) or Linux:

brew install supabase/tap/supabase

Verify:

supabase --version
Expected outcome

All four commands return version numbers without errors. You're ready to get the code.

Step 1 — Use the template on GitHub

01
Go to the Already template repo

Already is a public GitHub template. After purchasing, go to github.com/waitwhatco/already-template while logged into GitHub.

You don't need a GitHub invite — the repo is public and anyone with a licence can use the template.

Expected outcome

You can see the repository at github.com/waitwhatco/already-template with a green "Use this template" button in the top right.

Step 2 — Create your own copy

02
Use the template to create a new repo
Why not just fork it?

A fork stays linked to the original. A template creates a fresh, independent repository — your own history from commit one. That's what you want for a product you'll build on.

On the Already template page on GitHub:

  1. Click the green "Use this template" button (top right)
  2. Choose "Create a new repository"
  3. Give it a name — this will be your project name (e.g. my-saas-app)
  4. Set it to Private (important — this is your product code)
  5. Click "Create repository"
Expected outcome

You now have a repository at github.com/YOUR_USERNAME/YOUR_REPO_NAME that's entirely yours. No connection to the original.

Step 3 — Download the code to your computer

03
Clone the repository
What does "clone" mean?

"Cloning" a repository downloads a copy of all the code to your computer and keeps it connected to GitHub so you can sync changes back and forth.

Open your terminal. Navigate to where you keep your projects (e.g. cd ~/projects), then:

git clone https://github.com/YOUR_USERNAME/YOUR_REPO_NAME
cd YOUR_REPO_NAME

Replace YOUR_USERNAME and YOUR_REPO_NAME with your actual values. You can copy the exact URL from the green "Code" button on your GitHub repo page.

Then install all the dependencies:

pnpm install

This downloads all the packages your app needs. It may take 1–2 minutes the first time.

Expected outcome

You see a folder on your computer with all the code. Running ls shows files like package.json, CLAUDE.md, app/, lib/.

Step 4 — Set up Supabase (your database)

What is Supabase?

Supabase is a service that gives you a Postgres database (where all your app's data is stored — users, subscriptions, everything) plus user authentication (login/signup) already built. Already is deeply integrated with it. You can start with the free tier and upgrade only if you need to.

04a
Create a Supabase project
  1. Go to supabase.com and sign in
  2. Click "New project"
  3. Give it a name (anything — this is just for you)
  4. Set a strong database password and save it somewhere safe — you'll need it later
  5. Choose a region close to your users
  6. Click "Create new project" and wait ~2 minutes for it to spin up
04b
Get your Supabase API keys

Once your project is ready, go to Project Settings → API. You'll see three values you need:

  • Project URL — looks like https://abcdefgh.supabase.co
  • anon / public key — a long string starting with eyJ...
  • service_role key — another long string. Keep this secret — never put it in public code.

Also go to Project Settings → Database to get your connection strings. You'll need the "Connection string" (URI format) — there are two: Session mode (for most things) and Direct (for migrations).

Don't share these keys. The service_role key gives full access to your database. It goes in your private .env.local file only.

Step 5 — Set up Stripe (payments)

What is Stripe?

Stripe is the most widely used payment processor for internet businesses. It handles credit cards, invoices, subscriptions, and tax. Already uses Stripe for all billing. You develop against "test mode" — fake cards, no real money — until you're ready to go live.

05a
Create a Stripe account and get test keys
  1. Go to stripe.com and create an account
  2. Stay in Test mode — there's a toggle in the top right. Make sure it says "Test mode" with an orange badge
  3. Go to Developers → API keys
  4. Copy the Publishable key (starts with pk_test_)
  5. Reveal and copy the Secret key (starts with sk_test_)
05b
Set up the Stripe webhook secret (for local dev)
What is a webhook?

When something happens in Stripe (a payment succeeds, a subscription cancels), Stripe sends a notification to your app. This is called a webhook. Your app needs to listen for these to keep its database in sync with Stripe.

For local development, Already uses the Stripe CLI to forward webhooks to your laptop. Install it:

# Mac
brew install stripe/stripe-cli/stripe

# Windows/Linux: see stripe.com/docs/stripe-cli

Log in to the CLI:

stripe login

When you later run pnpm dev, it will automatically start the webhook listener and print a webhook secret that starts with whsec_. You'll add that to your env file in step 7.

Step 6 — Set up Resend (email sending)

What is Resend?

Resend is a developer-friendly service for sending transactional emails — things your app sends automatically, like "confirm your email", "your payment failed", "you've been invited to a team". Already uses React Email to write these templates. Resend's free tier covers 3,000 emails/month.

06
Get a Resend API key
  1. Go to resend.com and create an account
  2. Go to API KeysCreate API key
  3. Give it a name (e.g. "Already dev") and click Create
  4. Copy the key immediately — it's only shown once. It starts with re_

For local development, you don't need a verified domain. Emails won't actually send — they'll appear in the React Email preview instead. You only need a real domain when you go live.

Step 7 — Wire it all up

What is an .env file?

An environment file (.env.local) is a plain text file where you store your secret keys and configuration. The app reads from this file when it starts. It's never committed to GitHub — it stays only on your computer (and on Vercel when you deploy). Think of it as the keys to your services.

07
Create your .env.local file

Already includes a template file called .env.example that lists every variable you need with comments explaining each one. Copy it:

cp .env.example .env.local

Now open .env.local in any text editor (VS Code, Notepad, TextEdit) and fill in the values you collected in steps 4–6.

The file looks like this — replace the empty values:

# Supabase — from Project Settings → API
NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJh...
SUPABASE_SERVICE_ROLE_KEY=eyJh...
DATABASE_URL=postgresql://postgres:[email protected]_PROJECT.supabase.co:5432/postgres
DATABASE_URL_DIRECT=postgresql://postgres:[email protected]_PROJECT.supabase.co:5432/postgres

# Stripe — from Developers → API keys (use test keys to start)
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Resend — from API Keys page
RESEND_API_KEY=re_...

The .env.example file has every variable with inline documentation. Read the comments — they explain what each one does and where to find it.

Step 8 — Run it for the first time

08a
Run the setup script

Already includes a setup script that checks your config, runs database migrations, and bootstraps Stripe products. Run it once:

pnpm setup

It's interactive — it will tell you if anything is missing from your .env.local and explain what to fix. Follow the prompts.

For Stripe billing, also run:

pnpm setup:stripe

This creates the subscription plans in your Stripe test account and writes their IDs back to your .env.local.

08b
Start the development server
pnpm dev

This starts everything at once: your app, the local database, the Stripe webhook listener, and the email preview server.

Expected outcome

Open your browser and go to:

  • localhost:3000 — your app, showing a marketing page
  • localhost:54323 — Supabase Studio, a visual database browser
  • localhost:3001 — React Email preview (your email templates)
If pnpm dev fails

"Missing env variable X" — you have a typo or missing value in .env.local. Re-check step 7.

"Cannot connect to database" — double-check your DATABASE_URL. Make sure you replaced PASSWORD with your actual Supabase DB password.

"Port 3000 already in use" — something else is running on that port. Quit other dev servers or restart your terminal.

Still stuck? Run pnpm already doctor — it checks your setup and tells you exactly what's wrong.

Step 9 — Understand what you have

Here's a map of what Already ships with and where to find each part.

The app routes

Open the app/ folder. Routes are grouped by who can access them:

app/
  (public)/      ← Anyone can see this: marketing pages, pricing
  (auth)/        ← Login, signup, forgot password, MFA setup
  (app)/         ← Logged-in users with an org account
  (billing)/     ← Paid subscribers only
  (admin)/       ← Admin users only: user management, impersonation

The 16 modules

Already ships 16 complete features. You can use all of them, ignore the ones you don't need, or delete them entirely:

  • Auth — signup, login, magic link, passkeys, two-factor (in app/(auth)/)
  • Multi-tenant orgs — team accounts, invitations, role management
  • Billing — Stripe subscriptions, plan gates, customer portal
  • Admin panel — manage users and orgs, impersonate any user
  • Email — transactional templates in messaging/templates/
  • Background jobs — async task queue in lib/jobs/
  • AI integration — multi-provider AI with a per-org usage ledger
  • Feature flags — turn features on/off per user or org in config/flags.ts
  • …and 8 more. Full list in the repo's docs/ folder.

Useful commands for exploring

pnpm db:seed      # fill your local database with demo users and data
pnpm db:studio    # open a visual database browser
pnpm email        # preview your email templates in the browser
pnpm reset        # wipe and re-seed the database (safe — local only)

Step 10 — Make it yours

First things to change before you start building your actual product.

10a
Change the app name and description

Open config/app.ts. Change name, description, and url to match your product.

This value flows through the app — it appears in email subjects, page titles, and the admin panel. Change it once here and it updates everywhere.

10b
Set up your billing plans

Open config/billing.ts. This file defines your pricing tiers — names, prices, and which features each tier unlocks. Change these to match your actual product plans.

Then re-run pnpm setup:stripe to sync the new plan config to Stripe.

10c
Update the marketing page

The public marketing page lives at app/(public)/page.tsx. Replace the placeholder copy with your product's actual value proposition.

The legal pages (privacy policy, terms of service) are at content/legal/. Update them with your company details before you go live.

Step 11 — Deploy to the internet

What is Vercel?

Vercel is the hosting service Already is built for. You connect your GitHub repository, set your environment variables, and Vercel automatically deploys your app every time you push code. Free tier is enough for most early-stage products.

11a
Create a Vercel project
  1. Go to vercel.com and sign in with GitHub
  2. Click "Add New → Project"
  3. Import your GitHub repository
  4. Vercel auto-detects it's a Next.js app — click "Deploy"

The first deploy will fail because your environment variables aren't set yet. That's expected.

11b
Add environment variables to Vercel

In your Vercel project, go to Settings → Environment Variables. Add every variable from your .env.local file.

Important differences for production:

  • Use live Stripe keys (pk_live_, sk_live_) instead of test keys
  • Create a production Stripe webhook endpoint in your Stripe dashboard pointing to https://YOUR_DOMAIN.com/api/webhooks/stripe
  • Use your Supabase cloud project keys (not the local ones from supabase start)
  • Verify a sending domain in Resend and update RESEND_FROM_EMAIL

After saving, trigger a new deployment from the Vercel dashboard.

11c
Connect a custom domain (optional but recommended)

In Vercel project settings, go to Domains and add your domain. Vercel will give you DNS records to add at your domain registrar (wherever you bought the domain — Namecheap, GoDaddy, Cloudflare, etc.).

DNS changes can take up to 24 hours to propagate, but usually take minutes.

Expected outcome

Your app is live at your Vercel URL (and your custom domain if you set one). Real users can sign up. Real payments go through Stripe.

Common problems

"I get a blank page or error at localhost:3000"

Run pnpm already doctor — it checks your setup and tells you exactly what's misconfigured. Most problems are a missing or wrong value in .env.local.

"pnpm setup fails with a database error"

Your DATABASE_URL is wrong. Go back to Supabase → Project Settings → Database and copy the connection string again. Make sure you replace [YOUR-PASSWORD] with your actual password (the one you set when creating the project).

"Emails aren't sending"

In local dev, emails don't actually send — they appear in the React Email preview at localhost:3001. If you're in production, check that your Resend API key is correct and that you've verified a sending domain.

"Stripe webhooks aren't working"

In local dev, make sure pnpm dev is running (it starts the Stripe webhook forwarder). In production, make sure you've created a webhook endpoint in the Stripe dashboard pointing to /api/webhooks/stripe and that STRIPE_WEBHOOK_SECRET matches the whsec_ secret from that endpoint.

"I changed something and now nothing works"

Run pnpm reset (resets the local database) and pnpm dev again. If it's a code change causing a TypeScript error, run pnpm typecheck to see the exact error.

Ask Claude Code

Already ships with deep Claude Code integration. Once you're in the project directory, Claude Code understands the full architecture — you can ask it anything about the codebase in plain language.

Start Claude Code with the project's MCP servers

From your project directory, open Claude Code (the desktop app or claude in terminal). Point it at your project folder. It will automatically load the CLAUDE.md and connect to the MCP servers defined in mcp.json.

Things you can ask:

  • "Explain the multi-tenant architecture to me in simple terms"
  • "How do I add a new page that only paying users can see?"
  • "Show me all the users who signed up in the last 7 days"
  • "Why is this webhook failing?"
Use the built-in slash commands

Already includes 10 Claude Code skills — slash commands that understand the project structure:

/add-page       ← scaffold a new route with correct auth guards
/add-table      ← create a DB table + RLS policy + query helpers
/add-plan       ← add a Stripe pricing tier
/add-message    ← add an email template
/add-job        ← create a background job
/add-flag       ← add a feature flag
/deploy         ← pre-deploy checklist
/run-migration  ← run pending DB migrations
/debug-webhook  ← diagnose a webhook problem
/already-update ← check for Already updates

Type any of these in Claude Code and it will walk you through the task step by step, creating all the right files in the right places.

Not sure how something works? Just ask. The CLAUDE.md in the project root contains architecture rules, common pitfalls, and module maps — Claude Code reads it at the start of every session and will answer questions about any part of the codebase.