A Mythic+ group finder built around the one thing the in-game tool hides: who the other person actually is.
You get into a +18. Someone dies on the first pull and doesn't tilt. Someone explains the boss without being asked. Someone waits fifteen minutes for a replacement instead of leaving.
The key times. Everyone says "gg". The group dissolves.
And then you never find those four people again.
That's the whole problem. Not that the in-game finder is slow — it's fine at "right now". It's that five people just proved they can play together, and the game throws that away the moment the dungeon ends.
The two smaller frustrations everyone knows:
- As an applicant you never learn anything. Declined, ignored and "group already full" all look exactly the same.
- As a leader you get twenty applications with three numbers each, and nothing at all about the thing that actually ruins keys: whether this person leaves after the second wipe.
This gap isn't unknown — it's just solved socially, and the social solutions all charge the same price.
| Where people go today | What it gives them | What it costs |
|---|---|---|
| Blizzard's premade finder | Unbeatable at "right now" | No identity, no history, the decline is invisible |
| Raider.IO | A performance score inside the finder — no website beats that | It measures skill. Leavers can have excellent scores |
| A guild | Real bonds, the same people every week | Membership: application, raid nights, loyalty. Far too much for one key on a Tuesday |
| In-game communities (up to 1,000 members) | Scheduled key nights without switching guild | No application flow, no history — reputation lives in one officer's head |
| Discord communities — the largest, Mythic Plus Friends, has ~50,000 members | The de-facto answer to "planned, not queued" | Read the rules, get roles assigned, introduce yourself, post into a channel with 400 messages |
| LFG bots (LF.Group and similar) | Structured posts with role slots | Whatever standing you build stays on that one server |
| Review-based LFG sites (WoWLFG and others) | Reviews and a reputation score after each run | Free text and a public leaderboard — the two mechanics section 3 argues destroy the signal |
Two things follow from this list.
The real competitor is Discord, not Blizzard. Blizzard owns "right now" and should keep it. Everyone who wants Tuesday 20:00 with the same five people has already left the game client and is sitting in a Discord.
Reputation there is real — it just isn't portable. People genuinely know who is reliable, but that knowledge lives in one server's memory, in the heads of a few officers, and it dies the moment you leave. vouch is the attempt to make that knowledge follow the account, verified against Blizzard's own data, without asking anyone to belong to anything.
That is also the honest framing of the cold start (section 8): the goal isn't to replace Mythic Plus Friends. It's to be the thing you can use without joining it.
1 · Sign in with Battle.net. No form, no password, no email. Signing in also proves the characters are yours, which is what makes every signal below worth anything.
2 · List a key, or apply to one. A dungeon, a level, a time, the roles you need, one line of text. Applicants see their status move: seen → accepted → declined. The decline is visible — that is the single thing the in-game finder hides and the thing that annoys people most.
3 · Get into the group. You're accepted, you get a six-character code, you
whisper it in game: /w Thal-Antonidas vouch K7QF3M. The leader's addon
recognises the code and invites you.
Only the leader installs anything. As an applicant you type one line in chat and that's it. And the code is bound to your character name — passing it to a friend does nothing.
4 · After the run, ten seconds of feedback. One commendation to give, and only for something that stood out. That's what builds the history that makes step 2 mean something next week.
Not a score. Raider.IO already shows performance scores inside the in-game finder, and no website can beat that for convenience. The gap isn't skill — it's behaviour.
So a profile shows five coarse standing tiers with a genuinely rare top, and next to it things that are either counted or costly to give:
| You see | Where it comes from |
|---|---|
| 61 keys confirmed with others | Verified against Blizzard's own data |
| Ran again with the same player · 11× | Platform data — the strongest signal there is |
| Newcomers taken along · 14 | Rewards exactly what people usually skip |
| Commendations — saved the run, kept everyone calm, taught me something | Peers. One per key. Never for "stayed to the end" — that's the job. |
| Vouches — three per season, permanent, never returned | Peers. Scarce enough that giving one costs something. |
And three things you deliberately never see: no percentage, no leaderboard, no free text. Percentages inflate until everyone sits at 98% and the number tells you nothing. Leaderboards turn a trust signal into something worth farming. Free text needs moderators.
Criticism is private: reports are never shown, never attributed, and only count when several people independently report the same thing.
Anyone can claim anything, so it matters where a number comes from.
- ✅ "This group finished this key together." Provable — Blizzard's realm leaderboards list the full roster of ranked runs.
⚠️ "They finished 94% of their keys." Not provable. Abandoned keys appear nowhere in the API. That's why vouch counts completions and never shows a rate.- ❌ "The addon pulls groups from the website." Never possible. WoW addons have no network access at all — no HTTP, no sockets. Everything crosses that line as text you paste or whisper.
That last one reads like a weakness. It's the opposite: a platform that names what it cannot do is a platform that understands the platform.
demo/ — a Next.js app with sample data, no backend, nothing connected to
Blizzard. npm install && npm run dev, or npm run build for a static export
in out/ that can be dropped on any static host.
Browse open keys — apply, watch the status move, get your whisper line. Pending feedback sits at the top with a 48-hour window, so there's a way back in.
The addon, in game — step through four whispers. The third one is the point of the whole screen: a valid code, whispered by the wrong person, rejected.
A profile — five discrete standing segments, counted statistics, vouches with the reason they were given.
| Concept | This document. Complete, reviewed, and the single source of truth. |
| Demo | demo/, playable end to end. Last synced with this document 2026-08-02. |
| Code | None. No backend, no addon, no client. |
Naming: vouch is a working title — short, a verb, describes the core rather
than the mechanism, survives concept changes. Alternatives considered: sigil,
runback, kstn, ledger, pugrep, timed, keyring, whispr,
portalstein.
Artwork in this README is generated (scripts/generate_readme_art.py,
scripts/generate_avatars.py, OpenRouter → gpt-image-2). The four cut-out icons
are rendered on a chroma-key green the prompt forbids inside the subject, then
keyed out locally — a luminance key would eat the gold.
Everything below is the design in full: the API constraints that shape the data model, the invite bridge, the reputation research and the attacks it has to survive, the schema, the architecture, the MVP ladder, the risks, and the decisions that are still open.
1 · Sign-in and the four constraints that shape everything
Battle.net OAuth 2.0, authorization code flow, scope wow.profile.
There is no registration form, no password, no email.
| Endpoint | Gives |
|---|---|
/oauth/userinfo |
account id (sub) + BattleTag |
/profile/user/wow |
all characters on the account (requires user token) |
.../mythic-keystone-profile/season/{id} |
rating and best runs per character |
The same sign-in proves character ownership. Without that proof every signal on the platform is worthless — this is the foundation, not a convenience feature.
- Access tokens last ~24 h. Blizzard issues no long-lived refresh token. Cache the character list server-side; keep the app session independent of the token.
- Regions are separate. EU and US are separate endpoints and separate account ids. A player with characters in both signs in twice.
- Characters get renamed and transferred. Identity hangs off the account, never the character name. A character is an attribute, not a user.
- Rate limits. Roughly ~100 req/s and tens of thousands per hour per client — verify before finalising the sync design. Profile refresh belongs in a queue, not in a page request.
Good news for background jobs: only /profile/user/wow needs the user token.
Character-level endpoints work with client credentials, so the worker can sync
without the user being present.
Blizzard's finder is strong at "right now" and weak at "Tuesday 20:00 with the same five people". Compete where it is weak. Plan instead of queue.
Do not compete on performance scores. Raider.IO already shows them inside the in-game finder, which is more convenient than any website can be. The differentiator is behaviour, not skill.
Leader: sign in → list a key (dungeon, level, time, roles, one line of text) → review applications with behavioural signals → accept → addon invites on whisper → give feedback after the run.
Applicant: sign in → browse open keys → apply in one click → see the status
(seen / accepted / declined) → paste one line in chat → get invited → give
feedback after the run.
Two deliberate rules:
- The decline is visible. This is the single thing Blizzard consistently hides and the thing that frustrates people most.
- The leader's character name appears only after acceptance, otherwise the site becomes a whisper spam source.
2 · The bridge back into the game
Hard limit: WoW addons have no network access. No HTTP, no sockets, no runtime file access. An addon can never fetch groups from the website or report anything back. This is permanent, not a current gap.
Everything that goes in must go in as text — via clipboard, via chat, or via a file written before the game loads.
| Option | How | Limits | Verdict |
|---|---|---|---|
| Macro | Site generates /invite Name-Realm |
255 chars per macro, 2–4 names, fully manual | MVP fallback |
| Whisper code | Group gets a short code; applicant whispers it; leader's addon recognises it and invites | Leader needs the addon, applicant does not | Recommended |
| Import string | WeakAuras-style compressed group list, imported into the addon | Snapshot only, no refresh | Later |
| Desktop client | Reads the combat log WoW writes natively, uploads it | Leader must install and run it; log is not signed, so forgeable | Accepted for verification (see below) |
The earlier rejection of a companion app was based on the SavedVariables pattern — only readable at load. The combat log is different: WoW writes it continuously and a client can poll it continuously. That distinction is what reopens verification.
- The invite originates from a user action — the applicant types. The addon reacts; it does not automate gameplay.
- The invite call is available to addons; it is not a protected function.
- Auto-invite on a chat keyword is long-established addon practice.
- The sender supplies name and realm automatically, so cross-realm invites work.
- The applicant installs nothing. Only leaders need the addon, which halves adoption friction.
A single group code can be passed on. The addon can't check a live applicant list, because it has no network.
Solution: the addon receives a group secret once, when the key is listed — 256 bits, rotated when the group closes, and never typed into chat. Each accepted applicant's code is a truncated HMAC of that secret and their character name, six characters of Crockford base32 (~30 bits, no ambiguous glyphs to mistype). The addon recomputes it locally in Lua and accepts the code only from that exact sender. No sync, no network, and a shared code does nothing. Pure-Lua SHA-256 is fast enough for a handful of checks per minute.
- Accept a group secret / applicant list via clipboard (a text box, no network)
- Listen to whispers, validate the code
- Invite only on a valid match
- Rate limit: three to five failed codes from one sender triggers a lockout
- Log declines, detect a full group from the party size, disable itself
- One off switch
A few hundred lines of Lua. The smallest part of the project, and the only one that must be open source.
3 · Reputation — the research it is based on
The design goal is not "a rating system". It is a signal that survives contact with players who optimise against it.
- Riot / Jeffrey Lin (League of Legends Honor). Built on positive-reinforcement research, including the Richmond RCMP "positive tickets" programme — youth recidivism fell from 60% to 8% at a tenth of the cost of the reactive approach. A single well-worded line on the loading screen reduced verbal abuse by ~5%. The cheapest lever is wording in the right place, not the reward system.
- Balliet, Mulder & Van Lange (2011) meta-analysis. Reward and punishment are roughly equally effective at producing cooperation. Positive-only isn't more effective — it is cheaper, less moderation-heavy, and doesn't damage the community.
- FFXIV player commendations. Exactly one per instance, positive only, and only for players you were matched with, not your premade. That last rule is the single best defence against friend-circle farming. Known weaknesses: it decays into "give it to the tank and leave", and short duties get farmed for throughput.
- Overwatch endorsements. Level decays over time, and decay is reduced proportionally for players who couldn't endorse you because they recently did — so regular groups aren't punished. Then Blizzard lowered the decay rate, everyone hit level 5, and the tier became meaningless. Tune decay hard from day one.
- Rating inflation (economics literature). Over 90% of studied eBay sellers have ≥98% positive feedback. Almost 95% of Airbnb hosts sit at 4.5–5 stars. oDesk averages rose a full star over seven years. Cause: giving negative feedback has costs — fear of retaliation, guilt. Public ratings produce strategic inflation and variance collapse. The most-discussed fix in the literature: make negative feedback private.
- Badges and intrinsic motivation. Badge steering effects depend on user type; some significant contributors are unaffected. The overjustification effect (Deci, Koestner & Ryan, meta-analysis of 128 studies) shows external rewards for intrinsically motivated activity reliably reduce intrinsic motivation. Global leaderboards discourage everyone outside the top few.
- No fine-grained score. Five coarse, threshold-based standing tiers with a genuinely rare top — never a percentage and never a progress bar. A public average inflates toward the ceiling and stops carrying information. The moment the tier becomes a weighted sum or a fine-grained bar, it is the score this rule rejects.
- Praise is scarce. One commendation per key. Three vouches per season, permanent, never returned.
- Praise must be exceptional. "Stayed to the end" is the job, not an achievement. Traits are: saved the run, hard carry, kept everyone calm, taught me something, put the group first, made it fun. Baseline behaviour is only interesting by its absence.
- Criticism is private. Reports are never shown, never attributed, and only count when several people independently report the same thing.
- Only matched players can commend each other, never someone you queued with.
- Nothing rewards volume. Badges reward what people skip: taking a newcomer, explaining a pull, waiting for a replacement.
- No leaderboard. It turns a trust signal into something worth farming.
- Standing decays exponentially, half-life roughly two to three weeks, above a baseline, with a soft reset at season boundaries. Repeat teammates reduce the decay rate rather than costing you anything. Tune the constant from telemetry, day one. Vouches do not decay — standing measures "how you play now", vouches record "who ever stood up for you", and they are weighted by the giver's standing at the time of giving (snapshot), so they can't be re-valued later.
- Ratings appear after a delay (~30 min) to defuse revenge ratings.
- One sentence at the point of decision. Above the apply button: "Most keys don't fail because someone's damage was low. They fail because someone left."
| Signal | Source | Inflatable? |
|---|---|---|
| Keys confirmed completed | API leaderboard + client, verified | No |
| Ran again with the same player | Platform data | No |
| Newcomers taken along | Platform data | No |
| Commendations received | Peers, one per key | Scarce by design |
| Vouches received | Peers, 3 per season | Very scarce |
| Reports | Peers, private | Never displayed |
Two remaining holes worth naming: tier-weighted vouches make vouches a transferable currency, so the weighting must saturate (the first Exalted vouch counts, the tenth doesn't) and mutual vouching must be blocked. And report collusion needs reports to come from different runs, weighted by reporter history.
| Attack | Countermeasure |
|---|---|
| Revenge rating after a bad run | Delay before visibility; negative feedback is private anyway |
| Friend circle boosting itself | Premade exclusion; diminishing returns per pair |
| Alt account for a clean slate | A Battle.net account costs a subscription |
| Reputation as a gate against newcomers | "Accepts players with no history" filter; badge for using it; no hard minimum |
Open question: three vouches per season is a guess. With 200 active players over a ten-week season, nearly every active player ends up holding some, and they stop meaning anything. The number should scale with community size, not be fixed.
4 · Verification — three sources, none complete alone
- Character best runs —
mythic-keystone-profile/season/{id}. Only the best run per dungeon and affix. A +12 by strong players is invisible. - Realm leaderboards —
/data/wow/connected-realm/{id}/mythic-leaderboard/{dungeonId}/period/{period}, a game-data endpoint, no user token. Full member sets for ranked runs. Capped at 500 runs per realm and dungeon per week; on high-population realms low keys get pushed off as the week goes on. A run ranks if it makes the board on any member's realm, so mixed-realm groups get five chances. Raider.IO crawls exactly this and publishes the same limitation in its own FAQ. - Leader desktop client — reads the combat log WoW writes natively and uploads it. The only source that sees every run including abandoned ones. Raider.IO's Live Tracking works this way, and one member running it covers the whole group, so "the applicant installs nothing" survives. The addon still has no network; the client, outside the game, does the upload.
Correction to an earlier draft: a "% of keys finished" figure is not obtainable from the API alone, because abandoned keys appear nowhere in it. Two consequences the demo must respect: the metric is an absolute count of confirmed completions, never a percentage; and a streak ("41 in a row") is equally unprovable without client coverage. Where the client covers a run, abandonment becomes observable — report it with an explicit coverage caveat, never as a clean rate.
Platform-side inference, available without any client: the listing gives you the intended roster. If no leaderboard record appears for that roster, the key wasn't completed. If a record appears with four of the five plus a stranger, you know who was replaced. That attribution comes from your own data, not from Blizzard's.
On false positives: matching an exact five-member set plus dungeon, level and completion timestamp is far stronger than intersecting partial rosters. And a mispairing between two runs of the same group is harmless — the claim being verified ("these people ran together") remains true either way.
5 · Data model
Six tables. The account is the identity; the character is an attribute.
account id (bnet sub) · battletag · region · created_at · suspended_until
character id (blizzard) · account_id → · name · realm · class · spec
· m_plus_rating · last_synced
listing id · leader_char_id → · dungeon · level · starts_at · roles_open
· group_secret · status
application id · listing_id → · character_id → · role · status · seen_at
run_receipt id · listing_id → · members[] (character ids, with source
premade|matched) · season_id · origin (leaderboard|best_run|client)
· verified · completed_at · created_at
feedback id · receipt_id → · from_account → · about_account →
· commendation (bool) · traits[] · vouch (bool) · weight
report id · receipt_id → · from_account → (private, never shown)
· about_account → · flags[] (fixed ids, not free text) · created_at
listing also: recurrence flag · unique (listing_id, character_id) on application
6 · Architecture and the hardest parts
Web app Addon
Next.js · Auth.js --------> Lua · no network access
| copy & paste |
v v SavedVariables
Postgres <--------------------- Leader client
accounts · keys · ratings combat log · optional
|
v
Worker ------------------> Blizzard client
verification · sync · decay rate limit · token cache
|
v
Blizzard API
- Postgres over D1 — the vouch economy needs transactions and the verification queries are more relational than they first appear.
- One worker, three job types: profile sync, run verification, weekly decay.
- One rate-limited API client. The only component that talks outward. Global token bucket plus caching with TTL by data age; otherwise limit logic spreads across the codebase.
- The addon lives outside the system. Separate repository, open source, no shared code, no connection — it can't have one and mustn't have one.
- The desktop client is optional and leader-side. It reads the combat log and uploads it, relays the addon's heartbeat and invite log from SavedVariables, and triggers the feedback prompt when a run ends. Three-stage adoption ladder: web only → addon → addon + client with a visible "verified" badge.
- Timezones are day one. Store UTC instants, render viewer-local. "Tue 20:00" is the entire product wedge and EU spans UTC to UTC+3 with DST.
- Run verification. The API exposes only a character's best runs per season, and abandoned keys never appear. Matching needs dungeon, keystone level, completion timestamp with a tolerance window, and the member-set intersection. Weeks of work with many edge cases.
- The HMAC handshake in the addon. Lua's
string.loweris ASCII-only, so any scheme that lowercases a name in Lua silently mismatches on umlauts. Fix: decouple the HMAC from the chat event. The server sends the exact expected sender string; the addon matches the incoming sender fuzzily and hashes the stored string, so both sides hash identical bytes. Log mismatches to SavedVariables so silent failures become diagnosable. - Rate limits as an architectural driver. Five players per verification, several season queries each. Queue, not live fetch.
- Token lifecycle — covered in section 1.
7 · MVP scope
Each step builds on the previous, and after each one you can stop and still have something usable.
- Sign in and see characters. Without identity there is nothing.
- List and find keys. Already usable as a scheduler, even without the bridge.
- Apply with a visible status. The point where it stops resembling the in-game finder.
- Invite bridge. Macro for everyone, addon with whisper code for leaders.
- Feedback with run verification. Only now does the actual value appear — and only now is growth worth pursuing.
Verification may be missing in stage 1. The MVP works with unverified feedback; it is just attackable. Acceptable for the first hundred users, untenable for the first thousand.
Deliberately not in the MVP: raids, PvP, guilds, chat, Discord bot, notifications, mobile app, regular groups, calendar, friend lists, multiple languages, regions beyond EU.
8 · Risks
| Risk | Why it hurts | Handling |
|---|---|---|
| Cold start | An empty finder is worthless and everyone is already on Blizzard's. By far the biggest danger — not the technology. | Don't fight the instant use case. Start with scheduled runs and regular groups. Limit to EU and a few realm clusters rather than being thin worldwide. |
| API terms of use | Attribution required, resale prohibited, access revocable at any time. | Read the terms before the first line of code. No paywall on API data. Have a fallback. |
| Addon policy | Addons must be free and source-visible. An addon gating a paid feature violates it. | Addon strictly free and open. Any money goes to the website as voluntary support, never the addon. |
| GDPR | Ratings about identifiable players are personal data. Deletion rights vs. reputation integrity. | On deletion, remove the profile and anonymise feedback the user gave. EU hosting, imprint, privacy policy, processor agreements. |
| Competition | Raider.IO already shows scores inside the in-game finder. Discord communities already own the scheduled use case, and review-based sites (WoWLFG and similar) already occupy the reputation idea — with leaderboards and free text. | Don't compete on scores. Compete on behaviour: abandonment, reliability, meeting again. Against Discord, compete on not requiring membership; against review sites, on the mechanics section 3 refuses. |
| Moderation | The moment people rate people, abuse appears. | No free text. Private reports. Appeal path. Budget time for it from day one. |
| Verification coverage | Leaderboards cap at 500 runs per realm and dungeon per week, so low keys on busy realms go unrecorded. Raider.IO has the same gap. | State coverage honestly, never as a rate. Client-covered runs get a "verified" marker; the rest count as unverified. |
| Feedback drop-off | If nobody returns to give feedback, nobody has a history and the platform is just another finder. | State the cost up front ("takes about ten seconds"). Put pending feedback at the top of the group list on next visit. |
9 · Open decisions
- Instant or scheduled? Determines almost everything downstream. Scheduled means a smaller market but a real gap. Recommendation: scheduled, with instant added later.
- Is reputation the foundation or a feature? As a foundation it must be abuse-resistant from day one. As a feature it can come later but never reaches data density. Both are defensible; the middle isn't.
- EU only or all regions? Multiple regions mean triple sync, separate user pools, separate cold starts.
- Vouch economy. Three per season is a guess — see section 3.
- Is the leader desktop client an acceptable barrier? Raider.IO's userbase says yes, and it is the price of answering "who was actually there". The alternative is API cross-validation only, with abandonment left as a pure peer signal.
- What does a private report actually do? If nothing visible, there is no deterrent. If something visible, "never attributed" gets hard to hold.
- How is "premade" determined? The FFXIV exclusion is the best anti-farming defence available and the model can't currently distinguish it.
- What happens when the addon isn't running at the scheduled time? Presence signal via the client, plus a manual fallback.
- Discord as a distribution channel, not only as a competitor. The existing communities are where the target users already are. A listing that can be posted into an established server may be the cheapest cold-start lever there is — which puts the MVP exclusion of a Discord bot up for re-evaluation.
- Does the architecture section belong on the landing page? Ballast for players, proof of competence for technical readers. If both matter, hide it behind a disclosure toggle.
10 · The demo, in detail
demo/ — a Next.js 15 app exported statically. Sample data only, no backend, no
storage, nothing connected to Blizzard. The whole prototype is three files:
app/globals.css, app/page.tsx (the static shell) and public/demo.js, a
vanilla-JS app that renders every view into #views. See demo/README.md.
Opens with an explanation screen: the problem, what people already do about it (the six existing solutions and what each one costs), the three-step flow, a colour-coded scope (green: works today · amber: later · red: never possible), the reputation principles, and the architecture section. Then "Start the demo".
The existing-solutions block carries the same two conclusions as the section above: Discord is the real competitor, and the reputation there is real but not portable. It sits directly after the problem, because "why doesn't a Discord already solve this" is the first objection any reader has.
Four tabs, all playable:
- Groups — browse open keys, apply, watch the status move from seen to accepted, get the whisper line. A pending-feedback entry sits at the top of the list with a 48-hour window, so the feedback loop has a way back in after navigating away.
- My group — list a key, review applications, invite. The leader panel separates the two secrets the design depends on: a 256-bit addon secret marked never paste in chat, and a six-character code issued per accepted applicant, derived from it.
- Addon — a mock-up of the leader's side in game: chat frame, addon window, party frames filling up. Step through four whispers. The third is the point of the whole screen: a valid code whispered by the wrong person, rejected, failure counted. That makes the sender-bound code obvious in a way no paragraph does.
- Profile — the coarse standing tier as five discrete segments (no percentage, no progress bar), counted statistics, received vouches with reasons, commendation badges.
Everything shown is countable or peer-given. No percentages, no streaks, no leaderboard — the three things the concept argues cannot be honestly produced.
The red "never possible" card is the most important one on the page. It states that an addon can never pull groups from the website — which stays true even with the optional desktop client, because that client is a separate program outside the game. Read as a weakness at first glance, it is the strongest argument in the document: it shows the platform is understood rather than a promise being made that can't be kept.
None as of the last sync. When the demo drifts, record it here rather than silently — the two artefacts diverging is what the external review caught first, and it cost more time than any technical finding.
Spec sync: this document is the single source of truth. demo/ is versioned
against it; last sync 2026-08-02, covering the external review of the same date.
The reorganisation into a player-facing part and a developer part changed no
statement in the design.


