Owner profile: Repositories moves to its own tab (/:owner/repositories) #422

Closed
opened 2026-09-12 22:56:29 +00:00 by crueber · 3 comments
Owner

What's requested

Move the Repositories list off the owner profile page (/:owner) into its own tab: /:owner/repositories, with the profile page becoming a dedicated profile view (identity +, in future, activity/orgs) rather than a repo listing with a header.

Current state (evidence)

  • web/src/pages/Repos.jsx is both the profile page and the repo listing: after the profile header (~line 304) it renders the Repositories toolbar (heading + New repository CTA, ~line 432) and the two-column repo grid (~line 440–460), plus the "import into {owner}" footer link.
  • Routes (web/src/index.jsx line 72): <Route path="/:owner" component={Repos} /> — there is no /types style sub-route for the owner namespace, unlike the repo pages (/:owner/:name/issues, /pulls, …).

Proposed design

  • Add route /:owner/repositories (registered before/alongside /:owner — mind the static-before-dynamic ordering used for /orgs/new and /invitations).
  • The profile page keeps the header and links to the repositories tab (e.g. a Repositories entry count in a tab strip or link row under the header); the repositories page keeps the Repositories toolbar + New repository CTA + grid + import link exactly as they render today, so the listing is a move, not a redesign.
  • Decision point for the planner: profile-page tab strip vs simple link — pick one and note it. If a tab strip, reuse the repo page's tab bar anatomy (web/src/pages/Repo.jsx) for visual consistency.
  • Repo rows continue to use the shared <RepoRow> (also consumed by /explore) — do not fork it.

Architecture notes

  • Client-only: web/src/index.jsx routes + web/src/pages/Repos.jsx split (likely Repos.jsx keeps the header/profile, new Repositories page or a shared component takes the listing). No API changes — the listing still rides GET /api/v1/owners/{owner}/repos/detailed with the existing repos:{owner} cache key shared with /explore.
  • Deep links to /:owner must not break: external links and navbar entries currently target /:owner; decide whether /repositories redirects or /:owner keeps a repo-count teaser. (Planner's call; note it.)

Acceptance criteria

  • /:owner/repositories renders the repository listing (toolbar, New repository CTA per canWrite, grid, import link) unchanged from today's layout.
  • /:owner renders the profile (header, identity) without the repo grid, with a working link/tab to the repositories view.
  • Existing entry points (navbar, /explore owner sections, issue author links) still land somewhere sane — no dead /:owner behavior change without a note.
  • Org variant (isOrg()) keeps working on both routes.
  • No horizontal overflow at 390px on either route.
  • Headless tests updated; vite build green.
## What's requested Move the Repositories list off the owner profile page (`/:owner`) into its own tab: `/:owner/repositories`, with the profile page becoming a dedicated profile view (identity +, in future, activity/orgs) rather than a repo listing with a header. ## Current state (evidence) - `web/src/pages/Repos.jsx` is both the profile page and the repo listing: after the profile header (~line 304) it renders the Repositories toolbar (heading + New repository CTA, ~line 432) and the two-column repo grid (~line 440–460), plus the "import into {owner}" footer link. - Routes (`web/src/index.jsx` line 72): `<Route path="/:owner" component={Repos} />` — there is no `/types` style sub-route for the owner namespace, unlike the repo pages (`/:owner/:name/issues`, `/pulls`, …). ## Proposed design - Add route `/:owner/repositories` (registered before/alongside `/:owner` — mind the static-before-dynamic ordering used for `/orgs/new` and `/invitations`). - The profile page keeps the header and links to the repositories tab (e.g. a Repositories entry count in a tab strip or link row under the header); the repositories page keeps the Repositories toolbar + New repository CTA + grid + import link exactly as they render today, so the listing is a move, not a redesign. - Decision point for the planner: profile-page tab strip vs simple link — pick one and note it. If a tab strip, reuse the repo page's tab bar anatomy (`web/src/pages/Repo.jsx`) for visual consistency. - Repo rows continue to use the shared `<RepoRow>` (also consumed by `/explore`) — do not fork it. ## Architecture notes - Client-only: `web/src/index.jsx` routes + `web/src/pages/Repos.jsx` split (likely Repos.jsx keeps the header/profile, new Repositories page or a shared component takes the listing). No API changes — the listing still rides `GET /api/v1/owners/{owner}/repos/detailed` with the existing `repos:{owner}` cache key shared with `/explore`. - Deep links to `/:owner` must not break: external links and navbar entries currently target `/:owner`; decide whether `/repositories` redirects or `/:owner` keeps a repo-count teaser. (Planner's call; note it.) ## Acceptance criteria - [ ] `/:owner/repositories` renders the repository listing (toolbar, New repository CTA per `canWrite`, grid, import link) unchanged from today's layout. - [ ] `/:owner` renders the profile (header, identity) without the repo grid, with a working link/tab to the repositories view. - [ ] Existing entry points (navbar, /explore owner sections, issue author links) still land somewhere sane — no dead `/:owner` behavior change without a note. - [ ] Org variant (`isOrg()`) keeps working on both routes. - [ ] No horizontal overflow at 390px on either route. - [ ] Headless tests updated; `vite build` green.
crueber added this to the v1 milestone 2026-09-12 22:56:29 +00:00
Author
Owner

Fix is up for review: #428 (branch fix/issue-422, client-only, no API change). Planner calls: tab strip reusing the Repo.jsx tab bar anatomy + no redirect (/:owner stays a valid profile with a count teaser linking onward). Note: a repo literally named repositories loses its UI page (static route wins; git/API unaffected). Tests 889/887 (2 pre-existing shell-serve failures, identical on clean main); vite build green; browser proof open per workspace rules.

Fix is up for review: https://git.packden.us/crueber/walhub/pulls/428 (branch fix/issue-422, client-only, no API change). Planner calls: tab strip reusing the Repo.jsx tab bar anatomy + no redirect (/:owner stays a valid profile with a count teaser linking onward). Note: a repo literally named repositories loses its UI page (static route wins; git/API unaffected). Tests 889/887 (2 pre-existing shell-serve failures, identical on clean main); vite build green; browser proof open per workspace rules.
Author
Owner

Review PR #428 (fix/issue-422) — verified in scratch worktree /tmp/pr428 (detached 2c1a02b):

(1) Route ordering PASS — web/src/index.jsx:77 /:owner/repositories before :78 /:owner before :81 /:owner/:name; static-before-dynamic reservation comment cites /orgs/new rule, notes repo named repositories loses UI page, git/API unaffected. /:owner kept, deep-links safe.

(2) Profile view PASS — header/profile-header + #421 sidebar intact via shared OwnerPage(view); OwnerTabs reuses Repo.jsx tab anatomy (same flex/max-w-full/gap-1/overflow-x-auto/whitespace-nowrap/border-b, link treatment, active underline, aria-current, labelled landmark) under own owner-tabs hook; teaser count + View all link, no grid/toolbar/CTA/import on profile (headless-pinned).

(3) Repositories view PASS — toolbar/CTA/grid/import verbatim move (only Show view()==repos gate new); CTA gate + hrefs byte-identical; same repos:{owner} cache key (count rides payload, zero new fetches); single shared RepoRow, /explore untouched.

(4) Org variant PASS — strip at Repos.jsx:469 outside every isOrg Show (438 block closes 463), renders both routes/variants; org header + settings footer moved with listing.

(5) Entry points PASS — no navbar/explore/author link changes in diff; Owners.jsx still -> /:owner (now valid profile with teaser onward); post-create navigate -> /owner/repo unaffected. Noted in PR body.

(6) 390px PASS — owner-tabs narrow rules mirror repo-tabs (scrollbar none, shrink-0, max-w-full + overflow-x-auto + whitespace-nowrap); toolbar flex-wrap kept; no fixed widths.

(7) Scope/docs PASS — no .go files, no package.json/lock changes (client-only, no API, no new deps per Law 1); docs/go/12_web_ui.md route table + Decisions updated same commit (Law 12). Minor stale (non-blocking): §2.x line 282 '+N more -> /:owner (uncapped there)' now one click further via teaser — link target still sane.

Tests: node --test web/test/unit/*.test.js 889 total / 887 pass / 2 fail — both in smoke.test.js (live-server shell-serve), identical on clean main (main smoke 3/1/2). New owner-repos-tab-422.test.js 9 tests green. Vite build green (163 modules, 602kB JS).

No browser drive per task scope (node tests + reasoning; module-MIME/redirect risk noted as open, same as PR).

Recommendation: ready to merge.

Review PR #428 (fix/issue-422) — verified in scratch worktree /tmp/pr428 (detached 2c1a02b): (1) Route ordering PASS — web/src/index.jsx:77 /:owner/repositories before :78 /:owner before :81 /:owner/:name; static-before-dynamic reservation comment cites /orgs/new rule, notes repo named repositories loses UI page, git/API unaffected. /:owner kept, deep-links safe. (2) Profile view PASS — header/profile-header + #421 sidebar intact via shared OwnerPage(view); OwnerTabs reuses Repo.jsx tab anatomy (same flex/max-w-full/gap-1/overflow-x-auto/whitespace-nowrap/border-b, link treatment, active underline, aria-current, labelled landmark) under own owner-tabs hook; teaser count + View all link, no grid/toolbar/CTA/import on profile (headless-pinned). (3) Repositories view PASS — toolbar/CTA/grid/import verbatim move (only Show view()==repos gate new); CTA gate + hrefs byte-identical; same repos:{owner} cache key (count rides payload, zero new fetches); single shared RepoRow, /explore untouched. (4) Org variant PASS — strip at Repos.jsx:469 outside every isOrg Show (438 block closes 463), renders both routes/variants; org header + settings footer moved with listing. (5) Entry points PASS — no navbar/explore/author link changes in diff; Owners.jsx still -> /:owner (now valid profile with teaser onward); post-create navigate -> /owner/repo unaffected. Noted in PR body. (6) 390px PASS — owner-tabs narrow rules mirror repo-tabs (scrollbar none, shrink-0, max-w-full + overflow-x-auto + whitespace-nowrap); toolbar flex-wrap kept; no fixed widths. (7) Scope/docs PASS — no .go files, no package.json/lock changes (client-only, no API, no new deps per Law 1); docs/go/12_web_ui.md route table + Decisions updated same commit (Law 12). Minor stale (non-blocking): §2.x line 282 '+N more -> /:owner (uncapped there)' now one click further via teaser — link target still sane. Tests: node --test web/test/unit/*.test.js 889 total / 887 pass / 2 fail — both in smoke.test.js (live-server shell-serve), identical on clean main (main smoke 3/1/2). New owner-repos-tab-422.test.js 9 tests green. Vite build green (163 modules, 602kB JS). No browser drive per task scope (node tests + reasoning; module-MIME/redirect risk noted as open, same as PR). Recommendation: ready to merge.
Author
Owner

Fixed by PR #428 (review clean — all 7 checks pass, verbatim move, entry points sane), merged. Closing.

Fixed by PR #428 (review clean — all 7 checks pass, verbatim move, entry points sane), merged. Closing.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
crueber/walhub#422
No description provided.