feat: Techne v1 enrollment platform#2
Open
unforced wants to merge 3 commits into
Open
Conversation
Full web application replacing static index.html. Students can browse cohorts, enroll via Stripe, receive a magic link, and access session recordings in a protected members area. Admins manage sessions and resources via an authenticated dashboard. - Next.js 15 App Router with hand-crafted CSS (no Tailwind) - Supabase auth (magic link), Postgres, Row-Level Security - Stripe checkout with promo codes + idempotent webhook handler - Post-payment auth gap solved: success page sends magic link via email - Protected /cohort and /admin routes via middleware - Admin role via profiles.is_admin boolean 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Security: - Fix is_admin privilege escalation in RLS update policy (with check constraint) - Add get_auth_user_id_by_email RPC to replace listUsers() pagination issue - Move magic link send from unauthenticated success page into webhook handler - Return 500 on enrollment failure so Stripe retries (was incorrectly returning 200) - Exclude api/webhooks from middleware (prevents Supabase session overhead on webhook) Correctness: - Fix show_in_directory privacy filter applied at DB level in cohort directory query - Fix .single() to .limit(1) to handle multi-cohort students without 500 error - Add safeHostname() helper to prevent new URL() crash on malformed admin resource URLs Performance / indexes: - Migration 004: indexes on enrollments(user_id), enrollments(cohort_id), sessions(cohort_id), sessions(cohort_id, published_at), resources(cohort_id), profiles(id, is_admin) Cleanup: - Simplify lib/stripe.ts: remove Proxy pattern, export only getStripe() - Update checkout route to use getStripe() instead of named stripe export - Add X-Content-Type-Options and Referrer-Policy security headers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a Builds tab where enrolled students can share what they're building. Admins can mark projects as featured. Builds are visible to all enrolled students within the cohort. - Migration 005: projects table with RLS (one project/student/cohort, featured flag locked from student updates) - ProjectSubmitForm: upsert with onConflict, collapsed when submitted - ProjectCard: display component with featured badge - ProjectAdminTable: toggle featured flag from admin dashboard - cohort/page.tsx: Builds tab with submit form + projects grid - admin/page.tsx + AdminDashboard: Builds tab for admin management - globals.css: project card styles Bug fixes: - Sign In button invisible (black on black) — moved outside nav ul - Programs page error on load — force-dynamic instead of revalidate 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
index.htmlWhat's included
Auth + enrollment
allow_promotion_codes: truefor sliding scale/enroll/[cohort]/successretrieves Stripe session email and sends a magic link — never redirects directly to/cohortstripe_session_idunique constraint + pre-insert checkProtected routes
/cohort— sessions (YouTube embeds), resources (grouped by type), cohort directory/cohort/profile— update display name, toggle directory visibility/admin— manage sessions (add/edit/delete, publish/draft toggle) and resourcesInfrastructure
middleware.tsguards/cohortand/admin; admin role check viaprofiles.is_adminDeploy checklist
stripe_price_idin DBRegenHub-Boulder/techne.institute, main branch.env.local.example)https://techne.institute/api/webhooks/stripeupdate public.profiles set is_admin = true where id = (...)Build output