feat(guilds): a third place on the guild page, and where that page lives
All checks were successful
PR Checks / server-tests (pull_request) Successful in 23s
PR Checks / client-build (pull_request) Successful in 17s
PR Checks / frozen-manifest (pull_request) Successful in 34s

Two lines only core cannot supply for itself.

`uo.guild.header` is a third declared slot, at the top of the page, for core's
per-Team notification control. A third rather than a corner of the feed because a
slot holds one component and the first fill wins: the control is an action ON this
page and the other two are content IN it, and separate slots are what let this
module say so.

`pageUrlTemplate` tells core where a guild page actually is. Teams are a contract
primitive with no core surface — core owns the tables and the access rules, this
module owns the word "guild" and therefore the page — which leaves core unable to
write a link to one. A notification email that cannot take you to the thread it is
about is most of the way to useless. Core substitutes `{externalId}` and does
nothing else with it; a template naming its own host is refused at registration.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-18 14:35:36 -05:00
parent 7ce78e303c
commit c57310c505
4 changed files with 39 additions and 5 deletions

View File

@@ -214,10 +214,16 @@ it('declares its own guild slots, for core to fill', () => {
// core page: core owns the activity feed and the forum, this module owns the
// word "guild", so this module declares the places and core puts them in.
//
// TWO slots rather than one because a slot holds one component: stacking the
// feed and the forum into a single fill would take away this module's ability
// to place them separately on its own page.
assert.deepEqual([...registered.declaredSlots], ['uo.guild.detail', 'uo.guild.forum'])
// THREE slots rather than one because a slot holds one component: stacking the
// feed, the forum and the notification control into a single fill would take
// away this module's ability to place them separately on its own page — and it
// does place them separately, the control above the roster and the other two
// below it.
assert.deepEqual([...registered.declaredSlots], [
'uo.guild.detail',
'uo.guild.forum',
'uo.guild.header',
])
})
it('every declared slot is rendered by the page that owns it', () => {