Inspiration

Tarot has a rich symbolic language, but learning all 78 cards — each with upright and reversed meanings — is genuinely difficult. Most tarot apps are either static reference books or prediction tools. I wanted something in between: a private study companion that helps you memorize the cards, ask better questions, and use the symbolism for grounded self-reflection rather than prediction.

Tarot Learner Plus is a ground-up rewrite of a prototype I originally built in plain HTML, CSS, and JavaScript. During Build Week, I used Codex with GPT-5.6 to turn it into a tested, mobile-first application with a secure AI layer.

What it does

The core is a structured learning tool: browse the full 78-card Rider–Waite–Smith deck, practice upright and reversed meanings with spaced-repetition flashcards, and test yourself with quizzes and keyword matching. There are one-card and three-card reflective spreads, plus a monthly theme mode with daily card reveals. Everything works offline, requires no account, and stores progress locally in IndexedDB. The interface supports English, Traditional Chinese, Simplified Chinese, and Japanese.

On top of that is an optional AI layer. GPT-5.6 provides personalized reflections on spreads and coaches users to rewrite vague, binary, or predictive questions ("will he come back?") into open, self-directed ones. The app deliberately treats tarot as reflective practice, not prophecy — every AI reading is grounded in the supplied card meanings, preserves the user's agency, and ends with reflection questions or a small concrete action.

How I built it

The stack is Next.js 16, React 19, TypeScript, Tailwind CSS, IndexedDB, and a production service worker.

Codex handled the repo-wide work that is tedious to do by hand: auditing the legacy app and separating reusable content from its global-JavaScript architecture, converting and validating the multilingual card dataset, implementing spaced repetition and progress migration, writing unit tests and Playwright flows, and diagnosing artwork mapping bugs and Wikimedia rate limits. It also built a resumable pipeline that converts public-domain scans into optimized local WebP assets.

The AI layer runs through a server-side Responses API route. The browser never sees the API key and cannot select a model; the server enforces a model allowlist, input validation, request limits, timeouts, and strict JSON Schema outputs re-validated with Zod. For a spread, the model receives only the question plus each card's position, orientation, meanings, and keywords — nothing else.

Challenges I ran into

Preserving content through a rewrite. The deck has 78 cards, two orientations, stories, keywords, and four languages. Typed data structures and integrity tests made sure nothing was silently lost during migration.

Offline-first meets cloud AI. Core learning had to stay private, fast, and free, while AI requests needed a secure server boundary. The solution was keeping all progress in IndexedDB and making the AI layer strictly optional.

Responsible AI behavior. I did not want generated text presented as supernatural certainty. The prompts and output schemas require the model to reference the supplied card meanings, use agency-preserving language, and close with practical next steps.

Artwork performance. Loading original scans from Wikimedia was slow and occasionally rate-limited. The final version serves optimized WebP from the same-origin Vercel CDN and caches viewed cards offline — one homepage card went from a 1.12 MB source image to a ~24 KB responsive payload.

Accomplishments I'm proud of

The entire 78-card multilingual library survived the rewrite intact, including progress migration from the old localStorage format. The AI workflows are genuinely useful rather than a decorative chatbot. And the result is a responsive PWA with automated tests, optimized public-domain artwork, and a live Vercel deployment — no registration, no database.

What I learned

The best role for AI here is not oracle — it is learning facilitator: connecting symbols, exposing blind spots, improving questions, and returning control to the learner. Local-first and AI-assisted also turned out to be complementary: deterministic features handle repeated practice privately and for free, while the model is reserved for moments where contextual reasoning actually adds value. Codex was most effective on repo-wide loops of analysis, implementation, testing, and verification — not isolated code generation.

What's next

Adaptive practice sets based on each learner's weak cards, progress export and import, better accessibility, optional encrypted sync, and shared rate limiting for the AI gateway. Longer term, I want Tarot Learner Plus to become a reusable framework for learning any symbolic system through memory practice, structured reflection, and responsible AI coaching.

Built With

  • codex
  • gpt-5.6
  • indexeddb
  • next.js
  • openai-api
  • playwright
  • pwa
  • react
  • responses-api
  • service-worker
  • structured-outputs
  • tailwind-css
  • typescript
  • vercel
  • vitest
  • zod
Share this project:

Updates