Next.js 15 web application for the Noshop community membership platform.
This repository contains the web frontend for the membership platform. The Discord bot backend is maintained in a separate repository: ns-bot
- Landing Page - Public homepage with membership information
- Member Directory - Public directory of active members with status
- Application System - Discord OAuth + application form with CAPTCHA
- Payment Integration - Stripe Subscriptions ($299/month recurring)
- User Dashboard - Self-service subscription management via Stripe Customer Portal
- Admin Dashboard - Review applications, manage members
- Automated Role Management - Discord roles assigned/removed based on subscription status
- Framework: Next.js 15 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS 4
- Database: Supabase (Postgres 17)
- Payments: Stripe Subscriptions
- Auth: Discord OAuth
- Rate Limiting: Upstash Redis
- CAPTCHA: Cloudflare Turnstile
This web application is read-only for member data. The Discord bot writes member activity data to Supabase, and this web app reads from it via Row Level Security (RLS) for public member directory display.
Data Flow:
Discord Bot (Python) → Supabase (Postgres) → Web App (Next.js)
↓
Bot API (FastAPI)
↓
Web App (role management)
Related Repositories:
- Bot: ns-bot - Python Discord bot with message collection, member tracking, daily digest
- Web: This repository - Next.js membership platform
- Node.js 18+
- Discord bot must be running for role management features
- Supabase project with required schema (see Database Schema section)
npm install
Copy .env.example
to .env.local
and fill in all values:
cp .env.example .env.local
Required environment variables:
NEXT_PUBLIC_SUPABASE_URL
- Supabase project URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Supabase anon key (public read access)DISCORD_CLIENT_ID
- Discord OAuth app client IDDISCORD_CLIENT_SECRET
- Discord OAuth app client secretSTRIPE_SECRET_KEY
- Stripe secret keySTRIPE_PRICE_ID
- Stripe price ID for $299/month subscriptionBOT_API_URL
- URL to bot API (e.g., http://localhost:8000 for local, or Railway URL for production)BOT_API_KEY
- API key for bot API callsUPSTASH_REDIS_REST_URL
- Upstash Redis REST URLUPSTASH_REDIS_REST_TOKEN
- Upstash Redis REST tokenTURNSTILE_SITE_KEY
- Cloudflare Turnstile site keyTURNSTILE_SECRET_KEY
- Cloudflare Turnstile secret keyNEXTAUTH_SECRET
- NextAuth secret (generate with:openssl rand -base64 32
)RESEND_API_KEY
- Resend API key for email notifications
npm run dev
Open http://localhost:3000 in your browser.
noshop/ns-web/
├── app/ # Next.js App Router pages
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Landing page
│ ├── apply/ # Application flow
│ ├── pay/[token]/ # Payment page
│ ├── dashboard/ # User dashboard
│ ├── admin/ # Admin dashboard
│ ├── members/ # Public member directory
│ └── api/ # API routes
│ ├── auth/ # Discord OAuth
│ ├── applications/ # Application endpoints
│ └── webhooks/ # Stripe webhooks
├── lib/ # Utility libraries
│ ├── db.ts # Database utilities
│ ├── stripe.ts # Stripe utilities
│ ├── discord.ts # Discord OAuth utilities
│ ├── bot-api.ts # Bot API client
│ └── supabase.ts # Supabase client
├── components/ # React components
├── scripts/ # Utility scripts
├── package.json
├── tsconfig.json
├── tailwind.config.ts
└── next.config.js
This web app uses Supabase (Postgres) for data storage. The database is shared with the Discord bot.
- applications - Member applications with Discord OAuth data
- customers - Links Discord users to Stripe customers
- subscriptions - Active Stripe subscriptions
- payment_methods - Payment method details
- invoices - Invoice history
- role_sync_events - Discord role assignment audit log
- payment_tokens - Secure one-time payment tokens
- webhook_events - Webhook idempotency tracking
- admins - Admin user whitelist
- member_status - Member activity tracking (NEW/ACTIVE/IDLE/LURKER/GHOST)
- messages - Discord message storage
- reactions - Message reaction tracking
- resources - Extracted links, code, files
- member_goals - Goals from intro messages
- goal_progress - Win tracking
Schema Documentation: See the bot repository's SUPABASE_SCHEMA.md
for complete schema documentation.
Migration Management: Database migrations are managed by the bot repository as the single source of truth.
GET /
- Landing pageGET /members
- Member directoryGET /api/members
- Member data (proxied from bot API)
GET /apply
- Application formPOST /api/applications
- Submit applicationGET /dashboard
- User dashboardPOST /api/portal
- Create Stripe portal session
GET /admin
- Admin dashboardGET /api/admin/applications
- List applicationsPOST /api/admin/applications/:id/approve
- Approve applicationPOST /api/admin/applications/:id/reject
- Reject application
POST /api/webhooks/stripe
- Stripe webhook handler
npm test
npm run build
npm run lint
- Push code to GitHub
- Import project in Vercel
- Add environment variables in Vercel dashboard
- Deploy
Vercel will automatically:
- Build and deploy on push to main branch
- Set up preview deployments for PRs
- Configure edge functions for API routes
All environment variables from .env.example
must be set in Vercel dashboard under Project Settings → Environment Variables.
Critical Production Variables:
BOT_API_URL
- Must point to production bot API (Railway deployment)BOT_API_KEY
- Must match bot'sBOT_API_KEY
environment variableSTRIPE_WEBHOOK_SECRET
- Obtain from Stripe webhook configurationNEXT_PUBLIC_APP_URL
- Set to your production domain (e.g., https://creativetechnologists.com)
- All environment variables configured in Vercel
- Stripe webhook endpoint configured (https://yourdomain.com/api/webhooks/stripe)
- Discord OAuth redirect URI updated (https://yourdomain.com/api/auth/discord/callback)
- Bot API accessible from web app (test
/health
endpoint) - Supabase RLS policies enabled for member_status table
- Admin users seeded in
admins
table
- ✅ API key authentication for bot API calls
- ✅ Webhook signature verification (Stripe)
- ✅ CAPTCHA on application form (Turnstile)
- ✅ Rate limiting (3 applications/day per IP via Upstash Redis)
- ✅ Payment token security (bcrypt hashed, one-time use, 7-day expiry)
- ✅ Webhook idempotency (prevents duplicate Stripe event processing)
- ✅ Admin authentication (Discord ID whitelist)
- ✅ Row Level Security (RLS) on Supabase for public member directory
This web app communicates with the Discord bot via:
- Supabase (Read-Only): Reads member data from
member_status
table - Bot API (HTTP): Calls bot's FastAPI endpoints for role management
Bot API Endpoints Used:
GET /health
- Health checkGET /api/members
- Public member directory dataGET /api/members/{user_id}
- Individual member statusPOST /api/assign-role
- Assign role after paymentPOST /api/remove-role
- Remove role on subscription endPOST /api/sync-role
- Daily role sync
Local Development Setup:
- Run bot:
cd ../ns-bot && python src/bot.py
- Run web:
npm run dev
- Bot API available at
http://localhost:8000
- Web app available at
http://localhost:3000
If you see database connection errors:
- Verify
NEXT_PUBLIC_SUPABASE_URL
is correct - Verify
NEXT_PUBLIC_SUPABASE_ANON_KEY
is correct - Check Supabase project status (not paused)
- Verify RLS policies allow public read on
member_status
- Check webhook secret:
STRIPE_WEBHOOK_SECRET
- Verify webhook endpoint is accessible
- Check Stripe dashboard for webhook delivery logs
- Use Stripe CLI for local testing:
stripe listen --forward-to localhost:3000/api/webhooks/stripe
- Ensure bot is running and accessible
- Check
BOT_API_URL
is correct (Railway URL for production) - Verify
BOT_API_KEY
matches bot configuration - Test bot API health:
curl $BOT_API_URL/health
- Check bot logs for API request errors
- Verify bot is running and writing to Supabase
- Check
member_status
table has data - Verify RLS policy allows public SELECT on
member_status
- Check browser console for API errors
- ✅ Phase 1: Bot API foundation
- ✅ Phase 2: Web foundation + Landing page
- ✅ Phase 3: Discord OAuth + Applications
- ✅ Phase 4: Admin Dashboard
- ✅ Phase 5: Stripe Subscriptions (partial - payment flow complete)
- 🚧 Phase 6: User Dashboard (in progress)
- ⏳ Phase 7: Daily Role Sync Job
- ⏳ Phase 8: Polish + Testing
- ⏳ Phase 9: Deployment
- Bot Repository: ns-bot
- Supabase Schema: See bot repo's
SUPABASE_SCHEMA.md
- Phase Reports: See
PHASE_*_COMPLETE.md
files for detailed phase completion reports
Private repository - All rights reserved
For issues or questions, contact the maintainer or open an issue in the repository.