Static, framework-free D&D 5e utility site (HTML/CSS/JS). No build step; everything runs as plain static files behind any HTTP server.
Features
- Ability Score Generator (classic 4d6 drop-lowest)
- Physical Stat Generator (race-based age/height/weight using dice-expression parsing)
- Pre-generated Characters gallery (class/level filters linking to PDFs + portraits)
This site must be served over HTTP(S). Opening pages via file:// will break shared includes because js/includeHTML.js uses XMLHttpRequest.
This workspace has a VS Code task that opens:
http://dnd5etoolscom.localhost/
Run the task: Open in Browser.
From the repo root (D:\Websites\032-2021-DnD5eTools.com):
Python
python -m http.server 8080Then open http://localhost:8080/.
Node
npx http-server -p 8080- Pages
index.html— homeabilities.html— ability score generatorphysical-stats.html— physical stats generatorpregen-characters.html— character gallery
- Shared partials
header.html,footer.html
- Styles
css/— page + shared CSS
- Scripts
js/— feature logic, include loader, and gallery rendering
- Content
documents/characters/<level>/<Class>/...— PDF sheetsimages/characters/<Class>/...— portraits
The pages use include-html="..." placeholders which are filled at runtime by js/includeHTML.js.
Implementation summary:
- finds elements with an
include-htmlattribute - fetches the referenced file via
XMLHttpRequest - injects the HTML into the element
Because this is XHR-based, you need HTTP(S) for local development.
- Page: abilities.html
- Script: js/abilityGenerator.js
Flow: click → roll → render.
Algorithm per ability:
- roll four integers in
$[1,6]$ - sum them
- subtract the lowest (drop-lowest)
- Page: physical-stats.html
- Data: js/races.js
- Logic: js/physicalCharacteristics.js
Notes:
- Race tables store dice expressions as strings (e.g.
"2d10") which are parsed at runtime. - Weight depends on the height modifier roll (matching the 5e table behavior).
- Page: pregen-characters.html
- Dataset (“API stand-in”): js/characters-api.service.js
- Renderer: js/characters.service.js
- Wiring / bootstrapping: js/app.js
- Filter helpers: js/setMaxLevel.js, js/getCharacterSelection.js
The gallery is intentionally “static-host friendly”: it does not discover files on disk. Instead, it builds URLs from the selected class/level + dataset fields.
PDFs live under:
documents/characters/<level>/<Class>/
and are expected to follow the naming pattern:
<Class> <level> [<Build>] - <Character Name>.pdf
Example:
documents/characters/5/Warlock/Warlock 5 [The Undying] - Utassi Birdcruncher.pdf
Portraits live under:
images/characters/<Class>/
and are expected to follow:
<Character Name>.jpg
Verdan special case:
- if
character_raceis exactlyVerdan, the gallery expects either"<Name> (Young).jpg"(level < 5) or"<Name> (Mature).jpg"(level >= 5).
The gallery’s URL construction depends on exact string matches across:
- the class dropdown options in pregen-characters.html
- folder names under
documents/characters/...andimages/characters/... - the dataset strings in js/characters-api.service.js
Spelling, spaces, punctuation, and casing all matter.
- Add a dataset entry in js/characters-api.service.js.
- Add the PDF under
documents/characters/<level>/<Class>/using the filename pattern above. - Add the portrait under
images/characters/<Class>/using the filename pattern above.
- Add/update the race object in js/races.js.
- Add/update the
<option>label text in physical-stats.html. - Ensure
prepCharacter(...)in js/physicalCharacteristics.js maps that label to the correct race object.
prepCharacter(...) currently compares the selected dropdown label text against explicit strings, so UI labels and mapping strings must be kept in sync.
Key stylesheets:
- css/common.css — typography and shared primitives
- css/main.css — tool page layout + responsiveness
- css/menu.css — hamburger/overlay navigation
- css/characters.css — gallery grid + card styles
- Header/footer don’t appear: you likely opened via
file://instead of serving over HTTP. - Character image/PDF 404s: verify folder names + filenames match the conventions exactly.
- Race doesn’t generate: ensure the dropdown option label matches
prepCharacter(...)’s expected string.
This is a static site:
- copy the repo contents to any static host (IIS/Nginx/Apache/S3-style)
- no environment variables or build pipeline required
If serving from a sub-path, verify relative links still resolve (the site uses relative URLs).
This project is a fan-made utility site for tabletop gameplay and is not affiliated with or endorsed by Wizards of the Coast. Dungeons & Dragons and D&D are trademarks of Wizards of the Coast.