Source: ddx-documentation/research/rq2-route-shape.md
**Question** (BRIEF.md RQ2): does "portal/(slug)/[role]/" mean a route group or a dynamic org slug, and how does it compose with the `[locale]` root and the `(marketing)` / `(auth)` / `(app)` groups? **Answer** (owner Q2, confirmed 2026-10-23): a **dynamic org slug**. `/[locale]/portal/[slug]/[role]/...` lives inside the `(app)` group. Entity routes use `[entity]/[id]`, and list views switch with `?view=`. Decision: [ADR 0003](/en/docs/adr/0003-route-shape). ## Findings | # | Finding | Source | |---|---|---| | F1 | A route group `(slug)` adds no URL segment. It only groups layouts. It cannot carry an org value, so it cannot express a tenant. | Next.js App Router route groups docs <https://nextjs.org/docs/app/api-reference/file-conventions/route-groups> (cited, not fetched 2026-10-23); Q2 in `ddx-wip/rewrite_ui-shell-rnd-workspace/ANSWERS.md` | | F2 | HMS resolves the org from the host name and has no slug segment. Tenant scope is hidden from the URL, so isolation is hard to test. | Q2, `ANSWERS.md` | | F3 | The D4 canon has three route groups: `(marketing)`, `(auth)`, `(app)`. Providers 4-7 (Session, Org, Settings, SSE) mount only in `(app)`. The portal tree must sit under `(app)`. | `~/.claude/findings/nextjs-skills-audit/CANON.md` D4; stack-specialist rule R2/R5 | | F4 | HMS detail URLs have two shapes (`<seg>/[id]` and `<seg>/view/[id]`), edit URLs two shapes (`[id]/edit` 23 vs `view/[id]/edit` 4), and nine param names for the same id. | `findings/hms-pattern-audit/routes.md` §1 (lines 41-44) | | F5 | HMS encodes density and view in path segments (`list/<density>`). The gap map maps this to `[entity]/[id]` + `?view=`. | `findings/hms-pattern-audit/catalog.md` §Gap map (line 143); `PortalPageList` `viewModes` via `?view=` (line 33) | | F6 | 17 HMS pages (5.6 % of the tree) are redirect glue for duplicate route shapes. One shape removes them. | `findings/hms-pattern-audit/routes.md` I16 | | F7 | Role gating happens in one place only (PortalPage). The `[role]` layout resolves org + session; it does not gate. | `plans/ui-shell-rnd-workspace/_invariants.md` invariant 14 | ## Resulting tree ``` src/app/[locale]/ (marketing)/... SiteShell (auth)/... sign-in, sign-up (app)/portal/[slug]/[role]/ layout.tsx PortalShell; resolves org by slug + session [entity]/page.tsx list (?view=list|grid|board|timeline) [entity]/new/page.tsx create [entity]/[id]/page.tsx detail / record [entity]/[id]/edit/page.tsx ``` One param name: `[id]`. No `view/` segment. No redirect pages. ## Still to verify (later tasks) - The BRIEF asks for a typed-routes build of both variants. That build runs in the ddx-web scaffold task. This page holds the desk half only. - Host-based org resolution stays a later option (Q2). It is not built now.
Question (BRIEF.md RQ2): does "portal/(slug)/[role]/" mean a route group or a dynamic
org slug, and how does it compose with the [locale] root and the
(marketing) / (auth) / (app) groups?
Answer (owner Q2, confirmed 2026-10-23): a dynamic org slug.
/[locale]/portal/[slug]/[role]/... lives inside the (app) group. Entity routes use
[entity]/[id], and list views switch with ?view=. Decision: .
One param name: [id]. No view/ segment. No redirect pages.
adr/
deploy/
research/
src/app/[locale]/ (marketing)/... SiteShell (auth)/... sign-in, sign-up (app)/portal/[slug]/[role]/ layout.tsx PortalShell; resolves org by slug + session [entity]/page.tsx list (?view=list|grid|board|timeline) [entity]/new/page.tsx create [entity]/[id]/page.tsx detail / record [entity]/[id]/edit/page.tsx