refactor(app): delete dead home page and redirect to default workspace (#603 PR1/3)#651
Conversation
The /pages/home.tsx page (139 lines: Logo, server picker, recent projects, empty state) was never reached: Electron webContents persists the last URL, and the backend defaults the workspace to ~/PawWork (opencode/src/server/instance/middleware.ts:52,64). Every boot opens directly into the session route for the resolved path, bypassing /. Replace Route path="/" with HomeRedirectRoute that resolves the first registered project at render time and <Navigate>s to /<base64>/session. The blank fallback covers the one-frame projects-list hydration window so users see no flash of old home content. Remove the two orphan i18n keys (home.empty.title / home.empty.description); home.recentProjects stays — still used by dialog-select-directory.tsx:339. Slice 1 of 3 for #603 (W5 home surface). PR2 will remove the skill-card shortcuts; PR3 will rewrite NewSessionView as the W5 hero. See issue comment 4460021650 for the full design + 3-slice inventory. Refs #603.
There was a problem hiding this comment.
Suggested priority: P2 (includes user-path files (packages/app/src/app.tsx, packages/app/src/i18n/en.ts, packages/app/src/i18n/zh.ts, packages/app/src/pages/home.tsx)).
P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughRoot landing path now redirects to the first available project's session route via a new HomeRedirectRoute. The Home page component and its empty-state translations were removed; i18n now uses a recent-projects label. E2E smoke tests and smoke-tagging were updated to cover the new root redirect behavior. ChangesHome Route Redirect
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser
participant Router as App Router
participant HomeRedirect as HomeRedirectRoute
participant Layout as LayoutContext (useLayout)
participant GlobalSync as GlobalSync (useGlobalSync)
participant Navigate as Navigate / SessionRoute
Browser->>Router: navigate to /
Router->>HomeRedirect: render HomeRedirectRoute
HomeRedirect->>Layout: read projects.list()[0]
alt layout has project
Layout-->>HomeRedirect: project worktree
else layout missing
HomeRedirect->>GlobalSync: fallback read project[0]
GlobalSync-->>HomeRedirect: project worktree
end
HomeRedirect->>Navigate: Navigate to /{base64Encode(worktree)}/session
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Perf delta summaryComparator: pass
|
There was a problem hiding this comment.
Code Review
This pull request replaces the home page with a redirection mechanism that automatically routes users to the first available project's session. This change includes the removal of the Home component and its corresponding translation strings. A critical bug was identified in the new HomeRedirectRoute component where the child function of the Show component incorrectly treats its argument as an accessor, which will lead to a runtime TypeError in SolidJS.
The "root route renders the no-project empty state" smoke test asserted text and a button that this PR removes (home.empty.title / home.empty.description / the Open Project button on the dead / page). The empty-projects scenario the test mocked is impossible in real product because the backend ensures ~/PawWork exists at middleware.ts:64; the test was an artificial mock of UI that no longer exists. Other home.spec.ts cases (hero composer, starter cards, prompt-starts- session, single-row bar, model chip, server picker) are unchanged and still cover the live home surface. The sidebar "No projects open" state that this test also touched still has coverage elsewhere if needed; not in scope for this PR. Refs #603.
Sync the e2e-smoke-tagging.test.ts expected inventory with the prior removal of the "@smoke root route renders the no-project empty state" title from home.spec.ts. The inventory test enforces an exact-match contract on the @smoke catalog, so removing a spec without updating this list fails unit-opencode CI.
HomeRedirectRoute previously read only layout.projects.list(), which is the localStorage-persisted sidebar list of projects the user has opened in this client. On a clean install (empty localStorage) that list is [], so the route stayed on the hidden pending placeholder with no visible entry, even though the backend already registered ~/PawWork via middleware.ts mkdirSync. Add globalSync.project (the backend-pushed project catalogue) as a fallback so a fresh client redirects to /<slug>/session once the backend sync arrives, instead of stalling indefinitely. Cover the path with a new @smoke spec that opens a project, wipes the local server.projects map to mimic a clean client, navigates to /, and asserts the URL still lands on the project session route. Add the new title to the e2e-smoke-tagging inventory.
The new @smoke spec asserted toHaveURL(/${project.slug}/session), which expected the redirect to land on the fixture's test directory. In practice globalSync.project[0] on CI is the PawWork default project (~/PawWork), not the test fixture's createTestProject directory, so the URL legitimately resolved to /<base64-of-PawWork>/session. Switch the assertion to a slug-agnostic /<base64>/session pattern. The contract this test guards is "root no longer stalls on the hidden pending placeholder when localStorage is empty", which the pattern match expresses without coupling to which backend project comes first.
globalStore.project is hydrated from the persisted projectCache before the boot fetch runs (global-sync.tsx initial state + bootstrap.ts slow phase). Reading sync.data.project[0] before sync.ready can therefore hand the redirect a stale entry that the backend no longer registers, sending the user to a directory that fails to load. Gate the backend fallback on sync.ready so the route keeps the hidden placeholder until the fresh project list arrives. Normal Electron boots restore the previous URL via webContents persistence and never reach /, so the added wait is invisible in practice and only protects clean installs and cache-cleared edge cases.
## Summary
Refresh the home `<h1>` to the W5 welcome wording locked by the design preview ("今天我们做点什么?" / "What should we work on?") and tune the heading typography toward `--type-display`: medium weight, 28/130, and the documented zh-CJK letter-spacing rule (CJK 0, en tightest). Widen the heading-to-composer gap from `mt-12` to `mt-20` so the hero block breathes. Production layout, `WorkspaceChip` inside the composer, and every other home surface stay untouched.
## Why
PR1 (#651) cleared the dead home page and PR2 (#657) stripped the skill-card pipeline. PR3 originally planned to rewrite `NewSessionView` as a W5 hero (meta-path button + branch chip + extracted `WorkspacePopover`). The maintainer manual-tested the experiment in Electron and decided the cwd signal reads cleaner where it already is (inside the composer), and that the home page should stay minimal. Rolled back to the smallest change that delivers the welcome copy + typography refresh on the existing layout.
## Related Issue
Refs #603. Slice 3 of 3.
## Human Review Status
Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.
## Review Focus
- `session-new-view.tsx` — `--type-display` is rendered with arbitrary Tailwind values (`text-[28px] font-medium leading-[1.3]` + `tracking-[var(--letter-spacing-tightest|normal)]`) because there is no `text-display` utility class yet. Introducing one would be a cross-package utility addition (would touch `packages/ui` and the error-page heading); kept out of scope and noted as a follow-up candidate.
- i18n: `home.hero.title` replaces `session.new.title`. Both `parity.test.ts` and the `home.spec.ts` heading assertion are updated. `session.new.title` is removed in both locales — grep confirms no other consumer.
- The opencode `@smoke` inventory in `packages/opencode/test/config/e2e-smoke-tagging.test.ts` is updated alphabetically to match the new home smoke title.
## Risk Notes
None. No behavioral or platform-impacting change. No new schema, no migration, no IPC surface touched.
## How To Verify
```text
packages/app typecheck (tsgo -b): clean
packages/opencode typecheck (tsgo --noEmit): clean
packages/app unit tests (bun test src/): 1103 pass / 0 fail / 2649 expect()
packages/app E2E home.spec.ts (chromium): 6 pass / 10.0s
packages/opencode e2e-smoke-tagging unit: 2 pass
Electron `bun run dev:desktop` manual check: heading copy + medium-weight display tier + heading↔composer gap visible; WorkspaceChip remains inside composer; zh + en letter-spacing rules both render
Crosscheck (Claude Opus + Codex): 0 P0 / 0 P1; one P2 (`tracking-[var(--letter-spacing-tightest)]` token swap) applied in-PR; other P2/P3 deferred (new utility class out of scope; pre-existing parity-test observation)
```
## Screenshots or Recordings
Manual screenshot to be attached after PR open — the visible change is the heading copy ("今天我们做点什么?" / "What should we work on?") plus the slightly heavier medium-weight 28/130 display heading and the wider heading-to-composer gap. The composer, workspace chip, and overall layout are byte-for-byte unchanged from production.
## Checklist
- [x] Human review status is stated above as pending, approved, or not required
- [x] I linked the related issue, or stated why there is no issue
- [x] This PR has type, primary area, and priority labels, or I requested maintainer labeling
- [x] I described the review focus and any meaningful risks
- [x] I listed the relevant verification steps and the key result for each
- [x] I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
- [x] I manually checked visible UI or copy changes when needed, with screenshots or recordings
- [x] I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes
- [x] I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
- [x] I reviewed the final diff for unrelated changes and suspicious dependency changes
- [x] I am targeting `dev`, and my PR title and commit messages use Conventional Commits in English
Summary
Delete the dead
packages/app/src/pages/home.tsx(139 lines: Logo + server picker + recent projects + empty state) and replaceRoute path="/"with aHomeRedirectRoutethat resolves the first registered project at render time and<Navigate>s to/<base64>/session. Drop two orphan i18n keys (home.empty.title/home.empty.description); keephome.recentProjects— still used bydialog-select-directory.tsx:339.4 files changed, +16 / -146.
Why
The
/home page has been dead code for a while: ElectronwebContentspersists the last URL, and the backend defaults the workspace to~/PawWork(opencode/src/server/instance/middleware.ts:52,64). Every boot opens directly into the session route for the resolved path, bypassing/. Users only ever see the session-less landing rendered byNewSessionView— not this page.W5 collapses the two homes into one surface. Slice 1 of 3 for #603 removes the dead one. PR2 will strip the skill-card shortcuts; PR3 will rewrite
NewSessionViewas the W5 hero.Full design + 3-slice inventory: issue comment 4460021650.
Related Issue
Refs #603.
Human Review Status
Pending. A human should make the final merge decision after reviewing the diff and verification evidence below.
Review Focus
HomeRedirectRoutecorrectness: blank-div fallback covers the one-framelayout.projects.list()hydration window so users see no flash of old content if a stale URL or programmatic navigation hits/.<Navigate>only side-effects on mount.list()[0]is the deterministic redirect target — no last-active persistence. On multi-project setups the redirect lands on whichever project sorts first. Acceptable per design comment 4460021650; future work could add last-active persistence.app.tsx:useLayout(already a sibling ofLayoutProvider),base64Encode(already used bylocal.tsx,notification.tsx),createMemo+Show(already imported fromsolid-js).Risk Notes
Low. The deleted file was already unreachable in normal launch flow. The new redirect protects against the edge case of a stale
webContentsURL pointing to/after a future refactor that breaks the persistence chain.home.recentProjectsis preserved becausedialog-select-directory.tsx:339consumes it.No platform-specific risk (macOS / Windows). No packaging / updater / signing / permissions changes. No new dependencies.
How To Verify
Electron manual check was skipped because PR1 has no visible UI change in the normal launch flow — users land directly on
/<base64>/sessionviawebContentsURL persistence; the/redirect only fires if a stale URL or programmatic navigation hits root. Reviewer can verify locally:bun run dev:desktop, open devtools, runwindow.location.href = "/", observe redirect to/<base64>/sessionwithout flash.Screenshots or Recordings
Not applicable — no visible UI change in the normal launch flow. The dead
/page is removed; the only user-visible difference is "no flash of old home content if/is hit", which is invisible to most users.Checklist
dev, and my PR title and commit messages use Conventional Commits in EnglishSummary by CodeRabbit
New Features
Tests