Match therapists to patients
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Patients tap must-have tags. We show therapists who match some selected tag. Therapists publish a readable profile (photo, intro video, licenses, rates, cards). No booking.
Repo: github.com/mkirby42/kitchen_sink
Live: kitchen-sink-tau.vercel.app
Spec: docs/REQUIREMENTS.md. Prototype shots: prototype_screenshots/.
Node 22. Uses the hosted Supabase project. Demo seed therapists are removed by supabase db query --linked -f supabase/migrations/20260925043000_finish_demo_profile_removal.sql.
Open http://localhost:3000.檢視完整 README ↗Patients tap must-have tags. We show therapists who match some selected tag. Therapists publish a readable profile (photo, intro video, licenses, rates, cards). No booking.
Repo: github.com/mkirby42/kitchen_sink Live: kitchen-sink-tau.vercel.app
Spec: docs/REQUIREMENTS.md. Prototype shots: prototype_screenshots/.
Node 22. Uses the hosted Supabase project. Demo seed therapists are removed by supabase db query --linked -f supabase/migrations/20260925043000_finish_demo_profile_removal.sql.
git clone https://github.com/mkirby42/kitchen_sink.git
cd kitchen_sink
cp .env.example .env.local
# paste NEXT_PUBLIC_SUPABASE_URL + NEXT_PUBLIC_SUPABASE_ANON_KEY (see Reproduce the demo)
npm install
npm run dev
Open http://localhost:3000.
| Route | What |
|---|---|
/ | Home. Find a therapist, or create a therapist profile / log in |
/find | Public search |
/t/[id] | Therapist profile (owner sees Edit) |
/join | Therapist onboarding (auth). Returning therapists sign in from home and land on their profile. Sign-in links to forgot password |
/forgot-password | Request a password reset email (therapist, client, admin) |
/reset-password | Set a new password from the email link |
/admin/media | Ops helper upload: photo + intro video for an existing therapist (admin). Sign-in links to forgot password |
/admin/reviews | Ops review queue: approve to publish, or reject and hard-delete (admin). Sign-in links to forgot password |
/robots.txt | Crawler rules (search + named AI bots allowed; /admin disallowed) |
/sitemap.xml | Public URLs: home, find, join, open therapist profiles |
/llms.txt | Plain-language summary for AI tools |
npm run lint && npm run typecheck && npm test && npm run build
Next.js 16 App Router · TypeScript · Tailwind · @supabase/ssr + @supabase/supabase-js · hosted Supabase (Auth, Postgres, Storage) · Vercel · GitHub Actions
flowchart LR
Browser --> Next["Next.js on Vercel"]
Next --> Auth[Supabase Auth]
Next --> RPC["Postgres RPCs + RLS"]
Next --> Store[Storage photos / videos]
RPC --> DB[("profiles · therapists · tags · rates · licenses · reviews")]
/find calls one RPC, search_therapists — OR overlap on selected tags, ranked by match count, page size 24./t/[id] loads one therapist (photo + native <video> intro). The owner sees Edit (header, top right)./join is a 4-step therapist wizard. Continue does not require a photo or intro video. Publishing requires both (video up to 50MB). Returning therapists sign in from home and land on their profile; Save changes calls update_therapist_profile.proxy.ts refreshes the Supabase session. Schema lives in supabase/migrations/.*@kitchensink.demo) are not part of that list once the removal migration has been applied. Hidden profiles (therapists.listed = false) stay in the database and off Find.Create a .env.local from the sample below. Keys come from the Supabase project API page (anon / publishable key only). Server-only RESEND_API_KEY sends Join “Feedback for us” to the team. Optional RESEND_FROM is the verified sender.
# .env.local — copy from .env.example
NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOi... # anon / publishable, not service_role
Then npm install && npm run dev and follow Option A on localhost.
/admin/media and /admin/reviews need an admin you create yourself. In the Supabase Dashboard: Authentication → Users (confirm the email), then grant role = admin in the SQL editor. Never commit a password. Migrations do not ship a shared ops login.
photos and videos.supabase/migrations/ in filename order (supabase db push against the linked project, or the SQL editor). The demo-account wipe runs in that history. 20260925170000_remove_seeded_ops_admin.sql deletes a previously seeded ops admin when its id and email both still match, and a fresh apply does not create one. Grant your own admin in the Dashboard. Never commit a password..env.local.npm run dev. Join as a therapist to put a real profile in search.npm run seed:media signs in as the removed demo users and will fail after that migration. Do not re-run the historical seed SQL against production.
Travis White is applied separately, and only to project udgngzzzgrxjxljgtxpf:
SUPABASE_ACCESS_TOKEN=sbp_... \
SUPABASE_SERVICE_ROLE_KEY=eyJ... \
NEXT_PUBLIC_SUPABASE_URL=https://udgngzzzgrxjxljgtxpf.supabase.co \
npm run apply:travis-white
DATABASE_URL can replace SUPABASE_ACCESS_TOKEN when psql is installed. The script creates a therapist auth user for [email protected] with an unknown password. Claim it from /forgot-password, sign in at /join?mode=signin, then Edit. Re-runs update that profile and the intro video in place and do not reset the password. They do not assign photo_key on an existing row, and they skip the photo upload when that key is null. A brand-new insert still sets photo_key to {id}/photo.jpg and uploads it. On the hosted project the auth user is 3b354f1e-50a1-4a17-b536-cc7fce1296fe; the script refuses to insert a second user for that email or to retarget a different account that already has that id.
SUPABASE_SERVICE_ROLE_KEY is server-only. Tests and seed:media do not need it. Starting a therapist draft (/admin/starts) does: it creates that therapist's login and the "draft is ready" link. Never put the service role in the browser, Vercel public env, or git. npm run apply:travis-white also needs it, plus either SUPABASE_ACCESS_TOKEN (database write) or DATABASE_URL.
Demo seeds are not real clinicians. Travis White is a real therapist, applied with npm run apply:travis-white, not by a migration. No third-party health registry was imported.
| What | Where | Provenance |
|---|---|---|
| Maya Chen (LMFT, CA, rates, cards, 3 reviews) | supabase/migrations/20260919163316_seed_maya_chen.sql | Written to match prototype_screenshots/. Removed from hosted data by 20260925003000_remove_seed_demo_profiles.sql when id and [email protected] both match. |
| 10 more open therapists + reviews | supabase/migrations/20260919184500_seed_demo_therapists.sql | Synthetic profiles. Same removal rule: seed UUID and *@kitchensink.demo email. |
| Seed patients J.R., Priya S., D.M. | same Maya seed | Prototype reviewer names. Removed with the same id + email rule. |
| Tag / credential / insurance chips | lib/tags/presets.ts + requirements | Prototype + spec labels, not a published taxonomy |
| Headshots + intro clips | supabase/seed/media/<uuid>/ | Synthetic portraits. The removal migration nulls Storage ownership for matched seed ids. Hosted Storage rejects SQL deletes; remove the objects with the Storage API. |
| Travis White (PsyD, Austin) | scripts/apply-travis-white-profile.mjs | Real profile from thetalkshoppeatx.com and his Psychology Today page. Photo and intro video live in scripts/travis-white/. Not a @kitchensink.demo account, so the demo wipe does not remove it. |
Demo seed license numbers, phones, and addresses are fake. Reviews on those seeds are fiction. Travis White's license, phone, address, and rates are the ones published on his practice site and Psychology Today. Those pages do not say how many years he has been practicing, so start_date_of_practice stays null.
mailto: / tel: from listed outreach./admin/reviews. Reject and delete remove the row; nothing archives it. Demo seed reviews are removed with the demo profiles.These are product gaps, not a freeze. See REQUIREMENTS Not built yet.
| File | What |
|---|---|
| docs/REQUIREMENTS.md | Current product, backlog, schema, matching, CI |
| AGENTS.md | How agents work in this repo |
| prototype_screenshots/README.md | Screen → screenshot map |
GitHub Actions on PR and main: lint, typecheck, tests, build. The e2e job seeds the test Supabase project and runs Playwright against next start in the job. Push to main deploys production to Vercel after the check job passes. The deploy does not wait on e2e. PRs still get Vercel previews.
Repo secrets: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, VERCEL_DEPLOY_HOOK (production). Browser tests use TEST_SUPABASE_URL, TEST_SUPABASE_ANON_KEY, and TEST_SUPABASE_SERVICE_ROLE_KEY for project kxlonrjirrrjiinclamc only. Never put the production service role key in CI.