# Recipe: guild dashboard

Team-facing page showing guild profile data imported from Blizzard.

## What ships today

- A `wow_guild` entity per imported guild — name, realm, faction, member count, achievement points, and the crest (colors + emblem/border media).
- The `wow:guild-lookup` drush command and the corresponding `GuildSync::lookup()` service method.
- Plugin extension points for roster, guild achievements, and guild activity (`GuildDataProvider` manager) — contract and tests in place, **no in-tree provider implementations yet**.

## What requires custom work

If you need a full team dashboard with roster, shared achievement progress, or activity feed, you have to build it yourself:

- **Roster hydration** — `GuildSync::lookup()` does *not* create `wow_character` entities for each roster member. You either import characters one by one with `wow:character-lookup`, or write a `GuildDataProvider` plugin that walks the roster endpoint and calls `CharacterSync::lookup()` per member.
- **Guild-scoped achievement progress** — the `wow_achievement_progress` junction supports a `guild` reference (projected by `wow_guild`), but nothing in the tree currently populates it. A guild-achievement `GuildDataProvider` plugin would.
- **Guild activity feed** — same story. The endpoint is wrapped in `GuildApi::getActivity()` and is exposed to plugins, but no in-tree plugin persists it anywhere.

See the [plugin system](../../architecture/plugin-system.md#guilddataprovider-parallel-pattern) for how to implement these.

## Minimum modules (profile + crest only)

```
wow
wow_realm
wow_guild
```

That covers the read-only guild profile: name, faction, member count, achievement points, and the crest. Nothing else.

## Minimum modules (with per-character member data)

Add `wow_character` plus whichever reference modules it needs, then add the catalog modules you want surfaced per member:

```
wow_realm
wow_playable_class
wow_playable_race
wow_playable_specialization
wow_character
wow_achievement   # optional per-character progress
wow_mount         # optional per-character collection
...
```

## Setup (profile + crest)

```
drush en wow wow_realm wow_guild -y
drush wow:sync-realms --force
drush wow:guild-lookup stormrage "my guild name"
```

This fetches the guild profile and crest, saves the `wow_guild` entity, and invokes any registered `GuildDataProvider` plugins. By default none ship, so nothing else happens.

## Setup (with roster as characters)

After the basic setup, import each roster member you care about:

```
drush wow:character-lookup stormrage playerone
drush wow:character-lookup stormrage playertwo
```

Each character sync invokes the registered `CharacterDataProvider` plugins, so if `wow_achievement`, `wow_mount`, etc. are enabled, that data lands automatically.

There is no built-in "refresh all roster members" command. If you need one, wrap `CharacterSync::refresh()` in your own drush command or cron task.

## Exposing the dashboard

The suite ships no Views and no templates. Build your own UX:

- **Guild profile block** — render the `wow_guild` entity directly.
- **Roster view** — a View of `wow_character`, filtered by whichever property you track membership through. Note that `wow_character::guild_name` is a plain string (not an entity reference to `wow_guild`); if you want a true reference, add a field yourself or cross-reference by name + realm.
- **Cross-character achievement coverage** — a View of `wow_achievement_progress` filtered on the characters you imported, grouped by achievement.

## Data freshness

- `wow:guild-lookup` refreshes the single guild it names. Schedule it on the cadence your site needs.
- Character-backed data is only as fresh as the last `wow:character-lookup` for that member.
- The `wow.ttl_sweeper` still applies — junction rows untouched in 30 days are swept.

## Guild ownership of achievement progress

When both `wow_guild` and `wow_achievement` are enabled, the `wow_achievement_progress` junction gets a `guild` reference field in addition to `character` (projected by `wow_character`). The column exists and is indexed, but the suite does not currently write guild-owned rows to it — that's extension-point territory via a `GuildDataProvider` plugin.

Uninstalling `wow_guild` purges rows whose `guild` column is populated and leaves character-owned rows intact. See [lifecycle](../../architecture/lifecycle.md).

## See also

- [Plugin system — GuildDataProvider](../../architecture/plugin-system.md#guilddataprovider-parallel-pattern)
- [Blizzard API coverage](../../reference/apis.md) — what's wired vs extension-point
