The interesting calls — the ones that reveal how the product was thought about.
01
JSONB for entity field schemas
Entity types in a lore tool can't have a fixed schema — a Magic System has completely different fields to a Character. Rather than a generic EAV table, entity fields are stored as JSONB columns in PostgreSQL, which keeps queries readable and allows GIN indexing for search. The schema definition is itself stored per entity type, so the frontend can dynamically render the right form.
02
Custom PHP API over a framework
This project is intentionally a learning exercise with technology outside my usual stack. Building the REST API by hand — routing, middleware, JWT, error handling — meant learning PHP 8.2 idioms deeply rather than delegating them to Laravel or Slim. Every endpoint is explicit and traceable, which matters for a solo project you need to maintain months later.
03
Mobile-first, not mobile-adapted
The target user is a fiction author writing away from a desk — on a couch, a commute, a café. The mobile UI was designed first, with the desktop layout derived from it. The same information architecture and tab structure appears on both breakpoints; only the panel layout changes. This is reflected in how the component library was built: mobile variants are the canonical versions.
04
Sage as the only interactive colour
The design system uses a single interactive hue — sage — for all clickable elements, focus rings, active states, and primary actions. Gold is reserved for the logo mark and milestone badges only. This restraint keeps the UI calm during long writing sessions and makes interactive affordances immediately obvious. It also means the warm, ink-and-paper editor surface feels like a distinct context from the chrome.
05
Trigger words, not manual linking
Rather than requiring authors to manually insert entity links as they write, each Codex entity carries a set of configurable trigger words. The manuscript parser scans prose for matches and links them automatically. The entity name is included by default; aliases and abbreviations are added manually. This keeps the writing experience frictionless — you don't stop to tag, you just write.
06
Split hosting over monolith
The Next.js frontend and PHP API are deployed as separate Render services rather than co-located. This keeps the frontend and backend independently deployable and scalable, mirrors a professional production setup, and means the API can be reused by a future mobile app. The cost trade-off is two services to manage, which is acceptable for a project at this scale.