2026-05 — Single active organization in the portal¶
TL;DR¶
The Hadron portal now shows one organization at a time. The
left-menu ORGANIZATIONS section is gone; an org switcher appears
under "Signed in as" instead, and picking a different org opens it
in a new tab. The URL is the source of truth — /app/orgs/<id>/...
tells you which org a tab is showing.
If you had only your personal organization, nothing changes for you. You won't see a switcher and you won't see organization chrome.
What changed¶
Previously the portal rendered content from every organization
you belonged to simultaneously: the left menu listed all your orgs,
and top-level routes like /app/agents, /app/apps, and
/app/memories aggregated content cross-org. This was getting noisy
for people in many orgs and was inconsistent with the platform's
access model (which already scopes data per-org server-side).
In 2026-05 the portal adopted a Slack/Discord-style single active organization model. The visible org is determined by the URL:
/app/orgs/<id>/...— you're in org<id>./app/dashboard,/app/agents,/app/apps,/app/memories— 302-redirect to the same surface under your active org./app/marketplace— explicitly stays cross-org. It is the cross-org discovery surface.
The portal does not introduce any new client-side state for the
active org. There's no localStorage key, no cookie, no per-session
record competing with the URL. Multi-tab works for free: each tab's
URL says which org it's showing, and tabs don't interfere.
The change is portal-only. The access model, GraphQL API, and MCP tool surface are unchanged — agents installed across multiple orgs, memories picked from another org, and cross-org subscriptions continue to behave exactly as before.
The full design discussion is in design-discussions/hadron-platform/2026-05-03-1-single-active-org
(private repo); the spec is spec-kits/specs/014-single-active-org.
What users see¶
Multi-org users:
- The sidebar's old
ORGANIZATIONSsection is gone. - The "Signed in as" block at the bottom shows your name AND the active org's name.
- A dropdown trigger reveals your other orgs. Picking one opens that org in a new tab — the original tab stays where you were.
- The breadcrumb at the top of org pages no longer starts with
Organizations / <name> /. The org is implicit in the URL and the sidebar. - A
See all organizations →link in the switcher dropdown goes to/app/orgs/, where you manage memberships.
Single-personal-org users:
- The sidebar is unchanged. No active-org indicator, no switcher, no
breadcrumb prefix. (Your personal org is identified by the
platform's existing
isVisible: nullconvention.) - A
Create organizationbutton is on your/app/accountpage if you want to start collaborating.
What about returning users?¶
The portal will remember the org you were last in via a new server-
side field User.lastActiveOrgId. Cold loads of /app/dashboard
take you back to that org. The resolution chain is:
- URL hint (if you opened a deep link), then
- last-visited org, then
- your personal org.
If the recorded last org is no longer accessible (deleted, or you were removed from it), the portal silently falls through to the personal org. There's no "your last org is unavailable" error — the sidebar shows the resolved org and that's enough signal.
Action required¶
None for most users. The change is a UI rework; existing URLs keep working (legacy paths 302-redirect rather than 404).
If you have bookmarks to /app/agents, /app/apps, or
/app/memories, they will redirect to the org-scoped equivalents.
Consider rebookmarking the destination URLs if you always work in
one specific org.
If you build automation that scrapes portal HTML (you probably don't, but if you do): the legacy cross-org list pages no longer render. Switch to the GraphQL API or to the org-scoped URLs.
Why this approach¶
- Drop client state. Active org is a portal rendering convention, not an access decision. Keeping it in the URL means tabs are independent and the trust boundary stays on the server.
- Match the access model. Membership is already per-org server-side; the old cross-org portal layout was effectively presenting an authorization decision as a rendering choice.
- Multi-tab as the cross-org pattern. Slack/Discord proved that power users prefer "open another instance in a new tab" over in-place switching that loses context.
Cross-references¶
- Spec: 014-single-active-org
- Tracking issue: hadron-portal#209
- Design discussion:
2026-05-03-1-single-active-org(private) - Portal constitution1: this change does not modify any of the
six portal-only invariants P1–P6; it follows P5 (consumer-mode
derivation lives server-side) by adding the active-org resolution
alongside
isConsumerModein+layout.server.ts.
-
hadron-portal constitution, Refinements section. ↩