August 17, 2026 · active
Card Studio
Browser editor for AI character cards and lorebooks. Lossless import and export, live token counts, lint, and a trigger tester. Testing whether I could ship a finished product, not a prototype, with AI doing the engineering.
Why this exists
Most of my experiments are prototypes. This one was a test of finishing: a product with a spec, a conformance suite, a privacy guarantee, and a README someone else could follow.
The domain is AI roleplay character cards, a file format used by SillyTavern, Risu, JanitorAI and others. Every app handles the format slightly differently and most editors lose data on the way through.
What it does
Imports anything. PNG cards with any text chunk type, including ones other tools reject. JSON cards in spec v1, v2, and v3. SillyTavern world-info books.
Exports losslessly. A card survives import, edit, export with zero data loss, including fields the interface never shows. Exported PNGs carry both a v3 chunk and a backward-compatible v2 chunk.
Tests triggers. Paste a sample chat and see which lorebook entries fire, which almost fired and why they did not, and the assembled prompt.
Counts tokens live. Every field, while you type, with honest accuracy labelling.
Lints. Warnings for token bloat, greetings that speak for the user, empty first messages, and per-platform export quirks.
What it looks like


Privacy as a tested guarantee
The app makes zero network requests at runtime. No analytics, no telemetry, no CDN fonts. An automated test enforces it. Cards are stored in the browser’s IndexedDB and nowhere else.
What I learned
The spec is the product. Encoding the character card spec as Zod schemas and making that the single source of truth is what made lossless round-tripping possible. Everything else followed from it.
Stack
TypeScript strict, Zod, Vite, a conformance test suite, ESLint with zero warnings allowed. Deploys as a fully static site.