Skip to main content

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 WowModelViewer is rendered once and shared across both layouts. This avoids duplicate WebGL contexts.

File Mapโ€‹

FilePurpose
routes/characters/-CharacterDetailPage.tsxPage component, layout, equipment panels
components/game/WowModelViewer.tsx3D character model (WebGL)
components/game/aura-colors.tsSpec-aware aura color lookup
components/game/CharacterCardBackground.tsxFaction-tinted card background
components/game/FactionChip.tsxHorde/Alliance chip

3D Model Viewerโ€‹

WowModelViewer renders an interactive 3D character model with equipped gear and transmog.

Propsโ€‹

PropTypeDescription
racestringCharacter race name (mapped to Blizzard race ID internally)
genderstring | null"MALE" or "FEMALE"
characterClassstring?Used for aura color fallback
characterSpecstring? | nullUsed for spec-specific aura color
itemsArray<{ slotType, itemId, transmogItemId? }>Equipped items; transmog preferred when available
appearanceOptionsArray<{ optionId, choiceId }>? | nullCharacter customization options (skin, hair, etc.)
appearanceItemsArray<{ slotType, itemId, modifierId }>? | nullAppearance-specific item overrides

Rendering Pipelineโ€‹

  1. Race ID resolution โ€” Maps race name string to Blizzard numeric race ID. Supports underscore and no-underscore variants (e.g. blood_elf and bloodelf).
  2. Item display resolution โ€” For each equipped item, fetches display info from WoWHead via nginx proxy (/wowhead-api/item={id}&xml). Extracts displayid, appearance modifiers, and slotbak (robe detection). Results are cached in a module-level Map.
  3. 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.
  4. 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.
  5. Reveal โ€” Model starts at opacity: 0 with 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:

  1. Extracted dominant color โ€” Samples the WebGL canvas after render, weighted by saturation
  2. Spec fallback โ€” aura-colors.ts maps every class/spec to a hand-tuned hex color
  3. 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:

SpecColorReasoning
Priest / Shadow#6B21A8Deep purple
Mage / Frost#60C5F1Ice blue
Death Knight / Blood#8B1A1ADark crimson
Evoker / Preservation#33937FTeal 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:

QualityColor
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โ€‹

DependencyPurposeLoaded via
wow-model-viewer (npm)Fallback 3D rendererDynamic import()
ZamModelViewerFull-featured renderer with customizationScript tags in index.html
jQueryRequired by ZamModelViewerScript tag in index.html
WoWHead APIItem display ID resolutionProxied 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 Map outside the component to survive re-renders and avoid redundant network requests.
  • Transmog preference: When transmogItemId is present on an equipped item, it's used instead of the base itemId for visual display.
  • Slot 20 for robes: WoWHead reports slotbak: 20 for 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.