Skip to content

refactor(phase0): devices, manual apps, focus editor and changelog become shells - #197

Closed
adamXbot wants to merge 1 commit into
mainfrom
feat/phase0-batch2
Closed

refactor(phase0): devices, manual apps, focus editor and changelog become shells#197
adamXbot wants to merge 1 commit into
mainfrom
feat/phase0-batch2

Conversation

@adamXbot

Copy link
Copy Markdown
Collaborator

What

Batch 2 of Rust-core Phase 011 of 35 pages converted. These four shared exactly two server concerns, and both now resolve through the API.

Flag gates. resolveFlagFromDb(key) !== "on" → notFound() becomes RequireFlagGate, reading the resolved value from GET /api/feature-flags (flags[].currentValue — the same resolver output, not a re-implementation). Two details worth review attention:

  • It fails closed: a failed flag read renders the 404, not the page. These gates hide surfaces that shouldn't exist for an install, so "couldn't tell" must not fall open.
  • notFound() is thrown during render from state, not from the effect — the only way it works in a client component.

Initial data. Every list already had an exact API twin, so no new endpoints were needed:

Page Source Note
settings/devices /api/devices already includes appCount; DevicesView already fetched it in refresh()
dashboard/manual-apps /api/manual-apps already returned the exact { apps, sources } pair the page assembled by hand
settings/focus /api/focus already returned all six fields; new FocusEditLoader maps them
/changelog /api/apps filter dropdown

FocusEditLoader holds the form back until the fetch lands — FocusEditForm stages edits from its initial props, so mounting with placeholders then swapping would either be ignored or clobber user input.

The initialX props stay optional on the three views so their Storybook stories keep seeding fixtures (there the mount fetch fails and the seeded state stands).

Verification

  • By hand, where no e2e covers it: both gated pages render with their data through the gate; the manual-app form still defaults to Safari web app (sources[0] — unchanged, since both create paths reset from live sources and the deep-link path's fallback was already web_clip); flipping flag.page.manual_apps off renders the real 404 page.
  • Gate: tsc clean · biome clean · unit 462 pass / 0 fail · full Playwright 46 passed · visual net 13/13 pixel-identical against pre-conversion baselines captured via stash.

Next

Batch 3 takes the pages needing small new read endpoints (stats, privacy map, shortlist, review-recommendations), then the big three (dashboard, app detail, apps grid), with the layout/CSP batch last and coming to you for sign-off.

🤖 Generated with Claude Code

…come shells

Batch 2 of the Rust-core Phase 0 page conversions (11/35 done). These
four pages shared two server concerns, and both now come from the API:

- Flag gates. `resolveFlagFromDb(key) !== "on" → notFound()` becomes
  RequireFlagGate, which reads the resolved value from
  GET /api/feature-flags (the `flags[].currentValue` field — the same
  resolver output). It fails CLOSED: a failed flag read renders the 404
  rather than the page, because these gates hide surfaces that
  shouldn't exist for the install. notFound() is thrown during render
  (not from the effect), which is the only way it works client-side.
- Initial data. Every one of these lists already had an exact API twin,
  so no new endpoints were needed:
    devices      → /api/devices (already includes appCount, and
                   DevicesView already fetched it in refresh())
    manual apps  → /api/manual-apps (already returned the exact
                   { apps, sources } pair the page assembled by hand)
    focus editor → /api/focus (already returned all six fields; the
                   new FocusEditLoader maps them and holds the form
                   back until they land, since the form stages edits
                   from its initial props)
    changelog    → /api/apps for the filter dropdown

The `initialX` props stay optional on DevicesView / ManualAppsView /
UniversalChangelogView so their Storybook stories keep seeding
fixtures; in Storybook the mount fetch simply fails and the seeded
state stands.

Verified by hand where no e2e covers it: both gated pages render with
their data through the gate, the manual-app form still defaults to
Safari web app (sources[0], unchanged — both create paths reset from
live sources), and flipping flag.page.manual_apps off renders the real
404 page.

Gate: tsc clean; biome clean; unit 462 pass / 0 fail; full Playwright
46 passed; visual net 13/13 pixel-identical against pre-conversion
baselines captured via stash.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@adamXbot

Copy link
Copy Markdown
Collaborator Author

Superseded by #199, which consolidates Phase 0 batches 2–6 into a single PR (32 of 35 pages). This branch's commits are all contained in that one — closing to avoid a partial merge landing ahead of it.

@adamXbot adamXbot closed this Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant