Go Live in 30 Minutes
Connect your real credentials to switch from demo mode to a fully operational SaaS.
The site is fully functional for testing: auth modals open, reports gate correctly, and Stripe buttons fire — but no data is persisted and no real payments are processed. Complete the steps below to go live.
Step 1 · Supabase — Auth & Database
Time: ~10 minutes · Cost: Free tier
Supabase handles user accounts, email verification, and your subscriber list.
1.1 Create a project
- Go to supabase.com and click New Project
- Choose a region close to your users (EU West for Spain-based)
- Save the database password somewhere secure
1.2 Get your API keys
From your project dashboard → Settings → API:
| Key | Where it goes |
|---|---|
| Project URL | hugo.toml → supabaseUrl |
| anon / public key | hugo.toml → supabaseAnonKey |
| service_role key ⚠️ | GitHub Actions secret only — never in frontend |
1.3 Run the database migration
Open Supabase → SQL Editor and paste this to create the profiles table:
-- Sync auth users to a public profiles table
create table if not exists public.profiles (
id uuid references auth.users(id) on delete cascade primary key,
email text unique not null,
plan text not null default 'free',
created_at timestamptz default now()
);
alter table public.profiles enable row level security;
create policy "Users can read own profile" on public.profiles
for select using (auth.uid() = id);
-- Auto-create profile on signup
create or replace function public.handle_new_user()
returns trigger language plpgsql security definer as $$
begin
insert into public.profiles (id, email)
values (new.id, new.email)
on conflict (id) do nothing;
return new;
end;
$$;
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
1.4 Update hugo.toml
[params]
supabaseUrl = "https://YOUR_PROJECT_ID.supabase.co"
supabaseAnonKey = "YOUR_ANON_KEY_HERE"
After this, rebuild and redeploy — the amber demo banner will disappear automatically.
Step 2 · Stripe — Payments
Time: ~15 minutes · Cost: 2.9% + 30¢ per transaction
2.1 Create products in Stripe dashboard
Go to dashboard.stripe.com/products and create:
| Product | Price | Billing |
|---|---|---|
| Early Access | $9.99 | Monthly recurring |
| Professional | $29.99 | Monthly recurring |
Copy the Price ID (looks like price_1ABC...) for each plan.
2.2 Create a Supabase Edge Function for checkout
In your terminal (from the project root):
supabase functions new create-checkout
Paste this into supabase/functions/create-checkout/index.ts:
import Stripe from 'https://esm.sh/stripe@14?target=deno'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY')!, { apiVersion: '2024-06-20' })
Deno.serve(async (req) => {
const { priceId } = await req.json()
const authHeader = req.headers.get('Authorization')!
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_ANON_KEY')!,
{ global: { headers: { Authorization: authHeader } } }
)
const { data: { user } } = await supabase.auth.getUser()
if (!user) return new Response('Unauthorized', { status: 401 })
const session = await stripe.checkout.sessions.create({
customer_email: user.email,
line_items: [{ price: priceId, quantity: 1 }],
mode: 'subscription',
success_url: `${req.headers.get('origin')}/dashboard/?checkout=success`,
cancel_url: `${req.headers.get('origin')}/pricing/`,
metadata: { supabase_user_id: user.id }
})
return Response.json({ url: session.url })
})
Deploy it:
supabase functions deploy create-checkout \
--project-ref YOUR_PROJECT_ID
supabase secrets set \
STRIPE_SECRET_KEY=sk_live_... \
--project-ref YOUR_PROJECT_ID
2.3 Add GitHub Actions secrets
In your GitHub repo → Settings → Secrets → Actions, add:
STRIPE_SECRET_KEY— your Stripe secret key (sk_live_...)STRIPE_WEBHOOK_SECRET— from Stripe → Webhooks → your endpointSUPABASE_URL— your project URLSUPABASE_SERVICE_ROLE_KEY— service role key (for admin writes)RESEND_API_KEY— from Step 3
Step 3 · Resend — Email Alerts
Time: ~5 minutes · Cost: Free up to 3,000 emails/month
Resend handles your weekly distress alert emails with high deliverability.
3.1 Set up a domain
- Go to resend.com → Domains → Add Domain
- Add
distresssignal.email(or your domain) - Add the DNS records they give you (takes ~10 min to verify)
3.2 Get an API key
Resend dashboard → API Keys → Create API Key → copy it.
3.3 Test the alert script locally
cd scripts/
pip install resend supabase
RESEND_API_KEY=re_... python send_alerts.py --dry-run
This will print the emails that would be sent without actually sending anything.
Step 4 · Deploy & Verify
Once all three sets of credentials are in place:
# 1. Rebuild the site (demo banner disappears)
hugo --minify
# 2. Push to trigger Netlify auto-deploy
git add hugo.toml
git commit -m "chore: connect live Supabase credentials"
git push origin main
Verification checklist:
- Amber demo banner is gone from every page
- Sign-up modal creates a real account in Supabase → Authentication → Users
-
/signup/redirects to/reports/after login - Stripe checkout redirects to Stripe’s hosted page
- Email arrives after clicking “Subscribe” in footer
Estimated Time to Go Live
| Step | Time |
|---|---|
| Supabase project + migration | ~10 min |
| Stripe products + Edge Function | ~15 min |
| Resend domain verification | ~15 min (mostly waiting for DNS) |
| Rebuild & deploy | ~3 min |
| Total | ~45 minutes |