Skip to content

23 — iOS Phase 2: Information Architecture & Navigation

Active spec. Governed by 00-ROADMAP.md. Last updated 2026-06-07. Builds on the completed Phase 1 MVP (19-IOS-MVP-REVIEW-APPROVE.md) and the design system (22-IOS-DESIGN-SYSTEM.md).

Context

Phase 1 shipped the Review & Approve loop (sign in → feed → track → player → comment → approve), all working end-to-end. The landing screen is a flat Recent / Shared / Yours feed — a deliberate shortcut to the approve loop. Phase 2 replaces that with the artwork-forward browse hierarchy the canva-refs depict, plus first-class shared (inbound/outbound) views and Portals everywhere. The Phase 1 player/comment/approve surfaces stay exactly as they are — this is navigation around them.

The real hierarchy (grounded in the backend)

ArtistSpace → Project → Track → File (versions) → Comment / Section

  • ArtistSpace is the top-level container (an "Artist" in the UI). There is no Roster entity yetlabel is only a string field on Track. A Roster grouping above ArtistSpace (the "Roster" nav in web-front--home-dashboard-idea.png) is a future concept; do not model it as an entity now. (Preferred term is "Roster", not "Label".)
  • Permissions cascade ArtistSpace → Project → Track (owner / admin / editor / viewer).

Screen map (Phase 2)

ScreenSource refPrimary data
Home — Artistsmobile-front--artis-projects.png (hero + grid)GET /artist (owned) + inbound spaces
Artist → Projectsmobile-front--artis-projects.pngGET /project/artist/:artistId
Project → Tracksmobile-front--project-tracks.pngGET /track/project/:projectId
Track detail / Player / PortalPhase 1 (web-front--wave-player.png)existing — unchanged
Shared (inbound / outbound)see Sharing below

Navigation: NavigationStack with navigationDestination per level (Artist id → Project id → Track id), artwork-forward ProjectCard grid + TrackRow list (both already in DesignSystem/). The flat Recents feed becomes a secondary tab or the Home's "Recent" rail, not the primary surface.

Endpoint map (what exists vs gaps)

NeedEndpointStatus
My artistsGET /artist
Projects in an artistGET /project/artist/:artistId
Tracks in a projectGET /track/project/:projectId
Inbound — shared spaces / projects / tracksGET /collaboration/collaborator/{spaces,projects,tracks}
Inbound — recent shared activityGET /collaboration/recents
Outbound — what I shared(derive from owned + GET /link/{artist,project,track}/:id)🟡 may want a /collaboration/shared-by-me aggregate
Artist / Project metadata for PortalsGET /artist/:id, GET /project/:id

Portals everywhere

Extend the Phase 1 Portal (glass sheet + detents) beyond Track to Artist and Project contextual detail (metadata + collaborators + share). Same Portal / MetadataRow / LabelCopyTable components; new content bodies (ArtistPortalContent, ProjectPortalContent).

Sharing — inbound vs outbound (the UX the user called out)

PARKED (2026-06-07). A first-pass Shared tab was built then pulled — "Shared" is a consequence of how Roster / workspaces / actors are modeled, not a standalone tab. The browse hierarchy below stays active; this Sharing section is parked. The envisioning that answers it (lenses, sharing identity, Roster-as-tag — decisions confirmed 2026-06-07) is 26-IDENTITY-SHARING-NAVIGATION.md; it ships post-polish per 25-IOS-CRUD-FIRST-RELEASE.md. Keep the endpoint notes for when it's reintroduced.

  • Inbound ("Shared with me"): things others shared to me — /collaboration/collaborator/* + /recents.
  • Outbound ("Shared by me"): my owned resources that have collaborators or active share-links. No single endpoint today — derive client-side from owned resources + GET /link/*, or add a backend aggregate (/collaboration/shared-by-me) in a backend slice. Surface both as segments of a Shared screen.

Out of scope (later phases)

The pro dashboard (web-front--home-dashboard-idea.png — Roster, charts, ContactID), a Roster entity (grouping above ArtistSpace), upload/creation on iOS, and full search. Keep Phase 2 to browse + shared + Portals.

Build order (suggested slices)

  1. Home → Artists grid (GET /artist) with ArtistPortalContent.
  2. Artist → Projects (GET /project/artist/:id) using ProjectCard.
  3. Project → Tracks (GET /track/project/:id) using TrackRow → existing track detail/player.
  4. Shared screen (inbound segment first; outbound after the backend aggregate).

Each slice follows .agent/workflows/ios-feature-slice.md.

Cross-references

Ctrl-Audio Platform Documentation