尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Multi-sided marketplace for the DIY / local live music scene. Bands sync calendars, assemble 3–4 act bills on mutually open dates, pitch turnkey packages to venues, and hold each other accountable via a double-blind 3-way rating system.
Full product spec: bandmeld PRD.md.
Stack: Next.js 16 (App Router) · React 19 · Tailwind 4 · Supabase (@supabase/ssr) · TypeScript (strict).
| Phase | Scope | Status |
|---|---|---|
| 1 — Trojan Horse | Member calendar sync · Band EPK · Shareable public band page | In progress (this repo) |
| 2 — Network | Band-to-band Bill Builder · Local photographer directory · 3-way ratings | Not started |
| 3 — Venue marketplace | Shareable pitch pages · Inbound open-slot board · Verified draw stats | Not started |
| 4 — Mobile + monetization | React Native app · Escrow / door splits | Not started |
Built:
create_band RPC (makes creator admin, enforces unique slug) + create-band formsync_band_open_dates RPC (next 366 days, member unavailability → actively_seeking) + preferred gig days filterband-assets storage bucket (logo / press / rider), admin-write / public-readactively_seeking ↔ penciled_in ↔ booked) + conflict detection — app/dashboard/bands/[bandId]/availability/page.tsxband_invites table, email-locked tokens, /invite/[token] accept flow preserving token through sign-up — app/invite/[token]/page.tsx.ics upload-only import — app/dashboard/availability/import/ics/page.tsx, lib/ics.ts (on feat/apple-ics-fallback)feat/vault-oauth-tokens)fix/last-admin-guard)Still open:
npm install
cp .env.example .env.local # fill in URL + publishable key
# Apply both migrations to your Supabase project
npx supabase login
npx supabase link --project-ref <your-ref>
npm run db:push # runs supabase/migrations/* in order
npm run db:types # optional: regenerate types from the live DB
npm run dev
No CLI? Paste the two files in supabase/migrations/ into the SQL Editor, in order.
Auth settings (Supabase dashboard):
http://localhost:3001 (add your Vercel URL later), and add http://localhost:3001/auth/confirm and http://localhost:3001/auth/google/callback to Redirect URLs.{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email&next=/dashboardUsers can click Connect Google Calendar on /dashboard/availability to link their Google account and pull busy events into member_unavailabilities. Setup is a one-time dance:
Google Cloud Console
calendar.events scope)..../auth/calendar.events (covers both reading the user's events for import AND writing confirmed show dates back to their calendar). Save.https://<your-ref>.supabase.co/auth/v1/callback (yes, Supabase's, not ours — Supabase proxies the flow).Supabase dashboard
http://localhost:3001/auth/google/callback (and the prod equivalent later).This app's .env.local — same values as step 2, needed server-side to refresh access tokens:
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
The flow: user clicks the button → supabase.auth.linkIdentity('google', …) (not signInWithOAuth, so we don't create a second account) → Google consent → /auth/google/callback captures provider_token + provider_refresh_token into public.google_calendar_connections → redirects to /dashboard/availability/import for review. Preselect rules (one-offs + 2+ day blocks on, recurring series off) match band snap PRD.md §3.1.
proxy.ts Refreshes Supabase session; guards /dashboard (Next 16 name for middleware.ts)
utils/supabase/
client.ts Browser client for "use client" components
server.ts Per-request server client + getUserId()/requireUserId()
proxy.ts updateSession() used by root proxy.ts
env.ts Fails loudly on missing env vars
types/
database.types.ts Database type (same format as `supabase gen types`)
index.ts Aliases: Band, Profile, GigStatus, PublicEpk, ActionResult…
lib/
epk.ts getPublicEpk(slug) — cached, shared by page + metadata
embeds.ts Spotify / YouTube URL → safe embed URL
components/auth/auth-form.tsx Client form: useActionState + sonner toasts
app/
(auth)/login, signup, actions.ts Server Actions: signIn / signUp / signOut
auth/confirm/route.ts Email-link → session (the only route handler)
dashboard/ Auth-guarded: band list, new band, band settings, availability
bands/[slug]/ Public EPK (+ not-found)
supabase/migrations/
20261022000000_initial_schema.sql Original schema
20261022000100_rls_and_rpc.sql RLS fixes, create_band, availability engine, storage
20261024000000_google_calendar.sql google_calendar_connections (OAuth tokens, owner-only RLS)
lib/google-calendar.ts Google Calendar v3 client: token refresh, event list, classify
app/auth/google/callback/ OAuth landing: exchanges code → stores provider tokens
await createClient() from utils/supabase/server. No /api/* routes.ActionResult → shown with toast in a client component.supabase.rpc("create_band", {...}) returns the new band id — direct INSERT is blocked on purpose (the RPC also makes you admin). Unique-slug clash = Postgres error code 23505.supabase.rpc("sync_band_open_dates", { p_band_id }) (admins). Covers the next 366 days: adds free dates as actively_seeking, removes seeking dates that now conflict, and never touches penciled_in / booked / unavailable.profiles from public pages.band-assets, path {band_id}/{logo|press|rider}/{file}. Only that band's admins can write; files are publicly readable.getClaims() (verifies JWT), never getSession()..github/workflows/db-migrate.yml runs supabase db push on every push to master that touches supabase/migrations/**. Set these repo secrets (GitHub → Settings → Secrets and variables → Actions):
SUPABASE_ACCESS_TOKEN — personal access token from https://supabase.com/dashboard/account/tokensSUPABASE_PROJECT_REF — the 20-char slug from the Supabase dashboard URLSUPABASE_DB_PASSWORD — database password (Supabase → Settings → Database)Already-applied migrations are no-ops, so the workflow is safe to re-run (or trigger via Actions → Supabase migrations → Run workflow).
user_role enum exists but no column uses it yet (likely profiles.primary_role once venues/creatives onboard).YYYY-MM-DD strings. Standardize before shipping both widely.