Documentation

Everything you need to understand, set up, and deploy StormGecko — a complete, multi-tenant booking & appointments SaaS.

Overview

StormGecko is a real, production-ready SaaS — not a front-end template. Each business is its own tenant with authentication, isolated data, a public booking page, payments, emails, and a team. It runs on Next.js 14, Supabase, and Stripe, and deploys to Vercel.

It ships with a zero-config demo mode: run it with no environment variables and the whole app renders with sample data and no login — perfect for evaluating before you configure anything.

Features

Self-service booking

A public booking page per business — customers pick a service, date & time (from real availability, slot intervals, capacity, buffer times, min notice) and book themselves.

Links & embed widget

Share a direct link, a per-service link, or drop an <iframe> booking widget straight into any website (Squarespace, Wix, WordPress).

Locations & Zoom

Each service can be in-person, an external URL, or Zoom — with auto-generated meeting links (unique per 1-on-1, shared for groups).

Client timezones

Visitors see slots in their own timezone alongside the business's — no more missed cross-timezone bookings.

Payments (Stripe Connect)

Set a price per service; each business connects their own Stripe account and is paid directly. The platform routes the payment.

Automatic emails

Branded confirmations, cancellations, and next-day reminders via Resend + Vercel Cron.

Real teams & roles

Invite teammates by email; they get their own login. Four built-in roles plus a custom role builder — permissions enforced server-side and at the database.

Reviews, branding, CRM

Customer ratings on the booking page, per-business logo + accent color, and a client book with visits, tags, and history.

Owner dashboard

Today/upcoming schedule, a monthly calendar, revenue & service-mix charts, live notifications, and a platform admin panel.

Tech stack

Next.js 14 (App Router)TypeScriptTailwind CSSSupabase (Postgres · Auth · Storage · RLS)Stripe Connect + BillingResendZoom (S2S OAuth)Vercel

Quick start

1

Create a Supabase project

Sign up at supabase.com → New project. In the SQL Editor, paste the entire supabase/schema.sql and run it — this creates every table, Row Level Security policy, the auto-onboarding trigger, and the storage bucket.

2

Add environment variables

Copy .env.local.example → .env.local and fill in your three Supabase keys, NEXT_PUBLIC_SITE_URL, and ADMIN_EMAILS. Email, payments, and Zoom are optional and can be added anytime.

3

Run it

npm install then npm run dev, and open localhost:3000. Create your account — your business and booking page are generated automatically.

4

Deploy to Vercel

Import the repo (or use the Vercel CLI), add the same env vars, and deploy. Then set your Supabase Auth Site URL + /auth/callback redirect to your live URL.

The full step-by-step guide (with every click) ships in SETUP.md.

Integrations

Every integration is optional and independent — the app degrades gracefully without any of them.

Email — Resend

Add RESEND_API_KEY + EMAIL_FROM. For real delivery, verify your domain in Resend. Powers confirmations, reminders, and team invites.

Payments — Stripe

Enable Connect ("you collect payments and pay recipients"), add your secret + webhook keys. Optionally create a monthly Pro price for the platform subscription.

Video — Zoom

Create a Server-to-Server OAuth app with the meeting:write:admin scope; add the three ZOOM_* keys to auto-generate meeting links.

Reminders — Vercel Cron

A daily job (vercel.json) emails tomorrow’s customers. Set CRON_SECRET in Vercel to secure it.

Environment variables

VariableRequired
NEXT_PUBLIC_SUPABASE_URLRequired
NEXT_PUBLIC_SUPABASE_ANON_KEYRequired
SUPABASE_SERVICE_ROLE_KEYRequired
NEXT_PUBLIC_SITE_URLRequired
ADMIN_EMAILSRequired
RESEND_API_KEY / EMAIL_FROMOptional
STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRETOptional
STRIPE_PRO_PRICE_IDOptional
ZOOM_ACCOUNT_ID / CLIENT_ID / CLIENT_SECRETOptional
CRON_SECRETOptional

Security & architecture

Multi-tenant isolation

Every row is scoped to a business via Postgres Row Level Security — one business can never read or write another’s data. The public booking page reads/writes through the server (service-role) so customers never touch other tenants’ data.

Server-enforced permissions

Team roles are enforced both in the UI and on the server: every mutating action checks the member’s permission, and the database restricts direct writes to owners — so a limited member can’t escalate via the API.

Hardened surface

Cryptographically-random booking tokens, HTML-escaped email templates, owner-gated billing, a secret rotatable calendar-feed token, and fail-closed cron — all reviewed in a dedicated security audit.

Going live

  • Turn "Confirm email" back ON in Supabase Auth.
  • Verify your sending domain in Resend and point EMAIL_FROM at it.
  • Activate Stripe, switch to live keys, and create a live-mode webhook.
  • Re-create the Pro price in live mode (if you use subscriptions).
  • Set CRON_SECRET in Vercel for reminders, and NEXT_PUBLIC_SITE_URL to your domain, then redeploy.

Troubleshooting

Everything shows sample data / no login

You’re in demo mode — the Supabase env variables aren’t set. Add them to switch to the real app.

Signup says "check your email"

Turn OFF "Confirm email" in Supabase Auth for testing, or ensure your Redirect URLs include /auth/callback.

Emails not arriving

On the shared Resend sender you can only email your own account address — verify a domain to reach anyone. New domains may land in spam at first; check Resend → Logs.

Payment button doesn’t appear

The service price is 0, the business hasn’t connected Stripe, or STRIPE_SECRET_KEY is unset. Priced services fall back to free until Stripe is connected.

column ... does not exist

The schema didn’t fully run — re-run supabase/schema.sql (safe on a fresh project).