Critical – money integrity:
- server.ts: restrict Socket.IO CORS to NEXT_PUBLIC_SITE_URL (remove origin:"*")
- server.ts: validate userId against DB on join_room before any debit/credit
- server.ts: atomic coin-flip joiner claim via updateMany(where:{status:WAITING,joinerId:null})
- server.ts: await pong game_over payout+room update before emitting result; log errors
- prediction/route.ts: wrap market resolve + all payouts in one Prisma transaction;
concurrent PATCH returns 409; dust remainder credited to first winner
High – data truth:
- raised/page.tsx, leaderboard/route.ts, cards/route.ts: add status:"succeeded"
filter to all donation aggregations
- polls/next-president/route.ts: replace full in-memory row scan with DB-side
groupBy + bounded 14-day window for daily activity chart
Medium – ops:
- faq-board/page.tsx: add admin approve/reject tab (visible to ADMIN role)
Low – UX/consistency:
- faq-board, billboard, spotlight, cards: replace hardcoded "BWT" with creditTicker()
- faq-board: read submitCost/voteCost from API response instead of hardcoded values
- WalletActions.tsx: make refreshBalance stable with useCallback; remove
eslint-disable exhaustive-deps suppression
Co-authored-by: Cursor <cursoragent@cursor.com>
Democratic Fundraiser
A local-first Democratic fundraising platform built with Next.js, Stripe Checkout + webhooks, Auth.js credentials login, Prisma, PostgreSQL, and a server-authoritative supporter wallet.
The app is designed to make donating feel active instead of transactional: cinematic landing page, public momentum meter, issue narrative cards, impact planner, Blue Wave Token (BWT) supporter credits, /raised totals page, wallet rewards, raffle entries, and compliance placeholders that must be configured before real fundraising.
Features
- Stripe card donations through embedded Checkout Sessions.
- Server-confirmed wallet credits from Stripe webhooks with idempotent ledger writes.
- Blue Wave Token (BWT) supporter credits for rewards UX. BWT is not crypto and is not tradable.
- Supporter wallet with digital perk redemptions and raffle ticket spending.
- Public fundraising stats endpoint for raised total, donor count, and goal progress.
- Campaign action center, impact planner, issue grid, accountability frame, and rewards preview.
- Local LAN runtime on
0.0.0.0:8008.
Stack
- Next.js App Router + TypeScript
- React 19
- Tailwind CSS 4
- Prisma 7 + PostgreSQL
- Auth.js / NextAuth credentials provider
- Stripe SDK + Stripe React Elements
- Framer Motion for motion and interaction polish
Quick Start
cd /root/fundraising-platform
npm install
cp .env.example .env
npm run db:migrate
npm run db:seed
npm run dev
Open http://127.0.0.1:8008 or http://<machine-ip>:8008.
Configuration
Copy .env.example to .env and fill in the real local values. Do not commit .env.
Required values:
DATABASE_URLNEXT_PUBLIC_SITE_URLAUTH_URLNEXTAUTH_URLAUTH_SECRETSTRIPE_SECRET_KEYNEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYSTRIPE_WEBHOOK_SECRETPUBLIC_CAMPAIGN_GOAL_USDNEXT_PUBLIC_COMMITTEE_LEGAL_NAME_PLACEHOLDERNEXT_PUBLIC_DISCLAIMER_TEXT
For local Stripe webhook forwarding:
stripe listen --forward-to 127.0.0.1:8008/api/webhooks/stripe
Useful Commands
npm run dev # Next dev server on 0.0.0.0:8008
npm run build # Production build
npm run start # Serve production build on 0.0.0.0:8008
npm run db:migrate # Apply Prisma migrations in dev
npm run db:seed # Seed demo users, wallet, perks, raffles
npm run test:integration # DB and optional Stripe smoke checks
npm run test:http # HTTP smoke checks against a running server
npm run test:all # Validation script (prisma + smoke + production build)
Donation Flow
- A signed-in supporter chooses an allowed donation tier.
- The server creates an embedded Stripe Checkout Session and stores user + exchange snapshot metadata.
- Stripe confirms the card payment for the session's PaymentIntent.
- Stripe sends
payment_intent.succeededto/api/webhooks/stripe. - The webhook verifies the signature, checks idempotency, creates the donation, appends a ledger entry, and increments wallet credits exactly once.
- The wallet reads the updated balance and enables rewards or raffle actions.
Recent hardening updates
- Login/register now preserve and sanitize
callbackUrlso users return to the workflow they came from. - FAQ pending queue is visible only to signed-in users; public users see approved FAQ entries only.
- Public fundraising stats now aggregate only
status = succeededdonations for treasury consistency. - Movement meter writes now use serializable transactions with explicit conflict handling (
409retry signal on concurrent races). - Casino pages now include the site footer/disclosure block for consistency.
- Sitemap now includes
/vote/next-president.
Compliance Notes
This repository is a technical demo until configured by qualified campaign counsel. Political fundraising can require FEC, state, donor eligibility, disclosure, reporting, refund, and payment processor review. Replace all committee placeholders and legal copy before accepting live contributions.
Never commit secrets, live Stripe keys, donor exports, production database dumps, or private credentials.