mirror of
https://github.com/tiennm99/llmapikey.git
synced 2026-06-17 12:48:54 +00:00
02fa52ccf9ae6879ccacd66909347e50625c6b3f
- Next.js 15 App Router (JS+JSDoc): landing, auth-gated dashboard, docs - GitHub OAuth via Supabase; identity anchored on numeric provider_id - key provisioning: reserve-then-mint-persist-compensate, one key per account - api_keys in unexposed llmapikey schema via direct Postgres; RLS deny-all - live minting gated behind PROVISIONING_ENABLED; Vercel auto-deploy disabled - unit tests (mask, request-body), RLS deny-all test, reconcile script
llmapikey
Free, capped OpenRouter API key giveaway — one key per GitHub account.
Next.js (App Router, JS + JSDoc) on Vercel. GitHub sign-in via Supabase Auth.
Per-user OpenRouter keys are minted from the owner's master Provisioning key,
each capped at a daily USD limit. Key records live in a dedicated, unexposed
llmapikey Postgres schema reached only by a server-side direct connection.
Status: code build only. Live key minting is gated behind
PROVISIONING_ENABLED=falseuntil the OpenRouter ToS approval gate (plan Phase 1) clears. Do not deploy a public giveaway before that.
Stack
- Next.js 15 App Router, plain JS + JSDoc (no TypeScript)
- Supabase Auth — GitHub OAuth provider (sessions via
@supabase/ssr) - Postgres (
postgresnpm) — direct connection to the unexposedllmapikeyschema; the anon role can never reachapi_keys - OpenRouter Provisioning API — mints per-user keys
Architecture notes
- Identity anchor: the numeric, immutable GitHub
provider_id(not the mutable login). One key pergithub_user_id, enforced by a DB unique constraint. - Server-only secrets:
DATABASE_URLandOPENROUTER_PROVISIONING_KEYare guarded by theserver-onlypackage and never reach the client bundle. - Reserve-then-mint: a
pendingrow is inserted (ON CONFLICT DO NOTHING) before minting, so concurrent double-submits yield exactly one OpenRouter key. - Schema isolation:
llmapikeyis NOT added to PostgREST exposed schemas; RLS is deny-all as defense in depth.
Setup
- Install
npm install - Environment — copy
.env.exampleto.env.localand fill in values.Var Purpose NEXT_PUBLIC_SUPABASE_URLSupabase project URL (public) NEXT_PUBLIC_SUPABASE_ANON_KEYSupabase anon key (public, auth UI only) DATABASE_URLSupabase transaction pooler string (server-only) OPENROUTER_PROVISIONING_KEYMaster Provisioning key (server-only) NEXT_PUBLIC_REPO_URLRepo URL for the soft star nudge NEXT_PUBLIC_OPENROUTER_MODELModel id shown in /docsPROVISIONING_ENABLEDfalseuntil Phase 1 ToS gate clearsMAX_TOTAL_KEYSKill-switch: stop minting past N active keys KEY_DAILY_LIMIT_USDPer-key daily cap sent to OpenRouter KEY_EXPIRY_DAYSKey lifetime (sets expires_at) - Database — apply the migration to a staging branch first, then prod
(Supabase SQL editor or
psql "$DATABASE_URL" -f ...):Do NOT addpsql "$DATABASE_URL" -f supabase/migrations/0001_llmapikey_schema_and_api_keys.up.sqlllmapikeyto the project's PostgREST "Exposed schemas". Rollback:...0001_...down.sql. - GitHub OAuth — register a GitHub OAuth App; set the client id/secret in
the Supabase dashboard (Auth > Providers > GitHub), callback
https://<project>.supabase.co/auth/v1/callback. Add localhost + your Vercel domain to Supabase Auth redirect URLs. - Run
npm run dev # http://localhost:3000 npm test # unit tests
Deploy (gated)
Auto-build on Vercel is intentionally disabled (see vercel.json). Promote
manually once the Phase 1 ToS gate clears and PROVISIONING_ENABLED=true.
Description
Languages
JavaScript
95.9%
CSS
4.1%