Files
dnd-spell-cards/CLAUDE.md
T

4.5 KiB
Raw Blame History

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

  1. <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-bg CSS custom properties consumed by the card components). Also defines @media print rules and an @page rule (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).

  2. 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 calls window.print(). Elements marked .no-print are 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.

  3. Data + render logic (final <script>):

    • CHARACTER_DIR — path to the active character's data folder (currently characters/oswin-eisenbach).
    • loadSpells() — fetches manifest.json for the character, then fetches every spell JSON file it lists, populates SPELLS, 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, optional damage/saveDC/material, source (book/page citation), uses (e.g. "At Will", "Spell Slot", "2× / Long Rest"), tags (array of short labels), and desc (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() — filters SPELLS by the current activeType/activeSchool globals and re-renders the #card-grid container.
    • filterType(btn, val) / filterSchool(btn, val) — button click handlers that update filter state, toggle the .active class on buttons, and call renderCards().

characters/<character-folder>/

  • manifest.json{ character, subtitle, types: [{ level, label, files: [...] }] }. level is the folder name and matches the spell's level field ("cantrip", "1", "2", ...); files lists 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 (no level/levelDisplay redundancy 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).