Build the Party Finder feature on top of the current master codebase (which has the Adventure Log, modern auth, admin tools). The old feat/party-finder branch has working code we can reference/port, but it uses deprecated Lucia auth that must be replaced with our modern auth system.
Key decisions from owner:
- Full profile system (bio, experience, play style, contact + privacy)
- 4-factor matching algorithm, Tue-Sun availability
- Integrate Adventure Log play data into matching
- Add
play_participantstable for structured player-to-play linking - Separate
partyFinderfeature flag - Login required to view party finder
- Full admin dashboard for party finder
- In-person cafe meetup focus (scheduling, not real-time)
- Experience: New / Some experience / Experienced
- Play style: Casual / Competitive / Either
- Extend registration form with party finder fields
display_name(text, nullable)bio(text, nullable)experience_level(text, nullable) — values: 'new', 'some_experience', 'experienced'play_style(text, nullable) — values: 'casual', 'competitive', 'either'looking_for_party(boolean, default false)party_status(text, default 'resting') — values: 'active', 'resting'open_to_any_game(boolean, default false)contact_method(text, nullable) — values: 'email', 'phone', 'whatsapp', 'discord'contact_value(text, nullable)contact_visible_to(text, default 'matches') — values: 'none', 'matches', 'all'last_login(timestamp, nullable)
id(integer, PK)userId(text, FK users.id, ON DELETE CASCADE)dayOfWeek(integer) — 0=Sun, 1=Mon, 2=Tue ... 6=SatcreatedAt(timestamp)
id(integer, PK)userId(text, FK users.id, ON DELETE CASCADE)gameBggId(text, FK boardGames.bggId)createdAt(timestamp)
key(text, PK)value(text, required)description(text, nullable)updatedAt(timestamp)
id(integer, PK)playId(integer, FK gamePlays.id, ON DELETE CASCADE)userId(text, FK users.id, ON DELETE CASCADE)createdAt(timestamp)
sessions.userId→ CASCADEgamePlays.userId→ CASCADE
- Single migration covering all schema changes
Port partyFinderUtils.ts from old branch, adapted for modern auth:
calculatePlayerCompatibility()— 4-factor scoring (40% availability, 40% games, 10% experience, 10% play style)getActivePlayers()— query active party finder usersgetPlayerAvailability()/getPlayerGamePreferences()— data fetchingreactivateUserIfAutoRested()— called on logingetPlayHistory()— NEW: query shared play history between users fromplay_participants- Remove all Lucia references, use
locals.userpattern from our auth - Remove in-memory caching (unreliable on Vercel serverless) — rely on DB queries
Add partyFinder flag in src/lib/flags.ts alongside existing logBook flag.
- Add
last_logintimestamp update on successful login - Add
reactivateUserIfAutoRested()call on login - Port from old branch's
login/+page.server.ts, adapted to modern auth
Extend App.Locals.user type to include new user columns.
Port from old branch, adapted for modern auth:
- Load function: Fetch user data + their availability + game preferences
- Form actions: Update profile fields, contact info, visibility settings
- UI: Form with sections for:
- Display name, bio
- Experience level (New / Some experience / Experienced)
- Play style (Casual / Competitive / Either)
- Contact method + value + visibility
- Availability day selector (Tue-Sun)
- Game preference selector (search + pick from catalog)
- "Looking for party" toggle
Port game selection and profile fields from old branch's registration:
- Add display name field (required)
- Add experience level picker (optional)
- Add play style picker (optional)
- Add contact method + value (optional)
- Add game preference selector — pick 1-4 games from catalog (optional)
- All party finder fields optional at registration (can complete on /profile later)
GET /api/party-finder/players
- Paginated, filtered, sorted player list
- Calculates compatibility scores for current user
- Includes shared play history count from
play_participants - Filters: experience, play_style, availability_day, game_preference
- Requires auth
- Gated behind partyFinder feature flag
POST /api/party-finder/availability
- Update current user's day-of-week availability
- Delete old + insert new (replace strategy)
- Requires auth
POST /api/party-finder/game-preferences
- Update current user's preferred games
- Validate all bggIds exist in catalog
- Delete old + insert new
- Requires auth
GET /api/party-finder/games-search
- Search board_games by name for the game selector
- Returns bggId, name, thumbnail, player count info
- Requires auth
Port from old branch with auth rewrite:
- Gated: Feature flag + login required
- Layout: Sidebar (settings) + Main (player discovery table)
- Sidebar: PartyFinderSettings component (availability, games, toggles)
- Main area: Filterable, sortable, paginated player cards
- Player cards show:
- Display name, experience, play style
- Shared availability days (highlighted)
- Preferred games (shared ones highlighted, with thumbnails)
- Compatibility score (with "Great Match" badge at 75%+)
- Shared play history ("You've played X games together")
- Contact info (respecting privacy settings)
Port and adapt from old branch:
PartyFinderSettings.svelte— sidebar settings formPartyFinderFilters.svelte— filter dropdownsPartyFinderPagination.svelte— page navigationPartyFinderStatusWarnings.svelte— status alertsPlayerDiscoveryTable.svelte— player card listDaySelector.svelte— day-of-week picker (Tue-Sun)GameSelector.svelte— game search + selection
- When a play is logged with tagged players, insert records into
play_participants - Backfill: parse existing tagged player data from
gamePlays.notesif feasible - Update the plays API (
POST /api/plays) to accept an array of participant user IDs
- Query
play_participantsto find users who've played together - Show on player cards: "Played together X times"
- Factor into matching algorithm as a bonus signal (not a core weight — more of a "you already know each other" indicator)
Port from old branch:
/api/cron/cleanup-inactive-usersendpoint- Daily Vercel cron at 06:00 UTC (add to
vercel.json) - Inactivity based on MAX(last_login, latest play date) — whichever is more recent
- Configurable threshold via
system_settings - Auto-reactivation on login
party_finder_inactive_days— default 14
Port from old branch:
/admin/party-finder-settings— configure inactive days threshold- Manual trigger for cleanup cron
New page or section within existing admin analytics:
- Total active party finder users
- Most popular availability days
- Most requested games
- Average compatibility score
- Users who've been auto-rested
- Party finder adoption rate (registered users vs. active in party finder)
- Add party finder status to existing
/admin/userspage - Ability to manually deactivate/reactivate party finder profiles
- "Party Finder" link in header, next to Adventure Log
- Only visible when partyFinder feature flag is enabled
- Show for logged-in users only (since page requires auth)
- "Party Finder Settings" in admin sidebar
- Add rate limiting note: login/register endpoints should have rate limiting (sveltekit-rate-limiter) — deferred to separate PR
src/lib/server/partyFinderUtils.tssrc/routes/party-finder/+page.server.tssrc/routes/party-finder/+page.sveltesrc/routes/profile/+page.server.tssrc/routes/profile/+page.sveltesrc/routes/api/party-finder/players/+server.tssrc/routes/api/party-finder/availability/+server.tssrc/routes/api/party-finder/game-preferences/+server.tssrc/routes/api/party-finder/games-search/+server.tssrc/routes/api/cron/cleanup-inactive-users/+server.tssrc/routes/admin/party-finder-settings/+page.server.tssrc/routes/admin/party-finder-settings/+page.sveltesrc/lib/components/PartyFinderSettings.sveltesrc/lib/components/PartyFinderFilters.sveltesrc/lib/components/PartyFinderPagination.sveltesrc/lib/components/PartyFinderStatusWarnings.sveltesrc/lib/components/PlayerDiscoveryTable.sveltesrc/lib/components/DaySelector.sveltesrc/lib/components/GameSelector.sveltedrizzle/XXXX_party_finder.sql(migration)
src/lib/server/db/schema.ts— add tables + columnssrc/lib/flags.ts— add partyFinder flagsrc/app.d.ts— extend User type in Localssrc/routes/login/+page.server.ts— add last_login + reactivationsrc/routes/register/+page.server.ts— add party finder fieldssrc/routes/register/+page.svelte— add game selector + profile fieldssrc/routes/+layout.svelte— add Party Finder nav linksrc/routes/admin/+layout.svelte— add admin nav linksrc/routes/api/plays/+server.ts— add participant tracking on play creationvercel.json— add cron schedule
We are NOT doing a git merge of feat/party-finder. We are porting the logic manually into the current codebase, rewriting auth, and adding new features (play_participants, play history integration, admin analytics). This avoids the 18-file merge conflict nightmare documented in PARTYFINDERMERGE.md.