Endless personality quizzes — discover who you really are.
- Frontend: React + Vite + Tailwind CSS
- Backend: Supabase (auth + database)
- Hosting: Cloudflare Workers
- iOS app: Capacitor shell in
ios-app/— same bundle, no second codebase
Quizzes are data, not pages. To ship a new one:
- Create
src/data/quizzes/<key>.jsfollowing the spec documented at the top ofsrc/data/quizzes/index.js(pickmode for archetype quizzes,likertfor agree/disagree assessments — seenaruto.jsandgrit.jsas examples). - Register it in the
QUIZ_CATALOGarray insrc/data/quizzes/index.js(metadata + a lazyload()import — quiz data is code-split per quiz). - Run
npx vitest run src/data/quizzes/catalog.test.js— it structurally validates every quiz (reachable results, valid point targets, required display fields, engine smoke tests).
That's it: routing (/quiz/<key> + /quiz/<key>/result), scoring, result
rendering, sharing, dashboard/landing cards, and the next-quiz journey all
pick the quiz up from the catalog automatically. Database saves require the
quiz key to match ^[a-z][a-z0-9_]{1,31}$ (enforced by
supabase/migrations/20260720000004_expand_quiz_catalog.sql).
The App Store build lives in ios-app/. It is a
Capacitor shell around this same web bundle — there is no separate app
codebase, and native behaviour is a handful of branches in src/ guarded by
isNativeApp() (src/lib/native.js), all inert in a browser.
cd ios-app && npm install && npm run sync && npm run open # macOS + Xcode onlyAnything under src/ reaches the app on the next npm run sync. Three account-
level steps must be done before it can be submitted — the native OAuth redirect
in Supabase, the Sign in with Apple provider, and applying
supabase/migrations/20260807000001_add_account_deletion.sql. ios-app/README.md
walks through each. ios-app/capacitorConfig.test.js runs in the normal
npm test and fails if the app id, URL scheme, and plugin versions drift apart
across the config, the Xcode plist, and src/utils/deepLink.js.
If your site is showing a GoDaddy parking/landing page instead of your app, the domain's nameservers haven't been pointed to Cloudflare yet. Follow these steps:
- Log in to Cloudflare
- Click Add a Site and enter
mypersonalityquizzes.com - Choose the Free plan
- Cloudflare will scan your existing DNS records — review them and continue
- Cloudflare will give you two nameserver addresses (e.g.
anna.ns.cloudflare.comandbart.ns.cloudflare.com)
- Log in to GoDaddy
- Go to My Products → Domains → mypersonalityquizzes.com → Manage
- Scroll to Nameservers and click Change
- Select Enter my own nameservers
- Replace the existing nameservers with the two Cloudflare nameservers from Step 1
- Save
Note: DNS propagation can take up to 48 hours, but usually completes within a few hours. Wait for Cloudflare to send you an email confirming your domain is active before proceeding.
The GitHub Actions deployment uses the CLOUDFLARE_API_TOKEN secret to upload
the Worker and register its custom domains. Create a dedicated token from the
Edit Cloudflare Workers template and restrict it to the production
Cloudflare account and the mypersonalityquizzes.com zone.
- Account → Workers Scripts → Edit
Do not add Zone Read or DNS Edit to the deployment token. Workers Custom Domains create the required DNS records and certificates through the Workers API. Keep one token for deployment and use a separate, temporary token for any future DNS administration.
Store the token and account ID as the CLOUDFLARE_API_TOKEN and
CLOUDFLARE_ACCOUNT_ID GitHub Actions secrets. Rotate the deployment token
after any one-time DNS setup.
Once your domain is active in Cloudflare and the GitHub secrets are configured,
go to GitHub → Actions → Deploy to Cloudflare Workers → Run workflow. The
workflow runs the full quality gate, deploys the Worker, and then smoke-tests
the apex domain, www, the share Worker route, and the branded auth domain.
Wrangler will use the custom-domain entries under routes in wrangler.jsonc
to wire up mypersonalityquizzes.com and www.mypersonalityquizzes.com to the
Worker.
Important: GitHub Actions is the only production deployment authority. Keep Cloudflare Workers Builds disconnected for this repository so a second build token cannot create duplicate deployments or conflicting checks.
npm install
npm run devCreate a .env file based on .env.example and fill in your Supabase credentials.
npm run check
npx wrangler deploy --dry-runPush or merge to main to deploy production through GitHub Actions. Do not
deploy production locally or connect Cloudflare Workers Builds.
Apply new files in supabase/migrations/ to the production Supabase project in
filename order before deploying frontend features that depend on them. The app
degrades safely during a rolling deployment, but the migrations are required
for hardened share tokens, admin account-email access, atomic guest-result
sync, and the security event log behind the admin dashboard's Security panel.
The Worker renders Open Graph metadata for /s/:id by calling Supabase
server-to-server, so without this secret Supabase sees the Worker's own egress
address and every visitor shares one per-IP rate-limit bucket. Setting it lets
the Worker forward the real visitor IP, which the database accepts only when
the accompanying secret matches.
# 1. Generate a secret
openssl rand -hex 32
# 2. Store it in Supabase (SQL editor)
# UPDATE public.edge_config SET share_proxy_secret = '<the value>';
# 3. Store the same value in Cloudflare
npx wrangler secret put SHARE_PROXY_SECRETBoth halves must match. With neither set — the default after migrating — the Worker sends no forwarding headers and the database ignores them, so behaviour is unchanged. Rotate by updating the database first, then Cloudflare.