EdTechMulti-PlatformNext.jsGraphQLExpo

Yaumy — Cross-Device Learning Platform

A learning environment that synced your library, notes, and reading progress across web and iPad — designed for the rare reader who treats their books like a working notebook, not a finished archive.

Yaumy — Cross-Device Learning Platform preview

The Problem

Most reading apps optimize for finishing books. The people I built Yaumy for don’t finish — they research. They jump between chapters, write more notes than they read, leave a book mid-paragraph for a year, come back, and need everything to be exactly where they left it across device, app, and life-state.

Apple Books gets the visual right and the sync wrong. Notion gets the notes right and the reading wrong. Yaumy was the attempt to get both.

The Architecture

A monorepo across three apps sharing one GraphQL contract:

  • Web — Next.js App Router with a public marketing site and an authenticated reading playground.
  • API — NestJS GraphQL service with Apollo, Prisma over Postgres, Redis for ingestion queues.
  • Mobile — Expo React Native app, iPhone and iPad first, sharing the GraphQL types and a React Query cache with the web client.

The boring part — workspaces, Prisma migrations, embedded serverless guardrails — got more documentation than the product features did, on purpose. Once an app crosses three runtimes (browser, server, native) the operational rules need to be canonical before anyone writes a feature.

What I Learned

The Apple Books parity work is what taught me how much of a product is “the boring part.” Reading apps live or die on how the iPad client handles fonts, page-break math, and an asynchronous note that arrived while the user was offline on a flight. The novel UX wasn’t where the bar was — the bar was matching a fifteen-year-old product on craft.

Yaumy didn’t ship publicly. The docs and the platform skeleton sit in archive, and three of the engineering ideas — strict-mode guardrails, embedded serverless preflight checks, shared GraphQL types — became defaults in every project after it.