Skip to content
Professor Basil's Lab
Full-Stack Web App

Professor Basil's Lab

2025-2026Solo project
Next.js 16React 19TypeScript 5Tailwind v4Framer MotionTanStack Query v5Rust (10 WASM crates)PeerJSVercel KVRecharts 3IndexedDBPokeAPI v2Vitest

Demo

Live Demo

Live preview of Professor Basil's Lab

Problem

A full Pokemon platform with 5 AI difficulty tiers, online PvP via PeerJS, ELO ranked ladder with global leaderboards (Vercel KV), full replay system, 8 Kanto gym leaders, Elite Four, Battle Tower/Factory, tournaments, breeding system, Safari Zone, and Nuzlocke mode. GBA emulator with ARM7TDMI + PPU emulation, NDS emulator in progress, and Rust/WASM acceleration across 10 crates. PWA-capable offline-first. 70 commits.

Constraints

  • -Zero backend. Must run entirely client-side with no server costs
  • -GBA emulator requires SharedArrayBuffer threading (restricted by COOP/COEP headers)
  • -Gen 3 save format is XOR-encrypted with 24 sub-structure permutations per Pokemon
  • -Battle damage formula must match the actual games to be credible
  • -1025 Pokemon with full stat/move/ability data, which is a large dataset for client-side

Architecture

Hook-based architecture: useTeam for team management, useBattle (useReducer state machine) for the battle engine, useWildEncounter for the catch system, useGBAEmulator for WebAssembly integration. Online PvP via PeerJS with ELO ranked ladder backed by Vercel KV. Data layer: React Context for the Pokedex, TanStack Query v5 for PokeAPI with aggressive caching. Persistence: IndexedDB for emulator SRAM blobs, localStorage for teams. Visualization: Recharts 3 for stat radar charts, type coverage matrices, and damage distributions. The battle engine is a pure function, deterministic, replay-capable, and reused for AI lookahead evaluation across 5 difficulty tiers. Full replay system records and replays battles frame by frame. GBA emulator implements ARM7TDMI CPU and PPU emulation compiled to WASM.

Tech Choices & Why

useReducer

Battle engine needs pure state transitions for determinism and replay, not a global store

IndexedDB

Binary SRAM blobs exceed localStorage's 5MB limit

TanStack Query

Caching and deduplication for 1025 Pokemon worth of API calls

WebAssembly

Only way to run mGBA at playable speed in a browser

Challenges & Solutions

Problem

Gen 3 save files use XOR encryption (PID ^ OTID key), 24 sub-structure permutations (PID % 24), and bit-packed IV values (6 stats in one 32-bit integer).

Solution

Custom binary parser using ArrayBuffer/DataView. Decrypts each 80-byte block, determines sub-structure order from PID, extracts IVs by shifting and masking 5 bits per stat. The >>> 0 unsigned coercion was critical because JavaScript's signed 32-bit bitwise ops silently corrupt XOR results without it.

Problem

WebAssembly requires SharedArrayBuffer for threading, which needs COOP/COEP headers. These headers break CDN fonts, analytics, and third-party resources across the entire app.

Solution

Scoped COOP/COEP headers to just the /emulator route. Served WASM binaries from public/ to bypass Turbopack bundling. Save states persisted to IndexedDB survive page reloads.

Problem

The damage formula accounts for STAB, type effectiveness (18x18 matrix), crits, weather, terrain, items, abilities, and three generational mechanics (Mega, Tera, Dynamax). Nested Math.floor placement matters because wrong rounding cascades into incorrect damage ranges.

Solution

Gen V+ formula as a pure function with modifiers composed as a multiplier chain. Each mechanic is a state transformation in the reducer. Verified against online damage calculators for dozens of edge cases.

Trade-offs

  • ~Initially shipped without tests for speed. Now has 63 Vitest tests covering battle engine, save parser, and catch formula. Deterministic architecture made retrofitting tests straightforward.
  • ~Client-side only means no multiplayer without a complete rewrite.
  • ~TanStack Query cache means first load is slow; subsequent loads are instant.
  • ~WASM binary is ~5MB, which is acceptable for a SPA but adds to initial page weight.

Impact

Live at professor-basils-lab.vercel.app. 70 commits, 10 Rust crates. Demonstrates binary parsing, WebAssembly integration, state machine architecture, deterministic systems design, online PvP, ELO ranking, and full replay systems. PWA-capable offline-first.

What I'd Improve

  • +Complete NDS emulator integration (DeSmuME WASM port in progress)
  • +Extract the battle engine into a standalone publishable package
  • +Expand tournament system with bracket visualization
  • +Add spectator mode for live PvP battles

This project was reviewed by Luka (Principal Research Consultant) and Nala (UI/UX Compliance Auditor). They had no comments, which we interpret as approval.

You found the bottom! 🎯