Problem
#573 split the browse and manage views, but only the list moved. Position editing is still a subroute of the public tree:
app/(main)/positions/page.tsx ← public browse
app/(main)/positions/[id]/page.tsx ← public detail
app/(main)/(auth)/positions/[id]/apply/page.tsx ← apply (auth)
app/(main)/(auth)/positions/[id]/edit/page.tsx ← EDIT (auth) ← wrong tree
app/(main)/(auth)/my-positions/page.tsx ← manage list
So /positions/[id]/edit sits under the route users browse openings on, while the manage list it belongs to lives somewhere else entirely. The split is half-done.
Separately, "My Positions" is the wrong name. These aren't positions you own in any personal sense — they're positions you administer. The nav group containing it is already called "Manage".
Naming — decided
Route: /manage/positions. Label: "Manage Positions". Position editing becomes /manage/positions/[id]/edit.
The /manage/* namespace covers manager surfaces only. /users and /global-questions stay flat — they're admin utilities with no personal counterpart and no ambiguity to resolve.
The scheme this lands on:
| Audience |
Routes |
| Applicant / public |
/positions, and eventually /applications |
| Manager |
/manage/positions, /manage/applications |
| Admin |
/users, /global-questions |
Bare noun = the thing as a user encounters it; /manage/* = administering it.
Why the rename matters beyond tidiness. The app disambiguates personal from managerial with a my- prefix — /my-applications (mine) vs /applications (manage). But /my-positions uses that same prefix for a management surface, the exact opposite meaning. The prefix is inverted, not just ugly, which is why it reads wrong.
/manage/applications and the follow-on /my-applications → /applications are tracked separately; this ticket is positions only and does not depend on either.
Scope
1. Move the manage list. my-positions → the chosen route, with its loading.tsx.
2. Move position editing out of app/(main)/(auth)/positions/[id]/edit/ and under the manage route, with its loading.tsx.
3. Leave the applicant tree alone. /positions, /positions/[id] and /positions/[id]/apply stay exactly where they are — browsing and applying are the public/applicant flow.
4. Update every link and redirect. Known senders of users to the edit route: the position detail page's manage buttons (/positions/${id}/edit), position-card.tsx's Edit button, and the create-position flow if it redirects to edit. Grep for my-positions and /edit both; a stale link here is a 404 for a manager mid-task.
5. Rename the nav entry in components/layouts/nav-items.ts and check use-nav-items.ts's active-state matching still works against the new path.
6. Preserve the guards. The edit page uses requireListedManagerOr404 and checkPositionEditable; moving the file must not change either.
Non-goals
- No change to what the edit page does, or to the position form.
- No change to
/applications, /users or /global-questions in this ticket, even if /manage/* is chosen.
- No redirects from the old paths unless they've been shared externally — these are authenticated internal surfaces, so a clean move is fine.
Acceptance criteria
Problem
#573 split the browse and manage views, but only the list moved. Position editing is still a subroute of the public tree:
So
/positions/[id]/editsits under the route users browse openings on, while the manage list it belongs to lives somewhere else entirely. The split is half-done.Separately, "My Positions" is the wrong name. These aren't positions you own in any personal sense — they're positions you administer. The nav group containing it is already called "Manage".
Naming — decided
Route:
/manage/positions. Label: "Manage Positions". Position editing becomes/manage/positions/[id]/edit.The
/manage/*namespace covers manager surfaces only./usersand/global-questionsstay flat — they're admin utilities with no personal counterpart and no ambiguity to resolve.The scheme this lands on:
/positions, and eventually/applications/manage/positions,/manage/applications/users,/global-questionsBare noun = the thing as a user encounters it;
/manage/*= administering it.Why the rename matters beyond tidiness. The app disambiguates personal from managerial with a
my-prefix —/my-applications(mine) vs/applications(manage). But/my-positionsuses that same prefix for a management surface, the exact opposite meaning. The prefix is inverted, not just ugly, which is why it reads wrong./manage/applicationsand the follow-on/my-applications→/applicationsare tracked separately; this ticket is positions only and does not depend on either.Scope
1. Move the manage list.
my-positions→ the chosen route, with itsloading.tsx.2. Move position editing out of
app/(main)/(auth)/positions/[id]/edit/and under the manage route, with itsloading.tsx.3. Leave the applicant tree alone.
/positions,/positions/[id]and/positions/[id]/applystay exactly where they are — browsing and applying are the public/applicant flow.4. Update every link and redirect. Known senders of users to the edit route: the position detail page's manage buttons (
/positions/${id}/edit),position-card.tsx's Edit button, and the create-position flow if it redirects to edit. Grep formy-positionsand/editboth; a stale link here is a 404 for a manager mid-task.5. Rename the nav entry in
components/layouts/nav-items.tsand checkuse-nav-items.ts's active-state matching still works against the new path.6. Preserve the guards. The edit page uses
requireListedManagerOr404andcheckPositionEditable; moving the file must not change either.Non-goals
/applications,/usersor/global-questionsin this ticket, even if/manage/*is chosen.Acceptance criteria
/positions./positions,/positions/[id]and/positions/[id]/applyare unchanged.requireListedManagerOr404andcheckPositionEditablestill gate the edit page.loading.tsxat the same page-width tier perdocs/DESIGN.md.docs/WORKFLOWS.mdPM-2 and PM-4 updated — both name the current routes.npm run prettier:check,eslint:check,tsc:check,testall pass.