- Shipped
- September 7, 2026 at 5:09 AM UTC
- Author
- Kamo
- Commit
- 7a4335d
The launchpad pane a member works their organisation's growth requests through, and the Marketing settings tab an admin writes and reviews them from. `WidgetDefinition.anchored` becomes `anchorSlot`, and that is the change worth reading. Growth Hub has to sit immediately right of the App Shelf — column 2, row 1 — whether or not the organisation lets the member move it, and the launchpad could not express that: `anchored` meant "first cell, always", and an unmovable widget with no anchor fell into the pinned band ABOVE the grid. A fixed Growth Hub would have jumped out of the grid entirely and its position would have depended on a right, which is the sort of thing nobody can hold in their head. A slot now applies only when the policy says the widget cannot move, so both halves fall out of one mechanism: movable, it leads the ordering and mergeCanonicalOrder puts it in that cell for a member who arranged their launchpad last year as well as a new one; fixed, it is the anchored band's second child with nothing able to be dropped in front of it. The App Shelf is slot 1 and nothing about it changes — a system widget was never movable. THE ONE BOLD THING is the pane's EDGE: while a request is waiting, a light travels the border on a slow circuit, and nothing else on the pane animates by itself. A launchpad is a wall of glass panes and most ways to make one shout make the whole wall worse — a pulsing card is a heartbeat in the corner of somebody's eye all day. A line travelling an edge reads across a room, sits still where the reading happens, and STOPS: the moment the queue empties the circuit ends. It is not decoration that is always on, it IS the unread state, which is why it is asserted from both sides. Under reduced motion it becomes a static ring — dropping it would take the signal away from exactly the members who asked for less movement. The `?` does the glance and the read from one control: the org's explanation as a tooltip on hover, and a polished sheet on click for the rest of a paragraph. It is absent entirely when nothing was written, because a `?` that opens an empty dialog is worse than no `?` and is the sort of control that stays on a pane for years. Images are fetched and handed to the DOM as blobs, never assigned to a `src`: a browser-issued request carries no X-***-Token, 401s on an idle tab, and paints a broken image with nothing in the console. useGrowthImage owns that lifecycle, and compares the loaded path during render rather than clearing state from an effect — otherwise the previous task's artwork appears above the next task's title for a frame. VIEW_GROWTH_HUB is a root right and MANAGE_GROWTH_HUB hangs off VIEW_MARKETING; the settings-menu link is gated on the latter, because the page does not render the tab without it and an ungated link would open Marketing on some other tab while the address bar claimed otherwise.