Repository navigation
feat: add stripe membership dues checkout - #39
Open
StevScripts wants to merge 1 commit into
Open
StevScripts wants to merge 1 commit into
StevScripts wants to merge 1 commit into
Conversation
Adds a Membership section and navbar "Pay dues" button that post to /api/checkout, which creates a Stripe hosted Checkout Session (one-time payment, customer_creation always, required T-shirt size dropdown and Discord username fields, term metadata) and redirects to it. Paid members land on /join/success. Stripe client is created lazily so lint, build and the Docker image work with no env vars set. Closes #38 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
StevScripts
requested review from
alecocosette and
sebastian-noel
as code owners
November 4, 2026 17:46
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.
Pull Request
Description
Lets students pay GPK dues on the site through Stripe hosted Checkout and collects T-shirt size and Discord username with the payment, so the Stripe Dashboard is the member list and the shirt order. Phase 1 only: no login, no database, no webhook.
#membershipsection on the homepage (price, perks, "Pay dues") and a "Pay dues" button in the navbar.POST /api/checkoutcreates a Checkout Session (mode: payment,customer_creation: "always", required T-shirt size dropdown XS–3XL, required Discord username text field,termmetadata on the session and the PaymentIntent) and 303-redirects to Stripe./join/successthank-you page with the Discord invite.lib/stripe.tscreates the client lazily, sonpm run lint,npm run buildand the Docker image all work with zero env vars (verified locally with the vars explicitly unset)..env.examplewithSTRIPE_SECRET_KEY,STRIPE_PRICE_ID,NEXT_PUBLIC_SITE_URL;.gitignorenow keeps the example file;docker-compose.ymlreads an optional.env.Price and copy live in
lib/membership.ts($20per academic year, term2026-27, placeholder perks markedTODO(officers)); the Stripe Price is the source of truth for the amount.Type of Change
feat: New featurefix: Bug fixchore: Maintenance (dependencies, config, etc.)docs: Documentation onlystyle: Code style (formatting, no logic change)refactor: Code refactor (no new feature or fix)Changes Made
app/api/checkout/route.ts,lib/stripe.ts,lib/membership.ts(new)components/MembershipSection.tsx,app/join/success/page.tsx(new)app/page.tsx,components/Navbar.tsx,components/Footer.tsx.env.example(new),.gitignore,docker-compose.yml,README.md,package.json(+stripe)Screenshots (if applicable)
Desktop membership
Mobile membership and navigation (390 × 844)
Success page after sandbox checkout
Sandbox receipt
The receipt shows T-shirt size L and Discord username Stevin_dev.
Checklist
npm run lintpasses without errorsnpm run buildcompletes successfullyTesting notes
/join/successrenders;GET /api/checkoutis 405.price_1UYAufEhGiRjGRLNtgyUPbNg, the local Pay dues button opened Stripe Checkout in sandbox mode. Submittedtest@example.com, Test Student, size M, Discord usernameteststudent, and Stripe's 4242 test card; the browser returned to/join/successand displayed “You're in!”.termmetadata and the Customers entry..env.exampleto.env.localif needed, set a sandbox secret key and the one-time test Price ID, leaveNEXT_PUBLIC_SITE_URLempty, then runnpm run dev. Open the printed local URL, choose Pay dues, and use Stripe test card4242 4242 4242 4242with a future expiry, any three-digit CVC, and a ZIP code. Confirm the sandbox label before submitting; inspect the payment and customer in the sandbox Dashboard afterward.Before merge (not code)
Whose Stripe account this is and UCF RSO/SGA rules on collecting dues into it; card fee is baked into the price.
Follow-ups (out of scope here)
memberstable (chore: install drizzle orm dependencies #32), rate limiting on/api/checkout, a shared pill-button component (the hero classes are now copied in four places), and making navbar links work from/join/success(they are hash links and only work on/).Related Issues
Closes #38
🤖 Generated with Claude Code