Skip to content

[Task] Split layout.tsx into agent-readable controllers #474

@Astro-Han

Description

@Astro-Han

Goal

Split packages/app/src/pages/layout.tsx into smaller, agent-readable controllers/components so future PawWork sidebar, session navigation, project/workspace, and settings work can be changed safely without loading a 2k+ line catch-all component into one mental context.

When this is done, layout.tsx should mostly compose focused controllers and surfaces. Each extracted file should have one clear responsibility, small enough for an agent to read in one pass, with targeted tests around behavior that was previously hidden inside layout.tsx.

This is maintenance work to match the project AGENTS guidance for new or actively modified frontend code: keep files focused, easy to grep, and extract cohesive controllers/components when a file grows past a few hundred lines.

Scope

In scope:

  • Start with a read-only inventory of current layout.tsx responsibilities and existing dead/legacy code paths.
  • Propose review-sized slices before implementation; do not turn this into one giant rewrite PR.
  • Extract cohesive logic from layout.tsx into focused files under packages/app/src/pages/layout/.
  • Preserve current user-visible behavior unless a specific dead/legacy path is proven unreachable or obsolete.
  • Remove dead code, stale helpers, unused state, and legacy branches only when code search and tests prove they are not used.
  • Prefer pure helpers/controllers with unit tests where possible.
  • Keep UI components small and domain-named, not generic buckets.
  • Maintain current PawWork desktop UX: conversation-first layout, sidebar behavior, session routing, project/workspace controls, settings entry points, and existing keyboard/command behavior.

Suggested slice order:

  1. PawWork session window/controller

    • session window state
    • initial load / show more
    • active and pinned session merging
    • sidebar row construction
    • timestamp/sort data boundary
  2. Session prefetch controller

    • prefetch queues
    • LRU and pending limits
    • warm neighboring sessions
    • message cache preloading
  3. Project/workspace actions controller

    • open/close project
    • rename project/workspace
    • delete/reset workspace
    • workspace drag reorder
  4. Settings/theme/language/provider commands

    • settings surface open/close
    • theme and color-scheme cycling
    • language cycling
    • provider/server entry actions
  5. Inline dialogs/components still living inside layout.tsx

    • delete/reset workspace dialogs
    • any other local components that can move without changing behavior

Out of scope:

  • Do not redesign the sidebar UI.
  • Do not change the session window product semantics from [Feature] Sort initial sidebar sessions by last user message time #473 in this refactor unless that issue is explicitly included in a separate PR.
  • Do not change backend APIs, persistence schema, desktop packaging, updater, permissions, or model harness behavior.
  • Do not bundle unrelated visual polish, copy changes, or design-token work.
  • Do not delete code just because it looks old; prove it is dead by grep/tests/runtime path analysis first.
  • Do not create one large PR that mixes all slices. Each PR should be reviewable and reversible.

Relevant files or context

Current facts:

  • packages/app/src/pages/layout.tsx is currently about 2,274 lines.
  • It mixes route parsing, session window loading, session prefetch, project/workspace actions, settings/theme/language commands, deep links, drag/drop, dialogs, and sidebar rendering.
  • Existing extracted layout files already provide patterns:
    • packages/app/src/pages/layout/pawwork-session-source.ts
    • packages/app/src/pages/layout/pawwork-session-window.ts
    • packages/app/src/pages/layout/pawwork-session-nav.ts
    • packages/app/src/pages/layout/pawwork-sidebar.tsx
    • packages/app/src/pages/layout/sidebar-workspace.tsx
    • packages/app/src/pages/layout/shell-navigation.ts
    • packages/app/src/pages/layout/inline-editor.tsx
    • packages/app/src/pages/layout/deep-links.ts

Related issues / PRs:

Agent-era structure target:

  • Files should be named after product responsibilities, not technical leftovers.
  • Controllers should own state transitions and side effects for one domain.
  • Pure helpers should sit beside tests.
  • layout.tsx should become an orchestrator, not the place where every product behavior lives.

Verification

For every slice:

  • Show the before/after file responsibility map in the PR body.
  • Run targeted unit tests for extracted helpers/controllers.
  • Run bun --cwd packages/app typecheck.
  • Run git diff --check.
  • For visible app behavior or routing/sidebar/session changes, run bun run dev:desktop and manually verify the changed user path in Electron, or explicitly document why Electron verification was not possible.
  • If the slice changes sidebar, routing, session creation/opening, project opening, panel resize, dialogs, menus, or drag/drop behavior, add or update user-path E2E coverage where practical.
  • Confirm no unrelated generated files, docs, local-only AGENTS/TODO files, dependency files, or icon outputs were staged.
  • Confirm deleted code was proven unused by grep/tests or replaced by the extracted controller.

Execution mode

Agent should investigate and propose a plan first

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium priorityappApplication behavior and product flowstaskNarrow execution, audit, spike, migration, tracking, or upstream follow-up worktech-debtSupplemental cleanup, maintainability, architecture, test, or quality debt context

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions