Svelte 5 Admin Migration Assessment
Short Answer
Yes, tracker-admin can be migrated to Svelte 5 using the same side-by-side approach
already used for tracker-frontend → tracker-frontend-svelte. The difference this
time is that a working sibling app already exists: the theme system, app shell,
sidebar, API client, and auth/session logic don't need to be designed again, only
ported and re-pointed at tracker-admin's own navigation and pages. What's left is a
genuine framework rewrite of 12 in-scope route areas (of 14 total — the health
dashboard and service controller are unused and excluded, see "Not In Scope") and
roughly 22,000 lines of React, noticeably more than the frontend was.
The recommended shape is unchanged from the frontend migration: a new
tracker-admin-svelte/ folder, its own Vite/SvelteKit build, its own dev container,
running alongside the existing React admin panel until parity is reached.
What The Repo Looks Like Today
tracker-admin/src contains 31 page files, 51 component files, 16 hooks, and 14 API
modules — roughly 22,100 lines of TypeScript/TSX in total. Entry points:
tracker-admin/src/App.tsx— route table (react-router-domv6, all pages lazy-loaded)tracker-admin/src/hooks/useAuth.ts— auth contexttracker-admin/src/api/client.ts— axios instance, token refresh, session restoretracker-admin/src/components/layout/MainLayout.tsx— sidebar + mobile drawer shell
Route areas: Dashboard, Clients, Brands, Production Runs, Trackers, Locations, Images, Users, Health Dashboard, Tracker Status Heatmaps (analytics), Service Controller. Health Dashboard and Service Controller are not currently used and are out of scope for this migration — deprioritized indefinitely, not just deferred to a later phase. Five of these (clients, brands, production runs, trackers, locations) are near-identical List/Detail/Create/Edit CRUD quadruplets — the same shape repeated five times with different fields.
Two routes exist (/analytics/tracker-heatmaps, /service-controller) but are not
in the sidebar nav list (MainLayout.tsx:31-38 only has 8 items: Dashboard, Clients,
Brands, Production Runs, Trackers, Locations, Images, Users) — they're only reachable
by typing the URL directly. This matches confirmation that Health Dashboard and Service
Controller aren't in active use; no nav decision is needed since neither is being
ported for now (see "Not In Scope" below).
Stray craco.config.js and webpack.config.js files exist at the tracker-admin root
but appear to be dead leftovers — the app actually builds via vite.config.ts
(npm run build = tsc && vite build). Worth confirming they're unused before
treating them as migration input.
What Can Be Reused
Unlike the original frontend migration, this one starts with a second working example to copy from, not just a design sketch:
- the backend API contract — same FastAPI endpoints
tracker-frontend-sveltealready talks to for auth (/auth/login/json,/auth/refresh-cookie,/auth/logout,/users/me), and for the domains that overlap (locations, production runs) tracker-frontend-svelte's already-built, generic infrastructure:src/lib/api/client.ts,src/lib/state/auth.ts,src/lib/theme/*,src/lib/components/ThemeSelector.svelte,src/lib/utils/animatedDialog.svelte.ts— all confirmed to have no app-specific coupling during investigation, portable close to verbatimtracker-frontend-svelte's locations and campaign-management components (LocationEditorModal.svelte,LocationsImportModal.svelte,CampaignEditorModal.svelte,CampaignRow.svelte,TrackerCard.svelte/TrackerListRow.svelte,MoveTrackerModal.svelte,PasteSelectModal.svelte,CampaignDeleteModal.svelte) — these are prop-driven (typed data + callbacks, no direct global-state coupling beyondLocationEditorModal/LocationsImportModal's calls into$lib/api/locations.ts), so they're realistic to reuse directly once tracker-admin-svelte's own locations/production-runs pages exist, rather than rebuilding equivalent admin CRUD screens from scratch- Tailwind utility classes and pure TypeScript utilities that don't depend on React
(
src/utils/formatters.ts,src/utils/redirectUtils.ts) - Docker/nginx deployment topology, once/if this app is promoted past dev-only
What Must Be Rewritten
- routing in
react-router-dom→ SvelteKit file-based routing useAuthcontext + alluse*hooks insrc/hooks/(16 files, ~2,140 lines) → Svelte stores and derived state (same pattern already proven intracker-frontend-svelte/src/lib/state/auth.ts)- TanStack Query data-fetching/caching → plain
$state/$derived+ the sharedrequest<T>()wrapper (no query-cache library intracker-frontend-sveltetoday; decide during Foundation phase whether that's still fine at this app's scale) react-hook-form-based forms → native Svelte bindings- all 51
src/components/*+ 31src/pages/*— no direct mechanical translation @headlessui/reactprimitives (Dialog/Transition for the mobile sidebar drawer, modals) → daisyUI equivalents +AnimatedDialog(already used for every modal intracker-frontend-svelte)react-leaflet/leaflet-geosearchwrappers → direct Leaflet integration (same conclusion as the frontend migration: keep Leaflet itself, rebuild the wrapper layer)react-hot-toast→ the toast store already built fortracker-frontend-svelte($lib/state/toast.ts— referenced by its root+layout.svelte's<ToastHost />)
Not In Scope
Health Dashboard (/health) and Service Controller (/service-controller) are not
currently used and are excluded from this migration entirely, not just deferred to a
later phase. That also removes chart.js/react-chartjs-2 from the rewrite list for
now — Tracker Status Heatmaps is the only remaining chart-using page, and it can be
revisited alongside these two if/when any of them come back into use.
Effort Estimate
This app is bigger than the frontend was, and the CRUD repetition (5 parallel List/Detail/Create/Edit sets) is the strongest signal that a shared generic list/table/form scaffold would pay for itself here more than it did in the frontend migration, where each route was more distinct.
| Phase | Scope | Estimate |
|---|---|---|
| Scaffold + shared foundation | Port theme/app-shell/API-client/auth verbatim, admin nav, placeholder dashboard, dev container | 2 to 4 days |
| CRUD quadruplets | Clients, brands, production runs, trackers, locations (ideally via one shared scaffold, not five) | 3 to 5 weeks |
| Locations/campaigns reuse | Wire the already-built tracker-frontend-svelte location/campaign components into admin CRUD |
1 to 2 weeks |
| Singleton pages | Images gallery, Users, Tracker Heatmaps (Health Dashboard and Service Controller excluded — unused) | 1 to 2 weeks |
| Test migration and hardening | Rebuild coverage (tracker-admin currently has 1 test file), bug fixing, release validation | 1 to 2 weeks |
Practical total:
- Proof of concept (this pass — scaffold + shared foundation only): a few days
- Production-ready migration with parity (excluding Health Dashboard/Service Controller): 7 to 11 weeks
- Safer estimate if requirements are still moving: 10 to 14 weeks
Two engineers can parallelize by splitting along the CRUD-quadruplet boundary (one domain area each) once the shared scaffold exists, similar to the frontend's recommendation.
Main Risks
- The CRUD repetition is also a trap: building the first quadruplet (e.g. clients) without generalizing it will make the remaining four slower, not faster. Invest in a shared list/detail/form pattern before the second quadruplet.
- Chart.js integration (tracker heatmaps) is new territory for this codebase's Svelte side; validate the wrapper approach early, similar to how Leaflet needed its own spike in the original migration.
- Thin test coverage (one test file in the entire current app) means there's little regression safety net — most verification will be manual, route by route.
- Scope creep risk is higher here than it was for the frontend: an admin panel touches every entity in the system, so it's an easy place for "while we're rewriting this page" feature requests to creep in and blow the timeline.
Decision Check
This is a good target if the goal is a consistent design system (multi-theme daisyUI, shared modal/table primitives) across both the customer-facing app and the admin panel, and the team is willing to pay for a genuinely larger rewrite than the frontend was.
It is a poor target if the goal is a quick visual refresh — the existing React app already has a working (if plain) dark/light toggle, and a Svelte rewrite doesn't fix anything structurally broken in the current admin panel, it mainly buys design-system consistency with the already-migrated frontend and a smaller/simpler stack.
Given that tracker-frontend-svelte already proved out the app shell, theme system,
and several reusable feature components, the marginal cost of standing up
tracker-admin-svelte's foundation is now low — most of the risk and cost is
concentrated in the CRUD page volume and the two precedent-free feature areas, not in
re-deciding the framework/tooling questions the first migration already answered.
Suggested Next Step
See admin-svelte-implementation-plan.md for the concrete scaffold-first plan. After
the scaffold lands, the next useful document is a per-quadruplet CRUD scaffold design
(list/detail/form primitives shared across clients/brands/production-runs/trackers/
locations), since that decision shapes the cost of every subsequent page.