05 / Software / interactive experience
Vatic
A reading becomes more useful when there is somewhere to return to it.
- Role
- Cesar Delgado · product direction & development
- Status
- Implemented local prototype
- Technology / medium
- Next.js · React · TypeScript · Tailwind CSS
- Focus
- Product evolution, state integrity, responsible AI integration

- 1 / 3 / 5
- Card spread sizes
- 3
- Core screens: Draw, Journal, Revisit
- Isolated
- A no-signup fictional demo
From a draw to a reflective practice
Vatic is a tarot reflection journal for people who want to keep questions, card meanings and later perspectives together. It is built around three screens: Draw a reading, find it in the Journal, then Revisit it with a dated reflection and a self-reported outcome.
Cesar’s product direction evolved an existing tarot app into this journal experience, with Moira as an optional AI oracle. The implementation is local and has not been publicly released. There is no account or cloud synchronization in the current edition.
Preserve first, extend second
The scope included preserving existing saved readings and legacy outcomes while adding notes, tags, search, filters, exports and dated reflections. The demo had to be useful without signup and separate from a person’s journal. AI interpretation was restored as an explicit user action, rather than an automatic step in every draw.
A calm interface with explicit boundaries
Draw with intention
One-, three- and five-card spreads share a keyboard-accessible reveal interaction. “Draw & save reading” makes persistence part of the action’s label instead of leaving the user to guess whether a draw was saved.
Revisit without scoring belief
Later reflections keep their dates and personal outcomes. Older outcome values stay compatible, while their labels describe whether a reading resonated. They are not turned into a predictive-accuracy score.
Let the demo be a real workspace
Demo readings can be edited, searched, reflected on, exported and deleted in their own session store. Exiting the demo returns to the personal journal without merging either set of records.
Ask Moira explicitly
A disclosure shows the saved question and cards before an interpretation is requested. Notes, tags, reflections, other readings and previous interpretations are excluded from the provider prompt.

Compatibility is part of the architecture
The Next.js, React, TypeScript and Tailwind app separates screen components, a readings hook, storage and normalization logic, card and spread definitions, and a server-only interpretation endpoint. The storage layer accepts a narrow interface so persistence behavior can be exercised without a browser.
Personal readings keep the existing local-storage format. Legacy single-card entries are normalized in memory and upgraded on a later successful write. The reading collection and its current-reading pointer are written together. Invalid stored data is not silently reset; the interface offers an export of the original data for recovery.
- 01Draw / editTyped reading and reflection data
- 02Validate & normalizePreserve legacy shapes and IDs
- 03PersistPersonal local storage or demo session storage
- 04Render / revisitSearchable records and dated reflections
A separate boundary for AI
The browser sends a validated reading request to a server route; provider credentials stay on the server. The route checks origin and request shape, limits body size, deduplicates matching requests and uses bounded process-local rate limits. Moira is requested only by the user, and saved interpretations can be reused.
A generated result remains visible if a local save fails, with a retry to save it without requesting another interpretation. Demo interpretations are locally prepared, clearly labeled fictional text and never call the provider.
The tradeoffs are visible
Local persistence avoids a cloud journal account, but brings device and browser dependence. JSON exports provide portable copies; import and synchronization are not implemented. Process-local AI limits are suitable for a bounded local prototype, not distributed production protection.
Protect the journal through change
Compatibility and recovery
The project’s automated coverage exercises legacy reading normalization, missing-card fallbacks, malformed data, save failures and recovery exports. Existing records are preserved rather than reseeded.
End-to-end journal behavior
Recorded browser validation covers draws, keyboard reveals, persistence, editing, search and filters, dated reflections, exports, deletion confirmation and demo isolation across 320, 390, 768, 1024 and 1440px layouts.
AI success and failure paths
Provider-mocked checks cover request payloads, success and reload, errors and retries, duplicate clicks, save failures and offline demo behavior. Live paid-provider access has not been tested.
Quality gates
The latest project validation records lint, TypeScript, a production build and 35 passing unit tests, alongside journal and mocked-AI browser suites. Those are implementation checks, not evidence of a public deployment or user adoption.

A local prototype with a clear release boundary
Before publication, the inherited card artwork needs verified per-image provenance and attribution. The current screenshots demonstrate the implementation; they do not claim that the deck art was newly created or cleared for public release.
Further release work includes validating live-provider configuration separately, reviewing production abuse controls and deciding how journal backup or restore should work. Cloud sync, billing and accounts remain outside this edition.
