Inspiration

What it does

How we built it

Challenges we ran into

Accomplishments that we're proud of

What we learned## Inspiration

Studying alone is brutal. Apps like Forest and Pomodoro timers help for 25 minutes, but then what? We wanted studying to feel like progress — not just a streak number, but a world you can see filling up. We mixed two ideas we love: the satisfying ink-spread of a strategy game + the tension of Alice in Borderland's sealed exam rooms. The result is Pseudopodia: your focus literally paints a living earth.

What it does

Pseudopodia is a free, browser-based Focus RPG.

  • Focus to paint: Pick a run from 30 minutes to 12 hours. Stay focused and your ink spreads across a flat paper world and a real 3D globe. Leave fullscreen and you get eliminated.
  • 24 unlockable inks: From Common Zebra & Jade to Legendary Kintsugi, Ember & Frost — each with a seamless SVG motif drawn with CanvasPattern. Tiles scale with zoom so they never look tiny.
  • Exam Rooms — the sealed acid room: Create or join a custom room with a 5-char code. You set the subject, class/page, source, question count (3-20) and seats (2-10). The AI writes a fresh paper just for that room. Everyone answers together — fastest correct answer takes the round, wrong/silent = 1 acid pixel. Light 10 and you're out. Last one standing wins. Coins by rank: 1st +50, 2nd +30, 3rd +20, 4th +10.
  • Live, real points: You see every desk flip in real-time — ✓ 2.3s, who locked first, who got it right — and the center board updates instantly.
  • AI thinking, visible: No silent "Exam cancelled" anymore. A Flow-Morph 5-dot animation + live feed shows only sources & steps (Reading NCERT Class 10 Science, Fetching diagrams from Wikimedia Commons...) — never the questions.

Focus time = Ink, Coins, Scholar XP, and Streaks. Abandoned runs still give up to 25% so effort is never wasted.

How we built it

No frameworks, no heavy deps — just the web platform done right.

  • Frontend: Vanilla JS (classic scripts for deterministic load order), Vite for build, Three.js only for the globe. The globe is lazy-loaded via globe-loader.js so the lobby is instant; vendor code is code-split.
  • 2D World: <canvas> flat map with organic spread — frontier cells are picked uniformly at random, not sorted. Ink motifs are 128px SVG tiles applied as CanvasPattern with DOMMatrix scaling so one motif = one cell at any zoom.
  • 3D Globe: Procedural Earth (fbm noise: oceans, forests, snow, ice caps) + drifting cloud layer. Falls back to procedural when offline, uses LinearMipmapLinear + max anisotropy for sharp continents.
  • AI Paper Pipeline: Vercel Serverless /api/quiz proxies to Qwen/GLM. System prompt demands Unicode math ((cos θ + i sin θ)^n not ^), classroom-safe content, and per-question seconds (8-90s). Papers stream in batches (3 at a time) while you answer, deduped by question text. Wikimedia Commons images are allowlisted (upload.wikimedia.org only, png/jpeg/webp/gif) and capped to 8 per paper.
  • Safety: Blocklist (ADULT_TERMS) checks topic before the model is called (400 topic_blocked) and drops any generated question that slips through.
  • Infra: dist/ is deployed to Vercel with History API fallback to index.html for /globe. sharp + pngjs generate og-image.png (1200x630) at build.

Challenges we ran into

  1. Blank arena on Play: flatCanvas.style.display='none' while globe was visible made resize() measure 0x0 → bitmap clamped to 1x1. Fixed with requestAnimationFrame(resize) after flipping back to flat + a resize listener.
  2. Ink looked tiny when zoomed: Pattern was a fixed tile. Fixed by pattern.setTransform(new DOMMatrix([k,0,0,k,0,0])) where k = cellSize / 128.
  3. Cold free-tier AI channel: ~40% fail rate when cold, 10-20s cooldown. Solved with batched streaming, single in-flight request per session, cooldown-aware retries, and an OFFLINE PRACTICE fallback — but top-ups never inject fallback, the exam ends with dignity instead.
  4. "Everyone wrong = no points": beginExamReveal was resetting phaseT=0 before checking botLockAt — every bot answer was discarded. Now answers are snapshotted at stoppedAt before the reset.
  5. Readable but not broken UI: An !important override for lobby readability was also killing .picked/.correct/.wrong highlights. Replaced with a scoped fix + a tick-checkbox (✔/✘) so selection is unmistakable in light/dark mode.

We verified everything headless with playwright-core + SwiftShader and npm run quality (lint + prettier + 104 tests + build + smoke).

What we learned

Shipping a real game on just HTML/CSS/Canvas taught us more than any framework: how CanvasPattern transforms work, how to make Three.js textures crisp at every zoom, and how to design around flaky LLMs (deadlines, retries, streaming) instead of pretending they're reliable.

What's next

Friends-list + voice in exam rooms, ink trading, and a teacher mode where a PDF becomes the source for the paper.


Built by students, for students. Your focus paints the world.

Built With

Share this project:

Updates

Submission history