Meta-Build System
The meta-build system aggregates top-performing talent builds from Warcraft Logs (WCL) and provides per-character build matching via a pure fingerprint comparison. It answers two questions: "what are the current best builds?" and "does this character's loadout match one of the meta builds?"
Architecture Overview
flowchart TD
subgraph API["NestJS API"]
direction TB
sync["POST /admin/sync-meta-builds"] --> svc[MetaBuildSyncService]
active["GET /admin/sync-meta-builds/active"] --> svc
query["GET /meta-builds"] --> db[(MetaBuild table)]
enc["GET /encounters/:id/meta-builds"] --> db
inst["GET /instances/:id/meta-builds"] --> db
match["GET /characters/:id/meta-build-match"] --> matchSvc[MetaBuildMatchService]
groupMatch["GET /organizations/:orgId/group-comps/:id/meta-build-matches"] --> matchSvc
matchSvc --> db
admin["POST /admin/meta-builds"] --> db
guild["POST /organizations/:id/meta-builds"] --> db
end
svc -->|WebSocket| ws["/meta-build-sync namespace<br/>(sync-progress, sync-complete)"]
Data Model
MetaBuild
Each row represents a single popular talent build for a given spec and content type.
| Field | Description |
|---|---|
id | UUID |
specId | Blizzard specialization ID |
specName | Human-readable spec name |
className | WoW class name |
name | Build label (e.g. "Top Patchwerk") |
contentType | raid or mythic_plus |
encounterId | Blizzard encounter ID (raid builds) |
instanceId | Blizzard instance ID (dungeon builds) |
talentLoadoutCode | Blizzard-encoded talent string or fingerprint fallback |
talentNodeIds | Sorted array of selected talent node IDs |
source | warcraftlogs, admin, or guild |
sourceUrl | WCL link to source data |
sourceCharacter | name-realm of representative character |
popularity | Float — relative popularity score |
sampleSize | Number of parses in WCL sample |
organizationId | Null for global builds, set for guild-scoped |
patchVersion | WoW patch version string |
isActive | Soft-delete flag |
MetaBuildSyncSession
Tracks sync progress, following the standard sync session pattern.
| Field | Description |
|---|---|
status | running, completed, failed |
totalSpecs | Total specializations to process |
processedSpecs | Specs completed so far |
totalQueries | Total WCL queries to run |
processedItems | Queries completed so far |
buildsUpserted | Total builds upserted during sync |
triggeredBy | admin or scheduler |
Talent Fingerprinting
WCL returns talent builds as arrays of node IDs — not Blizzard loadout codes. The system resolves these through two paths:
- Loadout encoding (preferred): Uses GDL talent tree data to encode node IDs into a valid Blizzard
talentLoadoutCodeviaencodeTalentLoadout(). - Fingerprint fallback: When encoding fails (incomplete tree data, hero spec mismatch), generates a SHA-256 fingerprint of the sorted node IDs (first 16 hex characters).
Fingerprinted builds cannot be simulated directly — they must be resolved to a real loadout code first.
flowchart LR
A["buildTalentFingerprint([101, 203, 305])"] --> B["sort → [101, 203, 305]"]
B --> C["join → '101-203-305'"]
C --> D["SHA-256 → first 16 hex chars"]
D --> E["'a1b2c3d4e5f6a7b8'"]
isTalentFingerprint(code) checks if a string matches /^[0-9a-f]{16}$/ — used to flag builds that can be matched but not exported as a SimC-compatible loadout string.
Build Aggregation
aggregateBuilds() groups raw WCL results by fingerprint:
- Groups builds with identical talent selections
- Sums player counts and averages DPS
- Keeps the highest-DPS character as representative
- Sorts groups by player count (popularity) descending
WCL Sync Flow
Triggered by POST /admin/sync-meta-builds or cron (Mondays 06:00).
- Create
MetaBuildSyncSessionwith statusrunning - Load all specs from GDL
listTalentTrees() - Load current raid instances and M+ dungeons from GDL
- Map M+ dungeons to WCL encounter IDs via
getMythicPlusDungeonEncounters() - For each spec × encounter/dungeon:
- Fetch top builds from WCL (
getTopBuildsForEncounter/getTopBuildsForDungeon) aggregateBuilds()to group by fingerprintresolveLoadoutCodes()to convert node IDs → Blizzard loadout codes- Upsert
MetaBuildrows
- Fetch top builds from WCL (
- Emit progress via WebSocket (
/meta-build-syncnamespace) - Mark session
completed
Build Matching
Build matching is a pure SQL operation: the character's active loadout is fingerprinted (or its Blizzard talentLoadoutCode taken directly) and compared against the MetaBuild catalog for that spec. No SimC, no jobs, no queues. The match is synchronous and runs on every page load.
MetaBuildMatchService (in apps/api/src/domains/meta-build/meta-build-match.service.ts) fetches the character's active spec via GDL, computes the candidate codes, and returns:
exactMatch: the matchedMetaBuildrow, ornullotherMetaBuilds: other meta builds for the spec, ordered by popularityactiveSpecId,activeLoadoutCode,activeFingerprint: the inputs used
The group-comp endpoint iterates the same logic over every member and returns a per-character match result.
Match Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /characters/:id/meta-build-match | Match a single character's active loadout |
| GET | /organizations/:orgId/group-comps/:id/meta-build-matches | Match every member of a group composition |
API Endpoints
Public
| Method | Path | Description |
|---|---|---|
| GET | /meta-builds | Filter by specId, contentType, encounterId, instanceId |
| GET | /encounters/:id/meta-builds | Builds for a specific boss |
| GET | /instances/:id/meta-builds | Builds for a dungeon |
Admin
| Method | Path | Description |
|---|---|---|
| POST | /admin/meta-builds | Create a build manually |
| DELETE | /admin/meta-builds/:id | Soft-delete a build |
| POST | /admin/sync-meta-builds | Trigger WCL sync |
| GET | /admin/sync-meta-builds/active | Check active sync session |
Guild-Scoped
| Method | Path | Description |
|---|---|---|
| POST | /organizations/:orgId/meta-builds | Guild officer adds build |
| DELETE | /organizations/:orgId/meta-builds/:id | Guild officer removes |
Frontend Integration
RTK Query
useGetMetaBuildsQuery— fetch meta-builds with filtersuseGetCharacterMetaBuildMatchQuery(characterId)— passive fingerprint match for a characteruseGetGroupCompMetaBuildMatchesQuery({ guildId, groupCompId })— passive matches for every member of a group
WebSocket Hooks
useMetaBuildSync(sessionId)— subscribe to sync progress on/meta-build-syncnamespace
Cron Schedule
| Job | Schedule | Description |
|---|---|---|
| Meta-build sync | 0 6 * * 1 | Mondays at 06:00 UTC |