SpinAI is configured entirely through environment variables — there are no config files to edit beyondDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/fmoraga01/SpinAI/llms.txt
Use this file to discover all available pages before exploring further.
.env.local for local development and the equivalent secret/variable panels in Vercel and GitHub Actions for production. This page documents every variable, explains the authentication model, and covers the minimal Next.js configuration that ships with the project.
Environment Variables
Supabase Connection
The base URL of your Supabase project. Found in your Supabase dashboard under Settings → API → Project URL.This variable is prefixed with
NEXT_PUBLIC_ because lib/supabase.ts initialises the Supabase client in both server and browser contexts using createClient. It is safe to expose to the browser because access is further restricted by Row Level Security policies and the application-layer PIN gate.The anon/public API key for your Supabase project. Found in Settings → API → Project API keys → anon public.The anon key is used for all database operations (
members, assignments, templates, assignment_logs). The migration in supabase/migrations/20260702000000_esquema_inicial.sql creates anon full access RLS policies on all four tables so that these operations succeed without Supabase Auth.Authentication
The team access PIN. Users must enter this value on the PIN gate before they can access any page. The comparison is case-insensitive — the value you set here is compared to user input after both are normalised.Choose a value that is easy for your team to remember but not trivially guessable. You can change it at any time by updating the variable and redeploying; existing sessions will remain valid until their 30-day expiry.
The secret used to sign and verify session tokens with the HS256 algorithm. SpinAI uses the Generate a strong value with:If this variable is not set, the middleware falls back to the string
jose library (jwtVerify / SignJWT) to issue a token on successful PIN entry and verify it on every subsequent request via middleware.ts."fallback-secret-change-me". Always set a real secret in production.Email (Gmail SMTP)
The Gmail address that SpinAI uses as the sender for all notification emails.This address appears in the From field of every email sent by Nodemailer. It is also used as the SMTP authentication username.
The Gmail App Password for the To generate an App Password: open Google Account → Security → 2-Step Verification → App passwords, select Other (custom name), name it
GMAIL_USER account. This is a 16-character password generated specifically for SpinAI — it is not your regular Google account password.SpinAI, and copy the generated password. Gmail SMTP rejects regular account passwords when 2-Step Verification is enabled.Automation (GitHub Actions Cron)
A shared secret that the GitHub Actions weekly cron job sends in the Generate a strong value with:
x-cron-secret HTTP request header when it calls the SpinAI notification API. The API handler validates this header before sending any email.PIN and JWT Authentication
SpinAI protects every route with an application-layer PIN gate backed by a signed JWT cookie. No Supabase Auth or third-party identity provider is involved.How the flow works
- A user visits any page. The middleware (
middleware.ts) checks for a cookie namedspinai_token. - If the cookie is absent or its JWT signature is invalid, the middleware sets the
x-spinai-auth: 0response header. The root layout reads this header and renders the PIN entry form instead of the requested page. - When the user submits the correct PIN, the
/api/authroute issues a new JWT signed withJWT_SECRETusing the HS256 algorithm, valid for 30 days. - The token is written as an
HttpOnlycookie namedspinai_token:- HttpOnly — not accessible from JavaScript, preventing XSS token theft.
- Secure — sent only over HTTPS in production.
- SameSite=lax — prevents the cookie from being sent on cross-site POST requests while still allowing top-level navigations.
- On every subsequent request,
middleware.tscallsjwtVerifyfromjoseagainst the sameJWT_SECRET. A valid token allows the request through; an expired or tampered token falls back to the PIN gate.
Cookie details at a glance
| Property | Value |
|---|---|
| Cookie name | spinai_token |
| Algorithm | HS256 |
| Expiry | 30 days |
| HttpOnly | Yes |
| Secure | Yes (production) |
| SameSite | lax |
Excluded routes
The middleware matcher excludes_next/static, _next/image, and favicon.ico so that static assets load without a valid session. The /api/auth route is also explicitly allowed through before any token check so that the login request itself is never blocked.
Next.js Configuration
SpinAI ships with a minimalnext.config.ts that contains no custom options beyond the empty default:
Quick Reference
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | ✅ Always | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | ✅ Always | Supabase anon/public API key |
PIN | ✅ Always | Team access PIN (case-insensitive) |
JWT_SECRET | ✅ Always | Secret for signing 30-day HS256 session tokens |
GMAIL_USER | ✅ For email | Gmail sender address |
GMAIL_PASS | ✅ For email | Gmail App Password |
CRON_SECRET | ✅ For automation | Shared secret for GitHub Actions cron requests |