4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
This renders printable D&D 5e spell reference cards for a specific character ("Oswin Eisenbach", a Forest Gnome Artificer). index.html is the static page (Tailwind CSS, Flowbite, and Google Fonts from CDNs, no build step), but spell data lives in JSON files under characters/, loaded at runtime via fetch().
Running / Previewing
index.html fetches JSON files, which browsers block on file:// URLs (CORS). You must serve the directory:
python3 -m http.server
then open http://localhost:8000/. Opening index.html directly will not load any spells.
Architecture
index.html
-
<style>block — card visual design (.spell-card,.card-header,.stat-row,.card-body,.card-footer,.level-flag, etc.) plus per-school color theming via classes like.school-conjuration,.school-evocation, etc. (each sets--school-col/--school-bgCSS custom properties consumed by the card components). Also defines@media printrules and an@pagerule (A4 portrait, 12mm margin, 3-column grid) so the page can be printed directly to physical cards sized at 2.5×3.5 in (240×336px at 96dpi, set via--card-w/--card-h). -
UI chrome (
.ui-panel) — toggle buttons to filter cards by spell level (#type-filters) and school (#school-filters), built dynamically from the loaded data, plus a "Print Cards" button that callswindow.print(). Elements marked.no-printare hidden when printing. The card grid (#card-grid, also.print-area) is the same element in both screen and print view — print CSS just swaps it from a flex-wrap layout to a 3-column grid. -
Data + render logic (final
<script>):CHARACTER_DIR— path to the active character's data folder (currentlycharacters/oswin-eisenbach).loadSpells()— fetchesmanifest.jsonfor the character, then fetches every spell JSON file it lists, populatesSPELLS, builds the filter buttons, and renders.SPELLS— array of spell objects, populated at runtime from JSON. Each spell has:name,level("cantrip"or a numeric string like"1"),levelDisplay,school,castingTime,range,components,duration, optionaldamage/saveDC/material,source(book/page citation),uses(e.g."At Will","Spell Slot","2× / Long Rest"),tags(array of short labels), anddesc(array of HTML-containing paragraph strings — inline<b>/<em>tags are used for emphasis directly in the data).SCHOOL_ABBR— maps school name to a 2-letter abbreviation shown in the circular "pip" badge on each card.buildCard(spell)— returns the HTML string for one card, assembling stat chips, description paragraphs, tags, footer, and a corner.level-flag(grey "Cantrip" vs. gold "Lvl N Spell") from a spell object.buildFilters(typeLabels)— generates the type and school filter buttons after data loads, based on what's actually present.renderCards()— filtersSPELLSby the currentactiveType/activeSchoolglobals and re-renders the#card-gridcontainer.filterType(btn, val)/filterSchool(btn, val)— button click handlers that update filter state, toggle the.activeclass on buttons, and callrenderCards().
characters/<character-folder>/
manifest.json—{ character, subtitle, types: [{ level, label, files: [...] }] }.levelis the folder name and matches the spell'slevelfield ("cantrip","1","2", ...);fileslists the JSON filenames inside that level's folder, in display order.<level>/<spell-slug>.json— one spell per file, same shape as the spell objects described above (nolevel/levelDisplayredundancy issue — both are still included in the file since the card needs them).
Adding/editing spells
To add a new spell, create a JSON file in the right characters/<character>/<level>/ folder (create the folder if it's a new level) and add its filename to that level's files array in manifest.json. To add a new school, add both a .school-<name> CSS rule (lowercase school name) and an entry in SCHOOL_ABBR in index.html — filter buttons for schools and levels are generated automatically from whatever data loads.
To add a second character, create a new characters/<folder>/ with its own manifest.json and level folders, then point CHARACTER_DIR in index.html at it (there is currently no in-page character switcher).