Palace52 is a full-stack memory-training web app for learning to memorize a full deck of cards with the memory palace technique. It is designed as a portfolio-grade Next.js project with real auth, database models, server actions, analytics, spaced repetition, and leaderboard foundations.
- Account creation and protected app routes with Clerk
- Memory palace builder with ordered locations
- Personal image mapping for all 52 cards using person/action/object and custom prompts
- Shuffled deck training with study and recall phases
- Position-level scoring, mistake classification, and feedback
- Session history with score, accuracy, timing, and card-level mistakes
- Weak-card review queue using spaced repetition
- Dashboard metrics: best score, average accuracy, completed sessions, due reviews, weakest cards, and trends
- Leaderboard ranked by score, then speed
- Next.js App Router, React, TypeScript
- Tailwind CSS
- PostgreSQL and Prisma
- Clerk authentication
- Vercel deployment
No Docker or Kubernetes are required.
src/
app/
(app)/ Protected product routes
(auth)/ Clerk sign-in and sign-up pages
actions/ Server actions for mutations
globals.css Tailwind and product theme
layout.tsx Root Clerk provider and fonts
page.tsx Public landing page
components/
app/ App shell, charts, card display pieces
training/ Client training cockpit
ui/ Small reusable UI primitives
lib/
auth.ts Clerk-to-database user sync
cards.ts Deck definitions and shuffle
dashboard.ts Aggregate metrics
defaults.ts Starter palace and card images
prisma.ts Lazy Prisma singleton
scoring.ts Recall scoring and mistake analysis
spaced-repetition.ts Review scheduler
prisma/
schema.prisma PostgreSQL schema and Prisma models
docs/
architecture.md Build and deployment notesCore Prisma models live in prisma/schema.prisma:
User: local profile keyed toclerkUserIdPalace: a user-owned memory palacePalaceLocation: ordered route points inside a palaceCardImage: one personal image system entry per user/cardTrainingSession: generated deck, recall payload, score, timing, and statusSessionCardResult: card-by-card scoring output and feedbackReviewCard: spaced repetition state for weak cardsLeaderboardEntry: public ranked score rows linked to completed sessions
Enums cover card Suit, Rank, SessionMode, SessionStatus, and MistakeType.
/public landing page/sign-inand/sign-upClerk auth screens/dashboardpolished progress overview/palacespalace and location builder/cards52-card image mapping system/trainingdeck memorization and recall mode/sessionssession history and mistake review/reviewsspaced repetition queue/leaderboardranked completed sessions
ensureStarterContent: creates a starter palace and starter 52-card image systemcreatePalace,addPalaceLocation: palace builder mutationsupsertCardImage: card-image mapping updatescreateTrainingSession: generates and persists a shuffled deckcompleteTrainingSession: scores recall, stores card results, updates reviews, and writes leaderboard entrygradeReviewCard: advances spaced repetition state after a review
src/lib/scoring.ts compares the expected deck against recalled card codes by position:
- correct card in correct position:
CORRECT - blank answer:
MISSING - card exists elsewhere in the recalled deck:
WRONG_POSITION - different card in the slot:
WRONG_CARD
The result includes score, accuracy, per-card feedback, missed cards, misplaced cards, and correct streaks.
src/lib/spaced-repetition.ts uses an SM-2-inspired scheduler:
- forgotten cards reset to a 1-day interval and add a lapse
- hard or misplaced recalls keep the card close in the queue
- easy recalls grow the interval by ease factor
- ease factor is bounded so difficult cards do not disappear too quickly
The dashboard is designed for repeated training:
- top metric strip for score, accuracy, sessions, and due reviews
- trend chart for improvement history
- weakest-card list from accumulated card-level mistakes
- direct entry into training
The leaderboard stores one row per completed session and ranks by score first, then faster total time.
This project uses pnpm. On a normal machine with Node installed:
pnpm install
cp .env.example .env.local
pnpm prisma:migrate
pnpm devFill .env.local with:
DATABASE_URLNEXT_PUBLIC_CLERK_PUBLISHABLE_KEYCLERK_SECRET_KEY- Clerk redirect URL variables from
.env.example
Use docs/local-testing.md as the pre-deployment checklist. The app should be tested locally through sign-up, palace setup, card image edits, training, scoring, reviews, history, and leaderboard before any Vercel work.
- Create a PostgreSQL database with Neon, Supabase, or a Vercel Marketplace Postgres provider.
- Create a Clerk app and configure allowed redirect URLs for your Vercel domain.
- Add all environment variables in Vercel Project Settings.
- Import the GitHub repository into Vercel.
- Keep the build command as
pnpm build. - Run Prisma migrations against production before first launch.