Private professional network for verified Herzliah alumni.
Translation pending
SocialGitHub @alumni-network-caOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
Multi-tenant private alumni network platform (Next.js + Supabase). Herzliah is tenant #1.
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗A private, verified professional network for school alumni. Each school (a tenant) gets its own branded space at <school>.alumninetwork.ca, and graduates can only see and contact their own school's alumni. Herzliah High School (Montreal) is the first tenant; the pilot targets 2026-12-01.
Stack: Next.js (App Router) · React · TypeScript · Supabase (Postgres, row-level security, Auth) · Vercel.
| Where | What |
|---|---|
| Project board | Every task, decision and milestone |
| CONTRIBUTING.md | Branches, PRs, Definition of Done, releases, commands |
| docs/adr/ · docs/DECISIONS.md | Architecture decisions and the decision register |
| docs/PRODUCT_ANALYSIS.md | Audit of the initial MVP (findings F1–F27) and the target data model |
| documentation/diagrams/ | User flows and ERDs |
supabase --version)npm install # also installs the pre-commit hook
supabase start # local Postgres, Auth, Studio and Mailpit (first run pulls ~2-3 GB of images)
cp .env.example .env.local # then paste the publishable key from `supabase status -o env`
npm run dev
Open http://herzliah.localhost:3000. The subdomain selects the school: test-school.localhost:3000 is the second school, and plain localhost:3000 is the root site (the page for schools). A session belongs to one school's address, so signing in at one does not sign you in at the other.
supabase start applies supabase/migrations/* and then supabase/seed.sql. The seed contains fictional demo alumni for both schools plus local test accounts, listed below and at the top of supabase/seed.sql.
To sign in, enter one of those emails at /login: the 6-digit code arrives in Mailpit (http://127.0.0.1:54324). Or choose "Sign in with a password": every seed account has the local-only password LocalDev-Passw0rd (ADR 0015). Any account can set its own password at /account/password after signing in with a code.
The platform console is at http://localhost:3000/console (the root site has its own sign-in): sign in as [email protected] to list, create and suspend schools, invite their first school admin and open support access. On a PR preview, add ?tenant=root to reach it.
| Service | URL |
|---|---|
| App (Herzliah) | http://herzliah.localhost:3000 |
| App (second school) | http://test-school.localhost:3000 |
| Supabase API | http://127.0.0.1:54321 |
| Supabase Studio (database browser) | http://127.0.0.1:54323 |
| Mailpit (catches every email sent locally) | http://127.0.0.1:54324 |
| Postgres | postgresql://postgres:[email protected]:54322/postgres |
supabase db reset # rebuild the local DB from migrations + seed
supabase migration new <name> # new schema change; never edit applied migrations
npm run db:types # regenerate lib/database.types.ts after a migration
npm run seed:perf # add 10,000 alumni per school (local only; db reset removes them)
npm run bench:directory # time the directory search (p50/p95) after seed:perf
npm run check # lint + typecheck + format check + unit tests
npm run test:db # pgTAP database tests (stack must be running)
npm run test:e2e # Playwright end-to-end + accessibility tests
supabase stop # stop the local stack
The database runs the v2 schema (data model): three migrations in supabase/migrations/ (schema, access rules, RPCs), with the legacy MVP migrations kept in supabase/legacy/ for history. The app is the V1–V4 MVP being rebuilt onto it, issue by issue. The directory already reads v2 through clients typed from the generated lib/database.types.ts. Sign-in is by emailed code; new people sign up at /join and wait on their account page until the school approves them. Onboarding, the profile editor and the admin pages still use the old tables through an untyped createLegacyClient(), and fail locally until their M2 issues rewire them (each file names its issue).
Local test accounts (sign in with a code from Mailpit). After sign-in each one lands on its own home page:
| Account | Role |
|---|---|
[email protected] | Herzliah school admin |
[email protected] | Herzliah reviewer |
[email protected] | Herzliah alumnus (published) |
[email protected] | Signed up, waiting for approval |
[email protected] | Asked for more information, not answered yet |
[email protected] | Sign-up rejected |
[email protected] | Withdrew their sign-up |
[email protected] | Alumnus whose record the school suspended |
[email protected] | Approved, has not finished onboarding |
[email protected] | School admin of a second school (isolation tests) |
[email protected] | Reviewer of the second school |
[email protected] | Alumnus of the second school |
[email protected] | Waiting for approval at the second school |
[email protected] | Verified account with no school |
[email protected] | System admin |
The seed also holds 200 published Herzliah alumni and 20 at the second school (fictional, @example.test).
Never commit secrets: .env*.local is ignored, and only .env.example (no values) is tracked. The Supabase secret key must never be exposed to the browser. Report vulnerabilities privately (see .github/ISSUE_TEMPLATE/config.yml).