Character Detail Page
The character detail page (/characters/:characterId) is the richest UI surface in the app โ a WoW-style character sheet with a 3D model viewer, equipment panels, and spec-aware color theming.
Page Layoutโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Page-level aura โ โ fixed radial gradient, spec color
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Profile Card โ โ โ avatar, name, class, chips
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโฌโโโโโโโโโโโฌโโโโโโโ โ
โ โ Left โ 3D Model โ Rightโ โ โ desktop: 3-column grid
โ โ gear โ Viewer โ gear โ โ
โ โโโโโโโโดโโโโโโโโโโโดโโโโโโโ โ
โ [ MH ] [ OH ] โ โ weapons centered below
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Mobile equipment grid โ โ โ mobile: flat grid below model
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Responsive Behaviorโ
- Desktop (
lg:breakpoint): 3-column CSS grid (220px / 1fr / 220px). Left column shows headโwrist, right column shows handsโtrinkets. Weapons sit centered below the model. The mobile grid is hidden. - Mobile: Equipment columns are hidden. A single-column (2-col on
sm:) grid renders all items sorted by slot order below the model. - The
WowModelVieweris rendered once and shared across both layouts. This avoids duplicate WebGL contexts.
File Mapโ
| File | Purpose |
|---|---|
routes/characters/-CharacterDetailPage.tsx | Page component, layout, equipment panels |
components/game/WowModelViewer.tsx | 3D character model (WebGL) |
components/game/aura-colors.ts | Spec-aware aura color lookup |
components/game/CharacterCardBackground.tsx | Faction-tinted card background |
components/game/FactionChip.tsx | Horde/Alliance chip |
3D Model Viewerโ
WowModelViewer renders an interactive 3D character model with equipped gear and transmog.
Propsโ
| Prop | Type | Description |
|---|---|---|
race | string | Character race name (mapped to Blizzard race ID internally) |
gender | string | null | "MALE" or "FEMALE" |
characterClass | string? | Used for aura color fallback |
characterSpec | string? | null | Used for spec-specific aura color |
items | Array<{ slotType, itemId, transmogItemId? }> | Equipped items; transmog preferred when available |
appearanceOptions | Array<{ optionId, choiceId }>? | null | Character customization options (skin, hair, etc.) |
appearanceItems | Array<{ slotType, itemId, modifierId }>? | null | Appearance-specific item overrides |
Rendering Pipelineโ
- Race ID resolution โ Maps race name string to Blizzard numeric race ID. Supports underscore and no-underscore variants (e.g.
blood_elfandbloodelf). - Item display resolution โ For each equipped item, fetches display info from WoWHead via nginx proxy (
/wowhead-api/item={id}&xml). Extractsdisplayid, appearance modifiers, andslotbak(robe detection). Results are cached in a module-levelMap. - Slot mapping โ Maps slot types to numeric IDs. Armor slots use equipment positions (1โ19). Weapons use WoWHead inventory types (21=main hand, 22=off hand) because ZamModelViewer misroutes slots 16/17.
- Model instantiation โ Two paths:
- ZamModelViewer (preferred): Used when appearance customization data is available and the ZamModelViewer script is loaded. Supports full character customization (skin color, hairstyle, etc.).
- wow-model-viewer (fallback): NPM package, used when no customization data is available. Renders with
noCharCustomization: true.
- Reveal โ Model starts at
opacity: 0with a spinner overlay. After 800ms post-load, fades in.
Dracthyr Handlingโ
Dracthyr characters have two forms โ dragon and visage (humanoid). The viewer:
- Detects dracthyr race and shows a Dragon/Visage toggle
- Filters appearance options to the correct set per form (separate option ID sets)
- Uses race ID 45 for dragon form, 64 for visage form
Aura System (Toggleable)โ
The model viewer has a built-in aura overlay system that's currently disabled (showModelAura = false). When enabled, it renders:
- An accent-colored silhouette backdrop behind the model
- Two animated pulsing gradients (7s and 10s cycles, offset timing)
The aura color is determined by:
- Extracted dominant color โ Samples the WebGL canvas after render, weighted by saturation
- Spec fallback โ
aura-colors.tsmaps every class/spec to a hand-tuned hex color - Class fallback โ Falls back to the standard WoW class color
Aura Color Systemโ
aura-colors.ts provides spec-aware color theming used by both the page-level gradient and the (toggleable) model aura.
How It Worksโ
getAuraColor(class, spec)
โ look up SPEC_AURA_COLORS[class/spec] (e.g. "priest/shadow" โ #6B21A8)
โ fallback: getClassColor(class) (standard WoW class color)
โ returns [r, g, b] tuple or null
Every class/spec combination has a hand-picked color. Examples:
| Spec | Color | Reasoning |
|---|---|---|
| Priest / Shadow | #6B21A8 | Deep purple |
| Mage / Frost | #60C5F1 | Ice blue |
| Death Knight / Blood | #8B1A1A | Dark crimson |
| Evoker / Preservation | #33937F | Teal green |
Page-Level Auraโ
The CharacterDetailPage renders a fixed radial-gradient(circle at 50% 55%, ...) using the spec aura color at 25% opacity. This washes the entire page in the character's spec color, centered on the model area.
Equipment Displayโ
Item Quality Colorsโ
Items are color-coded by WoW quality tier:
| Quality | Color |
|---|---|
| Poor | #9d9d9d |
| Common | #ffffff |
| Uncommon | #1eff00 |
| Rare | #0070dd |
| Epic | #a335ee |
| Legendary | #ff8000 |
Slot Layoutโ
Desktop splits equipment into three groups:
- Left column (icon right-aligned, text left): Head, Neck, Shoulder, Back, Chest, Tabard, Wrist
- Right column (icon left-aligned, text right): Hands, Waist, Legs, Feet, Ring 1, Ring 2, Trinket 1, Trinket 2
- Weapons row: Main Hand, Off Hand (centered below model)
Mobile shows all items in a flat sorted grid with slot labels, ilvl, enchant/gem indicators.
External Dependenciesโ
| Dependency | Purpose | Loaded via |
|---|---|---|
wow-model-viewer (npm) | Fallback 3D renderer | Dynamic import() |
| ZamModelViewer | Full-featured renderer with customization | Script tags in index.html |
| jQuery | Required by ZamModelViewer | Script tag in index.html |
| WoWHead API | Item display ID resolution | Proxied via nginx (/wowhead-api/) |
Nginx Proxyโ
WoWHead requests are proxied through nginx to avoid CORS issues:
/wowhead-api/ โ https://nether.wowhead.com/tooltip/
Configured in docker/nginx/dev.conf.
Design Decisionsโ
- Single model instance: The viewer was originally rendered twice (desktop and mobile). Even with CSS
hidden, both mounted and created WebGL contexts. Consolidated to one instance that lives inside the responsive grid โ equipment columns hide/show around it. - Module-level display info cache: WoWHead fetches are cached in a
Mapoutside the component to survive re-renders and avoid redundant network requests. - Transmog preference: When
transmogItemIdis present on an equipped item, it's used instead of the baseitemIdfor visual display. - Slot 20 for robes: WoWHead reports
slotbak: 20for robe-type chest pieces. The viewer remaps these from slot 5 to slot 20 so the model renders the full-length robe instead of a chest-only piece.