https://github.com/garnertb/geo-quest
https://github.com/garnertb/geo-quest
Last synced: 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/garnertb/geo-quest
- Owner: garnertb
- Created: 2026-05-29T13:19:55.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-29T14:33:26.000Z (2 months ago)
- Last Synced: 2026-05-29T15:11:19.862Z (2 months ago)
- Language: TypeScript
- Homepage: https://geo-quest-flax.vercel.app
- Size: 2.79 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Geo Quest
A fast, visual geography learning game for kids ages 7–16.
Built with **Next.js 16 (App Router, static export)**, **React 19**, **TypeScript**, **Tailwind v4**, **Zustand**, **Framer Motion**, and **Tauri 2**.
## Run
### Web
```bash
npm install
npm run dev # http://localhost:3000
npm run build # produces ./out (static export)
npm run lint
```
### Desktop (Tauri 2)
```bash
npm run tauri:dev # launches native window pointed at the Next dev server
npm run tauri:build # produces a native installer (macOS/Windows/Linux)
```
Requires Rust toolchain (`cargo`). The web build always works without it.
## Architecture
```
src/
app/ Next.js App Router pages (/, /topics, /play, /summary, /mastery)
components/
ui/ Buttons, cards, progress (shadcn-style primitives)
maps/ USTileMap, ContinentMap (SVG)
content/seed.ts Static content packs: continents, US states, US capitals
engine/
learning/sr.ts SM-2-lite spaced-repetition + mastery tracking (pure)
session/builder.ts Question generation, session planner, scoring
store/game.ts Zustand store + localStorage persistence
types/domain.ts Shared TS types (ContentPack, GeoItem, Question, …)
lib/ Utilities (cn, shuffle, useHydrated)
src-tauri/ Rust Tauri 2 shell
```
### Learning engine
- Each `(item, questionType)` pair has its own `LearningState`: mastery 0–1, ease factor, current streak, next-review timestamp, recent attempts.
- `applyAnswer` updates state using an SM-2-lite rule: correct answers extend the interval by `ease`, wrong answers reset the interval and resurface the item within minutes.
- `bucketStates` partitions items into **due / weak / new / strong** for session planning.
- Sessions pull **60% due, 25% weak, 15% new**, falling back to fill if a bucket is short.
### Content packs
- A `ContentPack` declares `topic`, `items`, and `supportedQuestionTypes`.
- Items reference visual assets by id (`shape`, `tile`). The map components own the actual rendering, so packs can be added later without touching the learning engine.
- The MVP uses a stylized US tile-map and simplified continent silhouettes. Swap in GeoJSON-backed components later by replacing `USTileMap` / `ContinentMap`.
### Persistence
- `localStorage` via `zustand/middleware/persist`. Works in both the web app and Tauri webview.
- Single local profile in MVP; the store is shaped to allow multiple profiles later.
### Game loop
1. **Home** — first-time players start with **Start your quest** (map pick + 5-question focused quest), then transition to **Today’s Quest** and dynamic recommendations.
2. **Daily Quest** (`/play`) — 10 mixed-topic questions with a non-required speed bonus, combo multiplier, animated correct/wrong feedback, and a teaching map for misses.
3. **Summary** — stars (based on accuracy), XP, best combo, improved items, items to review.
4. **Topic picker** — jump directly into continents / states / capitals.
5. **Mastery map** — visual progress: mastered states light up green, weak ones tint red.
## MVP scope
✅ Home · Topics · Play (10-question Daily Quest) · Summary · Mastery
✅ Speed bonus, combo, XP, streak, daily goal, star rating
✅ Correct/wrong animations and teaching feedback on misses
✅ Reusable learning engine (SR + mastery)
✅ Content-pack data model with seed content
✅ Local-first persistence
✅ Tauri 2 desktop wrapper
🚫 Achievements (intentionally out of scope)
## Design decisions
- **Tile-map for US states.** Instantly recognizable, scales perfectly, and lets us highlight any state precisely. Real GeoJSON outlines can be dropped into the `USTileMap` component later.
- **No mascot.** Polish carries the game feel: large cards, smooth transitions, satisfying button physics, animated stars.
- **Speed bonus, not speed gate.** Younger players are never punished by the timer.
- **Distractor groups by region.** Wrong-answer choices tend to be regional neighbors, making questions challenging without random difficulty.