Inspiration

Language practice is most memorable when it feels like play, not homework. We wanted a social drawing game where every guess and question is real English — not rushed chat — so learners build confidence while having fun with friends. Lingo Sketch combines the energy of draw-and-guess with gentle grammar feedback, so mistakes become small teaching moments instead of embarrassment.

What it does

Lingo Sketch is a mobile-first English learning game built around drawing and guessing.

  • Play Solo — Gus, the mascot, draws a secret word while you ask yes/no questions or make guesses. A timer keeps rounds snappy, and you earn XP as you improve.
  • Play with a Friend (1:1) — Create or join a room with a short code, then take turns drawing and guessing in real time. When both players are in, the match starts automatically.
  • Grammar guard — As you type, your English is checked and corrected inline (with optional mascot-style nudges from Gus). Guesses and questions can be blocked until grammar is clean, or corrected gently in the chat feed — your choice.
  • Games history — Message threads from 1:1 matches are saved locally so you can revisit what you asked and how you phrased it.

Behind the scenes, accounts sync through Firebase Auth, game state runs over WebSockets, and user profiles live in PostgreSQL on Google Cloud SQL.

How we built it

We used a pnpm monorepo so mobile, API, and shared types stay in sync:

  • Mobile (apps/mobile) — React Native with Expo and expo-router; TanStack Query for REST; Socket.IO for live 1:1 play; custom drawing canvas and stroke sync; Firebase Auth (email/password and Google).
  • API (apps/api) — NestJS with Firebase token verification, in-memory game rooms for low-latency multiplayer, a /game Socket.IO namespace, and a grammar service (Gemini when configured, rule-based fallback otherwise). User records are stored with Drizzle ORM on Cloud SQL.
  • Shared client (packages/api-client) — OpenAPI-generated TypeScript client so the mobile app and dashboard call the same typed endpoints.
  • Infrastructure — Dockerized API deployable to Cloud Run (session affinity for WebSockets), secrets via Secret Manager, and SSL to Cloud SQL.

The flow for multiplayer: REST to create/join a room → WebSocket to enter the room and receive room:state → draw strokes, pick words, and send chat through socket events with server-side grammar enforcement.

Challenges we ran into

  • Device networking — Expo Go on a physical phone cannot reach localhost on a dev machine; we had to point EXPO_PUBLIC_API_URL at the host’s LAN IP and verify the API was reachable before create/join would work.
  • Real-time multiplayer — Keeping drawer strokes, phase transitions (waiting → word pick → drawing → guessing → solved), and chat in sync across two clients required careful state broadcasting and reconnection handling.
  • Grammar in a game loop — Balancing “learn English” with “keep the game fun” meant supporting multiple guard modes (block, inline highlight, gentle mascot corrections) on both client previews and server validation for 1:1 chat.
  • Monorepo + Metro — Wiring workspace packages (@lingo-sketch/api-client) into Expo’s bundler took extra resolver configuration so generated API types resolve reliably on device.
  • Production WebSockets — Cloud Run needed session affinity and longer timeouts so Socket.IO rooms stay stable under deploy.

Accomplishments that we're proud of

  • A complete solo loop with Gus, timed rounds, yes/no logic, and XP — playable without another person.
  • Working 1:1 multiplayer with room codes, live drawing, and shared game phases end to end.
  • A grammar guard that feels part of the game (highlighted errors, corrections, mascot copy) rather than a separate “study” screen.
  • A typed, generated API contract shared across apps, reducing drift between mobile and backend.
  • Production-shaped stack — Firebase auth, Cloud SQL, containerized API, and a path to Cloud Run — not just a local prototype.

What we learned

  • Social games are a strong motivator for language practice, but only if latency and setup friction are low — room codes and automatic start when the second player joins matter as much as the lesson design.
  • Grammar feedback works best when it is immediate and optional in tone (strict vs. gentle vs. mascot), not a single one-size-fits-all correction modal.
  • Mobile + real-time backends need explicit dev ergonomics (health checks, clear “can’t reach server” messages) because networking issues look like app bugs.
  • OpenAPI-first codegen pays off quickly in a monorepo where the same endpoints power multiple clients.

What's next for Lingo Sketch

  • Group rooms — Extend beyond 1:1 to party-style draw-and-guess with more players.
  • Share & invite polish — Native share sheet for room codes and push/deep links for invites.
  • Persistent rooms — Move game state from in-memory to Redis or the database so rooms survive API restarts and scale horizontally.
  • Richer progression — Leagues, daily streaks, and vocabulary packs tied to CEFR levels or themes.
  • Dashboard for teachers — Use the existing web app to assign words, review student phrasing from game history, and track common grammar mistakes.
  • App store release — EAS builds, TestFlight/Play internal testing, and a production API URL instead of LAN-based dev setup.
Share this project:

Updates