guildpro.io · design system · draft v0.1

Ledger.

Guild officers already run their raids out of a spreadsheet. Guild Pro's job is to be a better spreadsheet — one that knows what a Windfury totem is. Everything here follows from that: hairline cells, zero radius, monospace on every number, and a single gold accent that only appears where you can act.

Ground
#0a0a0b
Accent
#f0bd35
Radius
0
Row height
34 / 26px
Data face
Consolas
00

Identity

One mark: a gold blade on a violet-steel grip, drawn on a strict 16×16 grid in five tones. It is pixel art, so it never blurs, never gets a gradient, and never gets a drop shadow beyond its own glow.

Primary lockup sword + wordmark
Clearspace — one blade-width on all sides. Minimum wordmark 13px. Gap sword-to-word is 0.35× the wordmark cap height.
Mark alone 16 → 56px
Legible at 16px. Always render at a multiple of 16 so pixels stay square.
On light bronze variant
Gold drops to bronze #8a6a15 on light grounds. Never place the gold-on-dark version on white.

Animation

A single bright pixel-pair falls down the blade in hard steps() every 3.6s, with two glints near the tip. No easing — easing is what makes fake pixel art look fake. Disabled entirely under prefers-reduced-motion.

01

Colour

Two systems that never mix. Chrome is ours and can change. Data colour belongs to the game and to Warcraft Logs — our users read it fluently already, so overriding it to fit a palette makes the product harder to use, not more distinctive.

Chrome — ours

Ground
#0a0a0b
Ground 2
#0e0e10
Surface
#111113
Surface 2
#161619
Hairline
#202024
Ink
#d4d4d9
Dim
#83838d
Faint
#5c5c66
Accent
#f0bd35
Good
#379460
Warn
#b0842a
Bad
#b54843
Accent rule — gold marks the one thing you can act on in a view: primary button, active tab, selected row. If two golds are competing on a screen, one of them is wrong.

Warcraft Logs percentiles — theirs

Used on every parse number, everywhere, without exception. A 91 is purple here because it is purple there.

0–24
#75757e
25–49
#2aa83a
50–74
#3a76c4
75–94
#9048c4
95–98
#d2731d
99
#c65490
100
#c9b071

Class & item quality — Blizzard's

Class · names only
Warrior
Paladin
Hunter
Rogue
Priest
Mage
Warlock
Druid
Class colour appears on character names and spec labels only. Never on backgrounds, never on chrome. Desaturated ~10% from Blizzard's values so they sit on near-black without buzzing.
Item quality · text + icon border
🌿Uncommon 💧Rare 🔮Epic 🔥Legendary
Quality colours the item name and the icon tile border. Legendary is the only quality that earns a glow — nothing else in the product glows.
02

Typography

Two faces. A UI sans for anything you read as language, and a monospace for anything you read as a value. The split is not stylistic — the mono is what makes columns of numbers scannable.

Display / H1Reborn Council — Normal (20)
Section / H2Signup versus attendance
Card title / H3Raid groups · Thursday 20:00
BodyFive raiders signed up and never zoned in.
SecondaryRolling median of the last eight logged raids.
Label · monoRaid parse grade
Data · mono214,700.8   99.22%   2:46   35.70m
Metric87%
Sans Segoe UI Variable → Segoe UI → system-ui.   Mono Consolas → Cascadia Mono → ui-monospace.
Rule every numeral in a column gets font-variant-numeric: tabular-nums, no exceptions — ragged digits are the fastest way to make a data table feel amateur.
Labels 9–10px mono, .15em tracking, uppercase, faint. They are furniture; they never compete with the value.
03

Grid & density

Panels interlock. There are no floating cards and no gaps between boxes — regions share a single hairline, the way cells in a sheet do. This is the single decision that makes Guild Pro read as a tool rather than a dashboard.

Interlocked regions shared borders, zero gap
Attendance
87%
▲ 4 pts
Raids
24
this tier
Avg clear
3:07
▲ 22 min
No-shows
5
last raid
Row heights 34px comfortable, 26px compact, 18px in a heatmap. Cell padding 6–10px vertical, 10–12px horizontal.
Hairline 1px #202024 between regions, #191919 between rows inside a region. Two weights, no more.
Radius 0 everywhere. Shadow only on modal overlays.
04

Primitives

Six elements build almost every screen in the product.

Buttons
One primary per view. Destructive is outlined, never filled — a filled red button gets clicked by accident.
Segmented control
For 2–5 mutually exclusive options. Active state is accent-tinted, not filled.
Status pills
CoreTrial 4/6Late 3 no-showsExcused TankHealerMeleeRanged
Outlined only. Role pills use the desaturated role set so they never compete with class colour on the same row.
Icon tile
🛡️⚔️ 💧🔮🔥
Neutral fill, always. 20px in rows, 22px default, 34px in loot lists. Only the border carries meaning.
Meters & parses
98% 74% 52% 100 99 96 88 63 41
Meters take semantic colour by threshold. Parses take WCL band colour by value. Never swap the two.
Alerts
Shadow Weaving missingNobody slotted provides it. Every warlock loses 15%.
!Fire Vulnerability has one providerLose them mid-fight and it is gone for the pull.
Comp is cleanRoles met, every required buff covered.
Always state the consequence, not just the condition. "Missing" is a fact; "every warlock loses 15%" is why anyone cares.
05

Metric strip

The signature component. Every major screen opens with one: a grade block on the left, then a run of interlocked cells. It is the first thing an officer reads and the thing that changes when they act.

B Raid parse grade 80 medianmean 75 40 raiders · last 8 raids
Tanks
5
min 3
Healers
10
min 9
Melee
10
incl. off-spec
Ranged
15
casters + hunters
Grade cell is 1.6fr minimum 300px; the rest are equal. Grade letter takes its WCL band colour. Distribution bar is always the raid's actual spread, never a decorative gradient.
06

Tables

Guild Pro is mostly tables, so they carry more design weight than anything else. Sticky mono headers, hairline rows, right-aligned tabular numbers, and a share bar wherever a value is part of a whole.

Damage table log view
ParseRaiderShareDamageilvlActiveDPS
193 ⚔️GeardahFury 2.50m9599.22%15,026.4
299 🔥IggýFire 2.48m9399.55%14,904.2
397 ⚖️BoomtowneRetribution 2.29m9098.61%13,776.4
1382 ⚔️RâsszFury 1.86m9591.50%11,173.9
98Raid total 35.70m166.3s214,700.8
Share bars take the raider's class colour at 60% opacity and scale to the top value, not to 100%. Outlier rows get a 5% bad-tint and the offending cell coloured — here Râssz's 91.5% uptime. Never colour the whole row red.
07

Charts

Charts follow the same rules as tables: hairline grid, mono axes, one accent. No legends where a direct label will do, no 3D, no gradients except a 10% area fill under a line.

Raid DPS over the pull line + area
Kill and wipe markers sit on the axis. Grid lines are horizontal only — vertical rules fight the data.
Attendance · last 12 raids
12 raids agoserver maint.last night
Accent for normal, warn under 70%, bad under 50%. Annotate the anomaly in the footer — a chart that doesn't explain its own dip is a support ticket.
Parse distribution stacked
100 ×199 ×2 95+ ×675+ ×17 50+ ×925+ ×4 <25 ×1
The one place WCL colours appear as fills rather than text. Segments are counts, never percentages.
Attendance heatmap raiders × raids
PresentLate Benched · creditedNo-showExcused
18px rows, 2px gaps. Five discrete states — never a continuous gradient, because "slightly more present" is not a thing. Rows sort by attendance so the problem sits at the bottom.
Sparkline inline, in a row
Sylvanne99 Shivspark41
3px bars, 2px gap, 20px tall. Trend only — no axis, no tooltip. If it needs a tooltip it needs to be a real chart.
Loot distribution items per raider, this tier
Sorted descending, with the raid median marked. Fairness questions are the reason this chart exists — make the outliers unmissable at both ends.
08

Timelines

Two kinds: a raid night laid out horizontally, and an event history laid out vertically.

Raid night Thursday 20:00 → 23:07
20:0020:4521:3022:1523:00
Green is a kill, red is a wipe, grey is trash or a break. Bar length is real elapsed time — a 40-minute Ragnaros progression block should look like forty minutes.
Raider history vertical event rail
Tonight Present · 10 / 10 bosses187 minutes. Confirmed by addon, logs and Discord voice.
2 Jul Received Perdition's Blade180 DKP · loot council · BIS #1
27 Jun No-showSigned Yes, never zoned in. Not excused.
20 Jun Promoted to RaiderTrial completed 6/6 · 94% attendance
8 May Joined Ashen CovenantApplied via Guild Pro recruitment
One rail, diamond nodes, colour only where the event has a valence. Loot, promotions and absences share the rail — a raider's history is one story, not four tabs.
09

Roster

The home screen. Everything a GM needs to answer "who can I count on Thursday" in one pass.

Guild roster 38 raiders · 5 shown
RaiderRoleAttendTrendParseilvlItemsLast raidStatus
SylvanneHoly · Human Healer 98% 99946 Last nightCore
🛡️AlthilosProtection · Human Tank 100% 81948 Last nightRaid lead
❄️FrosthollowFrost · Gnome Ranged 95% 100965 Last nightCore
🌿MoonbraeRestoration · Night Elf Healer 74% 80892 Last nightTrial 4/6
🗡️ShivsparkAssassination · Gnome Melee 52% 41832 3 weeks ago3 no-shows
Attendance is the anchor column, not parse — reliability is what a GM is actually deciding on. Parse always sits beside item level so a low number from thin gear can't be mistaken for a low number from poor play.
10

Loot

Three surfaces: what dropped and who got it, what everyone is owed, and what everyone wants. The ledger is append-only — every points dispute in WoW history is "the officer edited my balance".

Loot ledger Molten Core · this tier
ItemBossAwarded toMethodCostWish rankDate
🪢Bindings of the WindseekerLeft half GarrStormvaleCouncil 130 Jul
🗡️Perdition's BladeMain hand RagnarosNixxaDKP 180130 Jul
👑Crown of DestructionHead RagnarosYewbowDKP 120330 Jul
💍Cauterizing BandFinger GolemaggSylvanneOff-spec 030 Jul
🧤Gloves of ProphecyHands · tier 1 SulfuronDisenchantedRot 23 Jul
Every row answers "why did they get it": method, cost, and where it sat on their wishlist. Rotted items stay in the ledger — a tier's rot rate is a real signal about wishlist hygiene.
Points ledger append-only
DateReasonΔBalance
30 JulPerdition's Blade−180142
30 JulRaid attendance · MC+50322
30 JulOn time bonus+10272
28 JulWeekly decay 10%−29262
27 JulRaid attendance · MC+50291
Never store a mutable balance — balance is the running sum and is shown, not saved. Raiders can read their own full history.
Wishlist Sylvanne · Holy
#ItemSourceGainState
1🔮Eye of DivinityMajordomo+11.4%BiS
2👘Robe of Everlasting NightRagnaros+6.2%BiS
3🧤Gloves of ProphecySulfuron+2.8%Upgrade
4📿Choker of EnlightenmentGolemaggReceived
Received items stay visible at 50% opacity rather than disappearing — a loot council needs to see what someone already has.
11

Player profile

The public face of the product and the growth engine. Everything on it is verified — characters by Battle.net OAuth, attendance by the raid, parses by Warcraft Logs. Nothing here is self-reported except availability.

Profile public view

Sylvanne

Holy Priest · Human · Whitemane–Alliance · Ashen Covenant
✓ Battle.net verified Core raider 3 alts linked Healer
Verified record
Attendance
98%
142 raids
Median parse
99
HPS · tier
Tenure
14
months
No-shows
1
excused
Attendance · last 20 raids
Parse by encounter · Molten Core
Ragnaros998 kills
Majordomo9511 kills
Golemagg8712 kills
Baron Geddon7912 kills
Guild history
May 2025Ashen Covenant · Core raiderWhitemane–Alliance · 98% attendance over 142 raids
Nov 2024Emberwatch · RaiderLeft on good terms — guild disbanded. Reference from GM available.
Consent — a player controls whether their record is public, guild-only, or hidden. A GM can never publish someone else's numbers.
Disputes — every absence can be contested; contested entries show as contested rather than silently disappearing.
12

Discord surface

Discord is a client, never the database. Posts are generated views of state that lives on the site, so a post can always be regenerated and can never drift.

AUse Discord's palette, not oursInside an embed we are a guest. Background #2b2d31, text #dbdee1, blurple #5865f2 on the primary button. Our gold appears only as the embed's accent rail.
BStructure in components, richness in an imageButtons, select menus and modals are native and must stay native. Class colours, kill-time charts and parse bands are rendered server-side as a PNG and attached — embeds cannot colour arbitrary text.
CGroups map to inline fieldsDiscord lays inline embed fields three across, which is exactly a raid group grid. Don't fight it with ASCII tables.
DEvery post has one jobA roster lock asks for a confirmation. A recap asks for nothing. Never merge them.
EDeep-link, don't dumpButtons open the site already scoped to that raid and already authenticated via Discord OAuth. The embed stays skimmable.
13

Discord widgets

Four posts carry the entire product inside Discord. The signup is the one that has to be better than what guilds already use, because it's the one they'd have to switch away from — and the only reason to switch is that ours knows things a signup bot can't.

What the incumbent gets right

Raid-Helper's signup format is genuinely good and we should not reinvent it out of pride. The structure below is worth keeping almost verbatim.

Keep
  • Queue numbers. The order people signed up in, shown before every name. Settles bench disputes without an argument.
  • Class columns, three across. Maps exactly onto Discord's inline field layout.
  • Role counts in one line above the columns.
  • Bench, Tentative and Absence as separate short lists, not mixed into the roster.
  • A closed state on the control once the event locks.
Add — the reasons to switch
  • Who hasn't answered. A signup bot only knows who clicked. We know the roster, so we can show the twelve people who said nothing.
  • Reliability per raider. A yes from a 52% attender is not a yes. Coloured dot, from real attendance history.
  • Live comp validation. Missing healers, missing debuffs, called out while people are still signing up rather than at 20:05.
  • Lockout awareness. The addon knows who is already saved to this ID.
  • Spec, not just class — and the role derived from it automatically.

1 · Signup sheet

Signup #raid-signups · open
#raid-signups
Guild ProAPPToday at 10:26 PM

TK start for Tuesday. Sign up with your spec — the sheet fills itself in. 🗡️

SSC / TK Lockout II

Led by Vanp · Tuesday 21 July · 8:30 PM · in 10 days
Signed24 Slots25 Bench2 No reply9 Roster reliability91%
!Still need 2 healersFour signed, six wanted for SSC. Jejensn and Bigarmflex can both go Holy — ask them first.
Roles
Tanks 2/3 Healers 4/6 Melee 8 Ranged 10
Signed · 24
Warrior (4)
  • 12VanpProt
  • 2DapFury
  • 7GeardahFury🔒
  • 10bhettArms
Paladin (4)
  • 20CherryflavorProt
  • 3NotJoopzHoly
  • 24JejensnRet
  • 21BigarmflexRet
Shaman (5)
  • 13FadeResto
  • 14LunyoneEnh
  • 19BazEle
  • 18MoraEle
  • 22SankaEnh
Priest (3)
  • 11laserHoly
  • 8BatjuiceShadow
  • 26VerrousShadow
Druid (2)
  • 4SkatmanResto
  • 25taxsinglmomsFeral
Hunter (2)
  • 1SazabeBM
  • 16MeyMM
Mage (2)
  • 15IggyFire🔒
  • 17BeansFrost
Warlock (2)
  • 9trescommasDestro
  • 28FunwAffli
Other
  • 🪑 Bench (2)
  • 5Naray
  • 6Tamaal
Tentative · absence · saved
🤔 Tentative (1)23Bara “work call, 50/50” 🚫 Absence (1)27Moons “holiday, back the 28th” 🔒 Saved to this ID (2)Geardah, Iggy cleared Tuesday with a pug
No response · 9
AlthilosPeanutYifster BoomtowneMarmmNarayy UmBrisnerRâssz
Guild Pro · reliability dot = attendance over the last 12 raids · 🔒 already saved to this lockout
Sign up — choose your spec
Reliability dot — green ≥85%, amber 60–84%, red <60%, from real attendance not signups. Never a number in the list; the aggregate goes in the header instead.
Remind the 9 is the highest-value button on the widget. It DMs everyone on the roster who hasn't answered, and no signup bot can offer it because none of them know the roster.
Class columns map to Discord inline fields, three across, exactly as the incumbent does it. Don't fight the platform's layout.

2 · Locked roster

Roster posted when the GM locks the comp
#raid-roster
Guild ProAPPToday at 6:02 PM

Roster is locked. React ✅ to confirm — anyone unconfirmed by 19:30 gets replaced from the bench. 🔒

Molten Core — Thursday 20:00

Ashen Covenant · Whitemane–Alliance · led by Althilos
Tanks5 Healers10 Melee10 Ranged15 GradeB · 80
Groups · 40 slotted
Group 1 · Tanks
  • Aldric
  • Bulmar
  • Thoradin
  • Bigbadben
  • Althilos★RL
Group 2 · Melee A
  • Kaelric
  • Eadric
  • Nixxa
  • Bradlands
  • Atenius
Group 3 · Melee B
  • Brynja
  • Halvard
  • Duskrend
  • Shivspark
  • Boomtowne
Group 4 · Hunters
  • Yewbow
  • Cragfoot
  • Kestrin
  • Bryndal
  • Dawnhold
Group 5 · Mages
  • Frosthollow
  • Willowyn
  • Emberly
  • Zephrit
  • Marrowlight
Group 6 · Locks
  • Vaeltha
  • Boofuss
  • Mordray
  • Grelth
  • Naliss
+ Group 7 · Casters  ·  Group 8 · Healers  ·  see all on the web
Before we pull
!G6, G8 have no paladinSix paladins, eight groups. Blessings and aura will not reach these two.
Guild Pro · locked by Althilos · consumes and repairs before 19:55
Six groups shown, two collapsed behind a link. An embed that scrolls past a phone screen doesn't get read — put the overflow on the web.

3 · Raid recap

Recap posted automatically after the sync
#raid-recaps
Guild ProAPPToday at 11:14 PM

Full clear, guild best. Nice work everyone. 🔥

Molten Core — Full Clear

Thu 30 Jul · 20:00–23:07 · 3h 07m · 22 minutes faster than last week
Raid parse96 Bosses10/10 Wipes2 Deaths14 Attendance25/30
Top parses
1Frosthollow FrostGolemagg100
2Vaeltha DestructionRagnaros99
3Sylvanne HolyMajordomo99
Attendance — 30 signed, 27 raided
25 present2 late 3 benched & credited5 no-show
Signed Yes, never zoned in — ShivsparkCragfootMordrayBulmarMoonbrae · officers can excuse any of these in one click.
Hall of shame
💀 Most deaths — Grimtusk ×7, four of them to Living Bomb 🔥 Fire enjoyer — Borkk, 412k avoidable damage taken ⚡ First blood — Dunkhoof, 11 seconds into Ragnaros
Guild Pro · attendance reconciled from addon, logs and voice · loot ledger updated
The no-show line is stated as a record, never an accusation — "logged, not judged", with the excuse action right there. This is the post that will decide whether guilds keep the bot installed.

4 · Loot recap

Loot separate post, separate channel
#loot-log
Guild ProAPPToday at 11:15 PM

14 items awarded. Bindings dropped — the quest is on. 🪢

Loot — Molten Core, 30 July

14 awarded · 1 disenchanted · loot council + DKP
Epics11 Legendary1 DKP spent780 Rot rate7%
Awarded
🪢 Bindings of the WindseekerStormvale · 2 of 2 — the quest is on council
🗡️ Perdition's BladeNixxa · wishlist #1 180 DKP
👑 Crown of DestructionYewbow · first item this tier 120 DKP
💍 Cauterizing BandSylvanne · off-spec free
🧤 Gloves of Prophecy→ disenchanted · nobody wishlisted it rot
+ 9 more · full ledger
Fairness check
Spread is healthyMedian 5 items per raider this tier, range 1–8. Bryndal is the only raider still on one — worth a look at his wishlist.
Guild Pro · captured by the addon at award time · every raider can see their own DKP history
Rotted items are posted, not hidden — a public rot rate is the fastest way to get people to keep their wishlists current. The fairness check is the thing no other loot tool volunteers.
14

Voice

Guild Pro talks like a competent officer: specific, unbothered, never preachy. It records what happened; it does not have opinions about people.

Do
  • State the consequence. "Shadow Weaving missing — every warlock loses 15%."
  • Name the number. "Signed Yes, never zoned in. Third time this tier."
  • Offer the next action. "Move a paladin into Group 6."
  • Stay neutral about people. "52% attendance" — not "unreliable".
  • Explain a score. Every derived number links to the evidence behind it.
Don't
  • Don't editorialise. No "Yikes", no "Oof", no emoji as commentary in the app.
  • Don't predict. We dropped projected DPS for exactly this reason — a model that's wrong once is never trusted again.
  • Don't hide the formula. If attendance % is weighted, say how, on the screen.
  • Don't apologise. An error says what broke and what to do, in one line.
  • Don't use system words. "Raid night", not "event instance".
15

Motion

Almost none. Motion in a data tool is either feedback or noise, and most of it is noise.

1Feedback only, 100–150msHover tints, row highlights, drag states. Linear or ease-out; nothing bounces.
2Value transitions get 200msA meter bar animating to its new width after a drag. The number itself changes instantly — animated counters make people wait to read a value.
3The logo is the only decorative motionHard steps(), 3.6s cycle, and it is the sole exception.
4Honour prefers-reduced-motionEverything decorative stops. Feedback states become instant rather than disappearing.
16

House rules

If a decision isn't covered above, these settle it.

1The game owns the data languageClass colour, item quality, parse bands. We never restyle them to fit a palette.
2One gold per viewThe accent marks the one thing you can act on. Everything else is ink, dim, or faint.
3Facts over modelsShow what was measured. If something is derived, show the inputs beside it.
4Parse never appears without item levelA tank's percentile and a mage's aren't comparable, and thin gear isn't bad play.
5Ledgers are append-onlyPoints, loot, attendance evidence. Corrections are new rows, never edits.
6Attendance attaches to the personBringing an alt still counts. This is the thing every competitor gets wrong.
7Panels interlockShared hairlines, zero gap, zero radius. No floating cards anywhere in the product.
8Officers see more, never something differentPrivate notes are additive. A raider's own numbers always match what leadership sees.