Skip to content

D&D 5e character creation tools built with plain HTML, CSS, and JavaScript. Includes ability score generation, race-based physical stat generators, and a scalable pre-generated character gallery—all framework-free, static, and designed for clarity, maintainability, and long-term use at the table.

Notifications You must be signed in to change notification settings

FrankJamison/2021DnD5eTools

Repository files navigation

DnD 5e Tools — Static Web App (HTML/CSS/JS)

DnD 5e Tools is a framework-free, static website that delivers three “table-ready” utilities for Dungeons & Dragons 5e:

  • Ability Score Generator (classic 4d6 drop-lowest)
  • Physical Stat Generator (race-based age/height/weight with dice parsing)
  • Pre-generated Characters gallery (filterable cards linking to PDFs + portraits)

This repo is intentionally “vanilla” (no build step) to highlight fundamentals: clear DOM manipulation, predictable asset conventions, and simple separation between data/service code and UI rendering.

If you’re an employer/recruiter: this project demonstrates practical front-end engineering skills (layout, UX consistency, state/data flow, deterministic file conventions, and maintaining a non-trivial dataset) without hiding behind frameworks.


Quick Facts (for recruiters)

  • Product: static D&D 5e companion tools + pregen character library
  • Scope: multiple pages, shared layout, interactive generators, dataset-backed gallery
  • Stack: HTML5, CSS3 (Flexbox), JavaScript + jQuery 1.12.4, light polyfills for compatibility
  • Deployment: any static host (IIS/Apache/Nginx/GitHub Pages-style hosting), no build pipeline

Pages

  • Home: index.html
  • Ability Generator: abilities.html
  • Physical Stat Generator: physical-stats.html
  • Pre-generated Characters: pregen-characters.html

Tech Stack & Constraints

Frontend

  • HTML5, semantic-ish page structure
  • CSS3 with Flexbox-based layout, responsive breakpoints, and a D&D-inspired theme
  • JavaScript
    • jQuery for click handlers and simple DOM updates on the generator pages
    • Vanilla DOM APIs for the character gallery renderer

Compatibility

  • pregen-characters.html loads ES5/ES6 shims via CDN (for older runtimes)

No build step

  • No bundler, transpiler, or package manager required
  • Runs as static files behind any web server

Local Development

Because this site uses XMLHttpRequest to load shared HTML partials (header/footer), it must be served over HTTP(S). Opening files directly via file:// will not load includes.

Option A — Use your existing local web server

  • This workspace appears to be configured to run at http://2021dnd5etools.localhost/.
  • If you already have that host + server set up, you can use the VS Code task “Open in Browser”.

Option B — Quick local server (no install)

Using Python (if installed):

cd d:\Websites\2021DnD5eTools
python -m http.server 8080

Then visit: http://localhost:8080/index.html

Using Node (if installed):

cd d:\Websites\2021DnD5eTools
npx http-server -p 8080

High-Level Architecture

This codebase uses a straightforward “static multi-page app” approach:

  1. Shared layout via HTML partials
  • header.html and footer.html contain shared navigation and footer markup.
  • js/includeHTML.js implements a tiny include system:
    • finds nodes with include-html="..."
    • fetches the referenced file via XMLHttpRequest
    • injects the HTML into the element
  1. Feature pages are small and explicit
  • Each page includes only the CSS it needs and the JS modules it needs.
  • Generators: simple “event → compute → render” flow
  • Character gallery: “service → list renderer → DOM mount” flow
  1. Data is organized by convention
  • Pre-generated character PDFs live under documents/characters/<level>/<Class>/...
  • Portraits live under images/characters/<Class>/...
  • The gallery builds links based on these conventions.

Feature Breakdown (Design + Implementation)

1) Ability Score Generator

User experience

  • Single-call-to-action button
  • Shows results in two useful presentations:
    • “Assigned” (STR → CHA) for quick character sheet filling
    • “Ordered” (high → low) for decision making

Implementation

  • Page: abilities.html
  • Script: js/abilityGenerator.js
  • Uses jQuery $(document).ready(...) and a click handler on #calc-abilities
  • Core algorithm per ability:
    1. roll four integers in [1..6]
    2. sum them
    3. subtract the lowest
  • Scrolls to results using window.location.href = '#calculated-abilities'

Engineering notes

  • Logic is intentionally readable and testable as pure functions (rollAbility, rollAbilities).

2) Physical Stat Generator (Race-based)

User experience

  • Large select list of races
  • One-click generation
  • Shows both:
    • “Your Stats” (a specific roll)
    • “Racial Stat Ranges” (min/max and age brackets)

Implementation

  • Page: physical-stats.html
  • Data model: js/races.js
    • character object holds runtime state
    • race definitions store dice expressions as strings like "2d10"
  • Logic: js/physicalCharacteristics.js
    • prepCharacter(raceName) maps the selected UI string to a race table
    • getCharacteristicRanges() computes age brackets and min/max ranges
    • rollDice('XdY') parses dice expressions to produce random rolls
    • convertInchesToFeet(...) provides user-friendly height output

Design decisions

  • Dice expressions are stored as human-readable strings rather than hard-coded distributions.
  • Weight depends on the height modifier roll (matching 5e table behavior).

3) Pre-generated Character Gallery

User experience

  • Filter by class and level
  • Card-based layout with portrait + key info
  • One-click access to a PDF character sheet

Implementation

  • Page: pregen-characters.html
  • “Service” layer: js/characters-api.service.js
    • returns an in-memory array of character records (a stand-in for a real API)
    • record shape:
      • character_id
      • character_name
      • character_race
      • character_class
      • character_build
      • character_max_level
  • UI renderer: js/characters.service.js
    • CharacterList renders cards using vanilla DOM APIs
    • filters by selected class and level
    • contains special-case portrait naming for Verdan variants by level
  • Wiring:
    • js/app.js instantiates CharactersService and CharacterList, then calls characterList.init()
    • js/setMaxLevel.js populates the level dropdown on class change
    • js/getCharacterSelection.js prevents form submission and triggers re-render

Asset/link conventions

Character PDFs:

documents/characters/<level>/<Class>/<Class> <level> [<Build>] - <Character Name>.pdf

Portraits:

images/characters/<Class>/<Character Name>.jpg

Why conventions matter

  • The gallery does not “discover” files; it computes URLs from the selected filters + the dataset.
  • This makes it easy to host as static files, and easy to audit/maintain once the convention is known.

UI/UX & Visual Design

Theme

  • The look aims for a D&D “book/leather/metal” feel using:
    • textured background images
    • warm gold/red accent colors
    • decorative divider sprites
    • the Cinzel/Cinzel Decorative typefaces

Layout

  • Flexible, responsive layout using Flexbox
  • Fixed header + fixed footer to keep navigation and attribution visible
  • Hamburger/overlay navigation implemented with a CSS-only toggler pattern

Key styling files

  • css/common.css: typography, shared elements (buttons, dividers), base layout primitives
  • css/main.css: main content layout, tool page layout, responsiveness
  • css/menu.css: hamburger menu and full-screen overlay animation
  • css/characters.css: character gallery card grid and card styling

Extending the Project

Add a new pre-generated character

  1. Add a PDF:
    • Place it under documents/characters/<level>/<Class>/... using the naming convention.
  2. Add a portrait:
    • Place it under images/characters/<Class>/<Character Name>.jpg.
  3. Add a dataset row:
    • Add a new object entry to js/characters-api.service.js.

Add a new race to the physical generator

  1. Add a race object in js/races.js (age, base height/weight, dice modifiers)
  2. Add the race to the <select> in physical-stats.html
  3. Add mapping logic in prepCharacter(...) in js/physicalCharacteristics.js

Deployment

Because this is static, deployment is simple:

  • Any static web host works (IIS, Nginx, Apache, S3-style static hosting)
  • No environment variables required
  • If you serve from a sub-path, ensure relative URLs remain correct (most links are relative)

Notes for Reviewers / Future Improvements

If you’re reading this as part of an interview loop, here are realistic improvements that would be good “next steps” in a production iteration:

  • Replace the long if/else mapping in prepCharacter(...) with a dictionary/lookup table to reduce repetition
  • Extract the character dataset to a JSON file and fetch it (keeps JS smaller and makes data easier to update)
  • Add lightweight unit tests for the pure functions (dice parsing, ability rolling)
  • Improve accessibility: keyboard nav for menu, verify color contrast, ensure consistent alt text
  • Fix minor HTML validity issues (e.g., some images/viewport meta attributes)

Disclaimer

This project is a fan-made utility site for tabletop gameplay. It is not affiliated with or endorsed by Wizards of the Coast.

Special case:

  • For Verdan, the image path changes based on level (< 5 uses (Young), >= 5 uses (Mature)).

“Service + View” Separation

The gallery is split into two layers:

  • CharactersService (js/characters-api.service.js): provides character data (currently static, but structured like a real API call)
  • CharacterList (js/characters.service.js): turns records into DOM and mounts them under #characters

Local Development

This project must be served over HTTP (not opened via file://) because shared partials are loaded using XMLHttpRequest.

Serve as static files (quick setup)

Any static server works; here are a few common choices:

Python

# from the repo root
python -m http.server 8000

Then open the URL printed by the server (typically http://127.0.0.1:8000/).

Node (one-liner)

npx serve .

VS Code convenience (optional)

If you use VS Code tasks, you can run the workspace’s Open in Browser task (see .vscode/tasks.json) to open whatever URL you’ve configured for your local server.


Extending the Content

Add a new pre-generated character

  1. Add a new record to the array returned by CharactersService.getCharacters() in js/characters-api.service.js.
  2. Add the PDF to:
documents/characters/<level>/<Class>/
  1. Add the portrait image to:
images/characters/<Class>/

Ensure the filename matches the conventions described above.

Naming rules (gallery relies on exact strings)

The gallery builds file paths from a mix of:

  • the selected class/level in the form (dropdown text/value), and
  • the character record fields (character_name, character_build, character_class, character_race).

That means spelling, spaces, punctuation, and casing must match across:

  • the class dropdown (pregen-characters.html)
  • folder names under documents/characters/<level>/<Class>/ and images/characters/<Class>/
  • the character_name and character_build strings in js/characters-api.service.js

PDF filenames are generated like:

<Class> <level> [<Build>] - <Character Name>.pdf

Example:

documents/characters/5/Warlock/Warlock 5 [The Undying] - Utassi Birdcruncher.pdf

Image filenames are generated like:

<Character Name>.jpg

Example:

images/characters/Warlock/Utassi Birdcruncher.jpg

Verdan special case:

  • For a character whose character_race is exactly Verdan, the image name must be either "<Name> (Young).jpg" (level < 5) or "<Name> (Mature).jpg" (level >= 5).

Add or adjust a race

  1. Add/update the race object in js/races.js.
  2. Ensure prepCharacter() in js/physicalCharacteristics.js maps the UI label to the correct race object.

Naming rules (physical stats)

prepCharacter(race) compares the selected dropdown label text (e.g. "Elf, Dark (Drow)") against a long set of if/else string checks.

When adding/renaming a race:

  • Update the <option> label text in physical-stats.html and the matching string in prepCharacter() together.
  • Ensure the referenced race object exists in js/races.js and has the expected fields (AdultAge, MaxAge, BaseHeight, HeightModifier, BaseWeight, WeightModifier).

Engineering Notes (Portfolio Highlights)

  • Separation of concerns: a small “service” layer (CharactersService) provides structured data, while CharacterList focuses on DOM rendering.
  • Deterministic conventions: PDFs and images are linked through consistent folder/file naming so content can scale without rewriting logic.
  • Progressive compatibility: shims are included where needed to keep client-side logic working across older environments.

Disclaimer

This project is a fan-made utility site and is not affiliated with Wizards of the Coast. Dungeons & Dragons and D&D are trademarks of Wizards of the Coast.

About

D&D 5e character creation tools built with plain HTML, CSS, and JavaScript. Includes ability score generation, race-based physical stat generators, and a scalable pre-generated character gallery—all framework-free, static, and designed for clarity, maintainability, and long-term use at the table.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published