Find your perfect gaming squad through Tinder-style swiping that matches you with MMO players who share your favorite games, playstyles, and online schedules.
- Tinder-like swipe interface - Discover compatible players through intuitive left/right swiping
- Intelligent filtering - Automatically matches profiles based on shared games, gameplay styles (PvP, PvE, casual, hardcore), time zones, and preferred play times
- Multi-slot scheduling - Set your weekly availability so you only see players who are online when you are
- Instant mutual matches - Get notified immediately when someone swipes right on you too
- Direct messaging - Chat with your matches to coordinate raids, dungeons, or casual sessions
- 300+ MMO titles with screenshots, descriptions, official links, and community ratings
- Community-driven catalog - Suggest new games or updates that admins review and approve
- Star ratings and reviews - See what the community thinks before diving into a new game
- Active player counts - Find out which games have the most active matchmakers
- RAG-powered recommendations - Ask the AI companion to suggest games based on your preferences using semantic search over the entire game database
- Natural language queries - "Find me games like World of Warcraft but more casual" or "What are trending MMOs for PvP players?"
- Intent detection - Automatically understands whether you want similar games, comparisons, trending titles, or detailed game info
- Smart entity extraction - Recognizes game names, categories, and playstyles in your messages
- Invite-only guilds - Create or join private communities with verified players
- Guild chat and events - Coordinate raids, schedule meetups, and stay connected with your squad
- QR code invites - Share one-hour guild invite links via QR codes for easy onboarding
- Guardian controls - Parent-managed kid accounts with chat oversight and match approvals
- Passwordless authentication - Secure login via email OTP codes and magic links
- Profile customization - Upload avatars, link social accounts, set timezone and language preferences
- Location-based badges - Collect badges by visiting gaming hotspots (GPS + QR codes)
- Data export - Download all your chat history and profile data anytime
- AI moderation - LLM-powered content screening protects against spam, abuse, and NSFW content
- Dark mode - Easy on the eyes during late-night gaming sessions
- Full account control - Sign out or permanently delete your account with cascade deletion of all data
- Next.js 15 App Router • React 19 Server/Client Components
- TypeScript with strict settings
- Prisma ORM + PostgreSQL
- Tailwind CSS + Radix UI primitives
- Framer Motion, react-hot-toast, sonner, lucide-react
- Playwright for end-to-end coverage
- Node.js 18 LTS or 20 LTS
- pnpm 8+ (recommended; swap commands for npm/yarn if preferred)
- PostgreSQL database (local Docker or hosted)
- SMTP credentials for transactional mail (development can fall back to console logging)
- OpenAI API key (optional, for AI companion intent detection)
-
Install dependencies
pnpm install
The repo tracks
pnpm-lock.yaml. Using pnpm keeps dependency resolution consistent. -
Create environment variables (
.env.localin the project root):DATABASE_URL="postgresql://user:password@localhost:5432/mmo_match" APP_URL="http://localhost:3000" SMTP_HOST="smtp.yourprovider.com" SMTP_PORT="587" SMTP_USER="smtp-user" SMTP_PASS="smtp-pass" SMTP_FROM="MMOPLAYA <no-reply@mmo-match.gg>" OTP_EXPIRATION_MINUTES=10 # optional override SESSION_TTL_DAYS=30 # optional override MODERATION_SECRET="super-secret" # required for moderation endpoints
OPENROUTER_API_KEY="sk-or-..." # required for avatar + comment moderation and suggestion review COMMENT_MODERATION_MODEL="mistralai/mistral-7b-instruct" # optional override for game comment checks MODERATION_MODEL="openrouter/auto" # optional override for shadowban tooling COMPANION_MODEL="anthropic/claude-3.5-haiku" # optional override for the AI companion OPENAI_API_KEY="sk-..." # optional, for intent detection (uses fallback regex if missing)
- If SMTP is omitted, OTP codes and magic links are printed to the server logs for local testing.
- Use port `465` for implicit TLS; the mailer auto-selects secure mode.
- If `OPENAI_API_KEY` is not provided, the AI companion will use a regex-based fallback for intent detection.
3. **Set up the database**
```bash
pnpm exec prisma migrate dev --name init
pnpm exec prisma generate
- Run
pnpm exec prisma migrate deployin production/CI. pnpm exec prisma studioopens a browser UI to inspect tables.
-
Seed preference tables and demo data (optional)
pnpm seed:preferences pnpm db:seed
pnpm seed:preferenceshydrates theGame,TimeSlotOption,LanguageOption, andPlaystyleOptionlookup tables.pnpm db:seedseeds a verified guardian/kid pair, a starter guild with events/badges, and 100 random pilot profiles (names, bios, avatars, preferences) so the swipe deck has immediate candidates.- Verify additional profiles directly in the database or via Prisma Studio by toggling the
isVerifiedflag onProfilerows. Only verified players can create guilds. - Generate creation codes with
pnpm generate:guild-codes <amount>(add--creator-email=to attribute a creator). Codes expire after 30 days and must be funded on-chain before use. - Guild officers can mint one-hour QR invites from the guild detail page; shareable URLs are embedded in the QR image for standard camera apps.
- Guardians can create kid accounts via
/api/parent/kidsand manage matches/guilds through theparent/API suite. - Seed badges via Prisma, then expose them through
/api/badges; players collect them with/api/badges/collectwhen on-site (GPS) or by scanning badge QR codes.
-
Start the app
pnpm dev
Visit
http://localhost:3000, request a login link, and accept the Terms of Use and Privacy Policy prompt. The dashboard, profile, matches, chat, and settings routes now require a valid session cookie.
| Command | Description |
|---|---|
pnpm dev |
Launch the Next.js development server with hot reload. |
pnpm build |
Create an optimized production build. |
pnpm start |
Run the production build locally. |
pnpm lint |
Execute ESLint against the project. |
pnpm test:unit |
Execute the Vitest suite for fast utility tests. |
pnpm test:e2e |
Run the Playwright end-to-end suite. Set PLAYWRIGHT_SKIP_WEB_SERVER=1 if the dev server is already running. |
pnpm generate:guild-codes <amount> |
Bulk-generate guild creation codes with 30-day expiry. |
pnpm seed:preferences |
Populate lookup tables for games, time slots, languages, and playstyles. |
pnpm generate:fakes <profileId> [count] |
Create demo matches for a given profile (default count: 5). |
pnpm update:disposable-emails |
Update the disposable email domain blocklist from public sources. |
pnpm exec prisma migrate dev --name <label> |
Apply schema changes locally and generate migrations. |
pnpm exec prisma migrate deploy |
Apply pending migrations in production/CI. |
pnpm exec prisma generate |
Regenerate the Prisma client after schema edits. |
pnpm exec prisma studio |
Launch Prisma Studio for inspecting data. |
- Install browsers once with
npx playwright install(pnpm will cache the binary). - Run
pnpm test:unitfor quick Vitest feedback on utilities (tests/unit). - Ensure
DATABASE_URLpoints to an isolated database; tests create and clean up users, OTP tokens, guild memberships, and sessions. - Playwright auto-starts the dev server (
npm run dev) unlessPLAYWRIGHT_SKIP_WEB_SERVER=1is set. - The sample tests (
tests/e2e/auth-flow.spec.ts,tests/e2e/homepage.spec.ts,tests/e2e/match-conversation.spec.ts,tests/e2e/profile-persistence.spec.ts,tests/e2e/account-settings.spec.ts) cover OTP login, profile persistence across sessions, account sign-out/deletion flows, and a complete mutual-match chat flow.
app/
page.tsx Landing page + OTP request
dashboard/ Swipe deck with matchmaking logic
matches/ List of mutual matches
chat/[matchId]/ Polling chat room
games/ Games directory with individual game pages
games/[gameValue]/ Game detail page with ratings, comments, and players
guilds/ Guild management + chat experience
profile/ Profile editor (avatar upload, enums)
settings/ Session + account management
feedback/ In-app feedback submission form
api/ Route handlers (auth, profile, swipes, messages, account, analytics)
admin/
users/[userId]/ Block, unblock, and delete user accounts (admin only)
analytics/
players/ Player summary metrics
preferences/ Preference distributions for dashboards
guilds/
[guildId]/invites/ One-hour QR invite lifecycle
[guildId]/messages/ Guild chat endpoints
join/ Join via invite code + nickname override
route.ts List/create guilds
guild-invites/ Public invite lookup for scanners
guild-codes/ Payment + status endpoints for creation codes
parent/
kids/ Manage child profiles (guardian only)
matches/ Guardian-initiated friendships + queue
matches/[matchId]/ Match approval/blocking actions
guilds/[guildId]/ Guardian guild controls
guilds/[guildId]/events/ Manage guild events + alerts
badges/ Badge directory + collection (GPS/QR)
export/ Download a JSON bundle of your chats
feedback/ Submit user feedback
games/
[gameValue]/
rating/ Submit game ratings
comments/ Post and fetch game comments
suggest-edit/ Suggest metadata updates for an existing game
game-suggestions/ Submit and moderate new game requests
game-update-suggestions/ Moderate metadata update submissions
og/ Dynamic Open Graph preview cards (player/guild/event)
moderation/ Shadowban + automated review endpoints
admin/
game-suggestions/ Admin queue for new game requests
game-update-suggestions/ Admin queue for metadata updates
users/ Admin user management dashboard
components/ UI primitives, swipe deck, chat room, forms, game ratings/comments, admin tools
lib/ Prisma client, auth/session helpers, mailer, disposable email detection
middleware.ts Session guard + redirect rules
prisma/schema.prisma Database schema and enums
public/uploads/ Local avatar storage (created at runtime)
scripts/ Maintenance utilities (guild code generator)
tests/e2e/ Playwright scenarios
The AI companion automatically classifies user messages to understand what players want:
- find_similar_games: User wants games similar to a specific game
- recommend_by_preference: User wants recommendations based on their preferences
- compare_games: User wants to compare multiple games
- my_games: User asks about their current game list
- trending_games: User wants to know what's popular
- game_info: User wants detailed information about a specific game
- category_browse: User wants to browse games in a category
- general_chat: General conversation
Intent detection uses GPT-4o-mini for accurate classification with entity extraction (game names, categories, playstyles, keywords). If OpenAI is unavailable, the system falls back to regex-based pattern matching. All intents are stored in the database for analytics and feature improvements.
Game embeddings enable intelligent game discovery beyond keyword matching:
- Each game has a 1536-dimension vector embedding generated from its description
- Enables semantic similarity search ("games like World of Warcraft")
- Powers natural language recommendations in the AI companion
- Uses OpenAI's text-embedding-3-small model for consistent, high-quality embeddings
- Stored in PostgreSQL with pgvector extension for fast nearest-neighbor queries
Note: The pgvector extension is required for full embedding functionality. Without it, the system will store metadata fields but not perform semantic searches.
- Avatar uploads are scanned with OpenAI's
omni-moderation-latestbefore storing in Supabase. - Game comments are screened through OpenRouter (default
mistralai/mistral-7b-instruct) to block spam, abuse, or explicit content. - Community suggestions (new games and metadata updates) route through
/admin/game-suggestionsand/admin/game-update-suggestionswhere admins can accept, reject, or annotate submissions. Accepted game edits apply immediately to the catalog.
To populate embeddings for your game library:
# Generate embeddings for all games without them
pnpm tsx scripts/generate-game-embeddings.ts
# Verify embedding coverage
pnpm tsx scripts/verify-embeddings.tsThe embedding generator:
- Processes games in batches to respect rate limits
- Tracks generation timestamps and model versions
- Skips games that already have embeddings
- Shows progress and estimates remaining time
- Login:
/api/auth/request-otpvalidates the email against a disposable email blocklist, hashes the OTP, stores it with expiry, and emails (or logs) the code plus magic link. Blocked accounts are rejected immediately./auth/callbackverifies the code and issues a session cookie stored undermmo_match_session. - Profiles:
lib/profile.tsensures every authenticated user has a profile row. Preference enums mirror the options rendered in the UI to keep data constrained, and theisVerifiedflag gates guild creation. Profile includes theme preference (light/dark/system) for UI customization. - Admin Tools:
/admin/usersprovides a searchable dashboard for admins to block or remove user accounts. Blocking immediately signs users out and prevents future logins./api/admin/users/[userId]handles block/unblock/delete operations with admin permission checks. - Games:
/gamesdisplays all supported MMOs in a grid layout. Each game links to/games/{game-slug}showing detailed information, community ratings (1-5 stars), user comments, and a list of active players. Game badges throughout the app are clickable links to their respective game pages. - Guilds:
/api/guildslets verified players spin up invite-only guilds using paid creation codes,/api/guilds/[guildId]/invitesmints one-hour QR invites,/api/guild-codes/payrecords EVM payments (ETH/ERC-20 on any chain), and/api/guilds/joinhandles membership via invite codes with nickname overrides./api/guilds/[guildId]/messagespowers real-time guild chat. - Moderation:
/api/moderation/shadowbantoggles shadowbans (requiresMODERATION_SECRETheader) and/api/moderation/reviewruns an OpenRouter LLM scan across a player’s last 10 messages, auto-shadowbanning on abusive or spammy content. - Guardian controls:
/api/parent/kidsmanages linked kid accounts,/api/parent/matcheslets guardians approve, block, or create friendships,/api/parent/matches/[matchId]handles approvals/blocks for existing chats, and/api/parent/guilds/[guildId]blocks or restores guild access. - Badges:
/api/badgeslists available location-based badges and/api/badges/collectlets authenticated players claim them via GPS radius or badge QR codes. - Data export:
/api/exportreturns a JSON dump of your profile, direct messages, and guild chats. - Guild events:
/api/guilds/{guildId}/eventsmanages scheduling with support for online/offline locations, banner images, and/alertssubroutes for email/SMS/Discord/Telegram notifications. - Open Graph:
/api/og/player|guild|eventrenders gradient preview cards for sharing profiles, guilds, and events across social platforms. - Analytics:
/api/analytics/playerssummarises user counts, guardian/kid activity, badge collections, and upcoming event metrics, while preference distributions remain available under/api/analytics/preferences. - Calendar export:
/api/guilds/{guildId}/events/{eventId}?format=icsgenerates an iCalendar file for easy calendar import. - Retention: One-to-one and guild chats automatically discard messages older than 30 days to keep storage lean.
- Matchmaking: The dashboard fetches profiles that match the current user’s game, language, playstyle, and time slot. Swipes record
yes/nodecisions and promote toMatchrecords when both parties say yes. - Chat:
/api/messages/[matchId]exposes GET/POST endpoints. The client polls every few seconds for new messages to keep dependencies light. - AI Companion:
/api/ai-chathandles companion interactions. Each user message is automatically classified for intent (find games, compare, recommend, etc.) using GPT-4o-mini or regex fallback. Intent data is stored alongside messages for analytics and can power future smart recommendations. - Account management:
/api/auth/logoutclears the session token./api/accountcascades deletion through user-owned records, then removes the session cookie.
- Provision PostgreSQL and set environment variables wherever the app runs (Vercel, Fly.io, etc.).
- Run
pnpm exec prisma migrate deployduring release to keep the schema in sync. APP_URLmust match the public origin so magic links redirect correctly.- Chat uses short polling; consider switching to websockets (Pusher, Ably, custom server) as concurrency needs grow.
- Uploaded avatars live on the application server (
public/uploads). For stateless deployments, back them with object storage (S3, R2) and update the upload handler.
- Terms of Use – respectful behaviour, guardian responsibilities, and acceptable use guidelines.
- Privacy Policy – data minimisation practices, retention windows, export/deletion instructions, and vendor disclosures.
- “Failed to send OTP” in development: confirm SMTP variables. Without them the code falls back to logging; check the server console for the OTP and magic link.
- Session redirects loop: verify cookies are enabled and
SESSION_TTL_DAYShas not expired; delete stale rows from theSessiontable if needed. - Playwright times out: ensure the database is reachable and
APP_URLmatches the URL the web server binds to.
Happy matching!