BibleWeb is in private beta. Rather than open sign-up, access to higher-tier features is granted by distributing short activation codes. This system lets invited users unlock their tier — with or without a Supabase account — by entering a code on the /activate page.
/activate, enters a code, and submits the form.beta_tier field is written to Supabase app_metadata via the admin service-role client. This persists across sessions and devices.bibleweb_beta_tier cookie is set (1-year expiry, samesite=lax, readable client-side). On the client, the same cookie is also set directly via document.cookie as a backup.beta_high, beta_low, or admin), an "already active" message is shown without re-processing.Status states: idle | success | invalid | already_active | error
Known codes (from beta-codes.ts):
| Code | Tier |
|---|---|
vriend |
beta_high |
friend |
beta_high |
beta |
beta_low |
uitproberen |
beta_low |
Code matching is case-insensitive, trimmed.
AI daily limits per tier:
| Tier | Daily AI queries |
|---|---|
admin |
999 |
beta_high |
20 |
beta_low |
5 |
free |
0 |
max-width: 26rem), dark popup background, rounded corners.autocomplete="off" / autocorrect="off" — styled for entering codes, not typing prose.… while loading.musicforhours@gmail.com.activate.title from i18n.Route: apps/web/src/routes/(app)/activate/+page.svelte
API: POST /api/beta/activate (apps/web/src/routes/api/beta/activate/+server.ts)
429 with Retry-After on breach.getBetaTier(session, cookies.get('bibleweb_beta_tier')).validateBetaCode(code) — returns 'beta_high' | 'beta_low' | null.adminClient.auth.admin.updateUserById() to write app_metadata.beta_tier.cookies.set('bibleweb_beta_tier', tier, ...).Core logic: apps/web/src/lib/server/beta-codes.ts
BETA_CODES — static Record<string, 'beta_high' | 'beta_low'> lookup.getBetaTier(session, cookieBetaTier) — priority order: admin email check → app_metadata.beta_tier → cookie fallback → 'free'.getAiDailyLimit(betaTier) — returns the daily AI query limit for a given tier.validateBetaCode(code) — normalises and looks up a code.Admin detection: compares session.user.email to process.env.ADMIN_EMAIL. Returns 'admin' tier if matched.
Fully implemented. Code table, API endpoint, Supabase metadata write, cookie fallback, and the activation UI are all in place. To add new beta codes, update BETA_CODES in beta-codes.ts. To extend tier logic, update getBetaTier and getAiDailyLimit in the same file.