Waystar Hackathon Challenge — Full-Stack Payment Platform
- Application URL: [YOUR_DEPLOYED_URL]
- Admin Login: Use credentials from your .env (
ADMIN_EMAIL/ADMIN_PASSWORD) - Demo Payment Pages:
/pay/yoga-class— Fixed amount, custom fields/pay/parking-fee— Range amount, license plate field
Quick Payment Pages is a hosted, self-service payment platform that lets providers create branded, configurable online payment pages in minutes. Admins configure pages with custom branding, payment rules, and custom data fields — then share them via URL, iframe, or QR code.
[Browser/Payer] ──→ [React + Vite Frontend :5173]
│
[Vite Proxy]
│
[Admin Browser] ──→ [Express API :3001] ──→ [Supabase Postgres]
│
[Stripe API (sandbox)]
│
[SMTP / Resend (email)]
| Layer | Technology |
|---|---|
| Frontend | React 18 + Vite, vanilla CSS |
| Backend | Node.js + Express |
| Database | Supabase Postgres |
| Payments | Stripe (sandbox/test mode only) |
| Nodemailer / SMTP (stub mode in dev) | |
| Auth | JWT (jsonwebtoken) |
Tables: admin_users, payment_pages, payment_page_versions, custom_fields, transactions, field_responses, page_views
Key relationships:
payment_pages→custom_fields(one-to-many)payment_pages→transactions(one-to-many)transactions→field_responses(one-to-many)payment_pages→payment_page_versions(versioning/history)
| Variable | Description | Required |
|---|---|---|
PORT |
Express server port (default 3001) | No |
JWT_SECRET |
Secret for signing JWT tokens | Yes |
ADMIN_EMAIL |
Seeded owner account email | Yes |
ADMIN_PASSWORD |
Seeded owner account password | Yes |
SUPABASE_URL |
Supabase project URL | Yes |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key | Yes |
STRIPE_SECRET_KEY |
Must start with sk_test_ |
Yes |
STRIPE_WEBHOOK_SECRET |
Stripe webhook signing secret | Yes |
SMTP_HOST |
SMTP server hostname | No |
SMTP_PORT |
SMTP server port | No |
SMTP_USER |
SMTP username | No |
SMTP_PASS |
SMTP password | No |
FROM_EMAIL |
Sender email address | No |
| Variable | Description | Required |
|---|---|---|
VITE_API_URL |
Backend API URL (default http://localhost:3001) | Yes |
VITE_STRIPE_PUBLISHABLE_KEY |
Must start with pk_test_ |
Yes |
# 1. Clone the repo
git clone [your-repo-url]
cd qpp
# 2. Backend setup
cp .env.example .env
# Fill in .env values (JWT_SECRET, ADMIN_EMAIL, ADMIN_PASSWORD, STRIPE keys)
npm install
npm run dev # Starts on http://localhost:3001
# 3. Frontend setup (new terminal)
cd frontend
cp .env.example .env
# Set VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
npm install
npm run dev # Starts on http://localhost:5173
# 4. Access the app
# Admin portal: http://localhost:5173
# Public payment page: http://localhost:5173/pay/[slug]| Card Number | Result |
|---|---|
| 4242 4242 4242 4242 | Payment succeeds |
| 4000 0000 0000 0002 | Card declined |
| 4000 0025 0000 3155 | Requires 3D Secure authentication |
Use any future expiry date, any 3-digit CVV, any billing zip.
| Role | Capabilities |
|---|---|
| Owner | Full access — manage pages, users, reports, settings |
| Editor | Create and edit payment pages, view reports |
| Viewer | View pages and reports only (read-only) |
Full API documentation is available in the codebase. Key endpoint groups:
POST /auth/login— Admin loginGET /auth/me— Authenticated user profileGET/POST /admin/pages— Payment page managementPATCH /admin/pages/:id/status— Enable/disable pageGET /public/pay/:slug— Public page config (no auth)POST /public/pay/:slug/create-payment-intent— Create Stripe PaymentIntentPOST /public/pay/:slug/confirm— Confirm paymentGET /admin/reports/transactions— Transaction list with filtersGET /admin/reports/transactions.csv— CSV exportGET /api/feed— SSE live activity feed (auth required)
# Install Stripe CLI
stripe listen --forward-to localhost:3001/webhooks/stripeA mobile wrapper is included at mobile/ (Expo + React Native WebView) to run QPP on iOS/Android quickly.
cd mobile
npm install
cp .env.example .env
# Set EXPO_PUBLIC_WEB_URL to your frontend URL (or LAN IP URL for physical devices)
npm run startThe admin dashboard features a real-time payment activity feed powered by Server-Sent Events (SSE). Every successful payment broadcasts instantly to all connected admin sessions, giving providers immediate awareness without polling or refreshing. This creates a noticeably more professional admin experience than static dashboards.
Use the built-in Lighthouse script to validate key quality thresholds on the public payment page.
# Terminal 1 (backend)
./dev-env.sh npm run dev
# Terminal 2 (frontend)
cd frontend
../dev-env.sh npm run dev -- --host 127.0.0.1 --port 5173
# Terminal 3 (audit)
cd frontend
../dev-env.sh npm run test:lighthouseOptional environment variables for the audit command:
LIGHTHOUSE_URL(defaulthttp://127.0.0.1:5173/pay/yoga-class)LIGHTHOUSE_MIN_ACCESSIBILITY(default0.9)LIGHTHOUSE_MIN_PERFORMANCE(default0.7)LIGHTHOUSE_MIN_BEST_PRACTICES(default0.85)LIGHTHOUSE_MIN_SEO(default0.8)
- ACH bank transfer checkout with authorization language and Stripe Financial Connections
- Dynamic wallet availability detection via Payment Request API (Apple Pay / Google Pay where supported)
- Multi-language localization (10 languages)
- Webhook hardening with idempotency and refund/dispute handling
- Dark mode with persisted preference and OS preference detection fallback
- Playwright end-to-end smoke tests
- Mobile wrapper app (Expo + React Native WebView)