Static landing page + Supabase Edge Function backend for pilot onboarding. The UI lives on any static host (GitHub Pages), while a Supabase function receives submissions, stores them (with Geo-IP country) in Postgres, and sends owner notifications via Mailgun.
Visitor ─► GitHub Pages (index.html, admin.html)
│
fetch https://<project>.functions.supabase.co/functions/v1/database-access
│
Supabase Edge Function
│
Postgres (applications table) + Mailgun API
If the function is unreachable, the UI falls back to localStorage so leads are not lost; the admin page can still view those cached entries.
- Install the Supabase CLI and log in:
supabase login supabase link --project-ref YOUR_PROJECT_REF
- Configure secrets (service role key, admin password, Mailgun, etc.):
supabase secrets set \ ADMIN_PASSWORD="set-a-strong-password" \ SUPABASE_URL="https://YOUR_PROJECT.supabase.co" \ SUPABASE_SERVICE_ROLE_KEY="service-role-key" \ MAIL_FROM="MB3R Lab <noreply@mb3r-lab.org>" \ MAILGUN_API_KEY="key-..." \ MAILGUN_DOMAIN="mg.example.com" \ MAIL_NOTIFY_TO="owner@company.com" \ ALLOWED_ORIGINS="https://mb3r-lab.github.io,http://localhost:5500" # Optional: MAILGUN_API_BASE_URL=https://api.eu.mailgun.net/v3 # Optional admin brute-force controls: # ADMIN_MAX_FAILED_ATTEMPTS=8 # ADMIN_ATTEMPT_WINDOW_MS=600000 # ADMIN_BLOCK_MS=600000 # ADMIN_BASE_DELAY_MS=400 # ADMIN_MAX_DELAY_MS=5000
- Deploy the function:
If production still uses the legacy endpoint name, deploy the same code as:
supabase functions deploy applications --project-ref YOUR_PROJECT_REF
The function expects an existingsupabase functions deploy database-access --project-ref YOUR_PROJECT_REF
public.applicationstable (see SQL below).
Edit assets/js/config.js and set the function URL (no trailing slash):
window.__MB3R_API_ENDPOINT__ =
'https://YOUR_PROJECT_ID.functions.supabase.co/functions/v1/database-access';Production currently uses the legacy endpoint database-access. If you deploy this repo's
applications function name, switch frontend config to /functions/v1/applications.
Push the static site (e.g., to GitHub Pages). The landing page and /admin.html will now send all API calls to the Supabase function.
- CTA + modal form — collects email/company/context and sends the payload to the Supabase function.
- Supabase storage — submissions persist in
public.applications; schema (includingcountrycolumn) is auto-created on first call. - Mailgun owner notifications — the function posts to Mailgun so the owner mailbox receives every new lead.
- No auto-reply to requester — submitters are not emailed automatically; follow-up is manual from the owner side.
- Admin dashboard —
/admin.htmllists submissions and supports deleting requests. Access requires the password that you stored in the function secret (x-admin-passheader). If the function is offline, the dashboard shows the locally cached leads. - Offline fallback — when the API is unreachable (or not configured) leads are saved in
localStorage, so you can later recover them from/admin.
The deployed function handles:
POST /database-access— validate payload, insert intoapplications, send owner notification toMAIL_NOTIFY_TO(if configured), respond with the created ID.GET /database-access— requirex-admin-passheader, validate requestOriginagainstALLOWED_ORIGINS, apply per-client failed-login throttling (delay + temporary block), return ordered submissions.DELETE /database-access— requirex-admin-pass, accept{ "id": <number> }, delete one request by ID.OPTIONS— CORS preflight for allowlisted origins (content-type+x-admin-passheaders).- Schema requirement — create the table once in Supabase (SQL editor):
create table if not exists public.applications ( id bigint generated by default as identity primary key, email text not null, company text not null, comment text, country text, created_at timestamptz not null default now() );
Run this manually after linking the project; the function assumes the table already exists.
## Local testing
1. Duplicate your secrets in a local `.env.functions` file (key=value per line).
2. Run the function locally:
```bash
supabase functions serve applications --env-file .env.functions
- Update
assets/js/config.jsto point at the local URL printed by the CLI (for this repo function name:http://127.0.0.1:54321/functions/v1/applications), run a local static server (for examplepython -m http.server 5500), and test viahttp://localhost:5500/index.html.
Remember to switch config.js back to the production URL before committing.