Svelte 5 Migration Assessment
Short Answer
Yes, the frontend could be migrated to Svelte 5, but it is a framework rewrite rather than a drop-in upgrade. The current app is a React application built on React Router, TanStack Query, React Hook Form, React Hot Toast, React Error Boundary, and React Leaflet. Those pieces do not transfer directly to Svelte, so the bulk of the work is replacing the component tree, routing, and browser state management.
If you want to reduce risk, the cleanest shape is a side-by-side app in a separate folder such as tracker-frontend-svelte/ or frontend-svelte/, with its own Vite/Svelte build and its own deployment path until parity is reached.
Because the current React frontend already runs through Docker Compose, the Svelte app should follow the same pattern: a dedicated dev container for local development and a separate production image once the new app is stable.
The Svelte app should be built for Svelte 5 only. Do not design the migration around Svelte 4 legacy syntax. Keep the codebase modular, DRY, and split into manageable components and modules instead of large monolithic page files.
What The Repo Looks Like Today
The frontend is not tiny. Under tracker-frontend/src, the codebase currently contains 56 *.tsx files and 32 *.ts files, plus tests and static assets. The main entry points are:
tracker-frontend/src/main.tsxtracker-frontend/src/App.tsxtracker-frontend/src/hooks/useAuth.tstracker-frontend/src/api/client.ts
The app already has several distinct feature areas:
- authentication and session restoration
- dashboard filtering, pagination, and tracker history
- tracker map visualisation with Leaflet and marker clustering
- location CRUD and import flows
- campaign management and batch actions
- reports and charts
What Can Be Reused
Several parts of the current frontend can survive the migration with little or no change:
- backend API contracts and OpenAPI-driven type generation
- most
src/api/*request logic, if you keep the same REST endpoints - shared domain types in
src/types/* - TailwindCSS design tokens and utility classes
- Docker, nginx, and the existing deployment topology
- pure TypeScript utility functions that do not depend on React
What Must Be Rewritten
These parts are tightly coupled to React and would need replacement:
- routing in
react-router-dom - React context providers and hooks such as
useAuth - TanStack Query hooks and cache wiring
- React Hook Form based forms
- all React component trees in
*.tsx - React-specific integrations such as
react-leaflet - toast/error boundary integrations that assume React component composition
The map stack deserves special attention. Leaflet itself can stay, but the current integration uses React wrappers and React lifecycle hooks heavily. Expect to rebuild the map components rather than translate them mechanically.
That said, Leaflet is still a good fit for Svelte. Leaflet is just a JavaScript mapping library for mobile-friendly interactive maps, so the migration is mainly about replacing the React wrapper layer with Svelte components and lifecycle hooks, not replacing the map engine itself.
UI Strategy
Because the team already uses TailwindCSS, bringing in daisyUI is a sensible way to speed up the visual rewrite.
The main value is in standardizing the common shell and form patterns:
- buttons
- inputs
- tabs
- cards
- modals
- drawers
- tables
That lets you convert many custom presentational components into simpler, more consistent UI primitives. It will not eliminate custom work for the map screens, dashboard filters, or dense data tables, but it should reduce the amount of bespoke CSS and improve design consistency.
daisyUI is designed to sit on top of Tailwind as a plugin, so it fits the current styling direction well.
Theme Strategy
This migration should include a real daisyUI theme system, not just a light/dark switch.
The theme switcher pattern from Cortex is a good fit here because it already solves the important parts:
- persist the selected theme in
localStorage - apply
data-themeon the root element - update
color-schemeso browsers render built-in controls correctly - fall back to the system theme when nothing is stored
- keep the selectable theme list explicit instead of letting every page invent its own styling rules
The implementation should mirror that shape in the new Svelte app:
- a small theme utility module
- an early boot script in the HTML shell to avoid theme flash
- a reusable theme selector in the app shell
- a fixed list of supported themes, with room to expand later
That would make the Svelte rewrite materially better than the current app from a styling perspective, because it gives you a controlled design system instead of a single dark-mode toggle.
Recommended Migration Shape
The lowest-risk path is a side-by-side migration:
- Keep the backend API unchanged.
- Stand up a new Svelte 5 frontend in a separate folder, for example
tracker-frontend-svelte/. - Add a matching Docker Compose service for the new app so local development still works through containers.
- Port shared primitives first: API client, auth/session logic, layout shell, theme handling, and Tailwind/daisyUI setup.
- Add the theme selector and boot-time theme application before most of the page work, so styling decisions stay consistent from the start.
- Port the highest-value routes next, starting with the login flow and dashboard.
- Move the map-heavy and form-heavy screens after the framework foundation is stable.
- Retire the React app only after the Svelte app reaches feature parity.
Trying to mix React and Svelte inside the same component tree is usually a dead end. It adds complexity without reducing the amount of rewrite work.
Effort Estimate
These numbers assume one experienced engineer and a requirement for functional parity with the current app.
| Phase | Scope | Estimate |
|---|---|---|
| Discovery spike | Validate Svelte 5, router, auth, map strategy, daisyUI fit, and container approach | 2 to 4 days |
| Foundation | Vite + Svelte 5 setup, routing, auth shell, theme system, API client, Tailwind/daisyUI, Docker dev image | 1 to 2 weeks |
| Core pages | Dashboard, trackers, locations, reports, campaigns | 2 to 4 weeks |
| Maps and rich interactions | Leaflet, clustering, editable maps, modal flows | 1 to 2 weeks |
| Test migration and hardening | Unit tests, E2E gaps, bug fixing, release validation | 1 to 2 weeks |
Practical total:
- Proof of concept: 1 week or less
- Production-ready migration with parity: 5 to 10 weeks
- Safer estimate if requirements are still moving: 8 to 12 weeks
If two engineers can work in parallel, the calendar time can drop, but only if the work is split cleanly by route or feature area.
Main Risks
- React-specific libraries may not have a one-to-one Svelte replacement.
- The current auth/session flow is stateful and browser-storage heavy, so it needs careful rework.
- Map features are the most likely source of regressions, especially around Leaflet wrappers and DOM sizing.
- A UI refresh can expand scope quickly if there is no shared component system early.
- Theme management can add complexity if the theme list, palette, and meta colors are not centralized.
- Docker packaging for the new app adds setup work, but it is small compared with the framework rewrite itself.
- Test coverage will need to be rebuilt around Svelte components and Svelte-aware utilities.
- A framework rewrite can easily hide product scope creep, so the migration plan needs a hard feature-parity boundary.
Decision Check
Svelte 5 is a reasonable target if the goal is to reduce long-term UI complexity and you are willing to pay for a rewrite.
It is not a good choice if the goal is a cheap framework upgrade. In that case, improving the existing React app will be much faster.
If the team is already planning a visual refresh, Svelte 5 plus Tailwind plus daisyUI is a good combination for the new app shell and standard pages. It still does not remove the need to design the map-heavy screens carefully, but it should make the overall UI work more tractable.
The theme switcher is the piece that makes daisyUI especially worthwhile here. If you carry over the Cortex-style theme system, you can support multiple curated themes instead of hardcoding the app into one look and one dark mode.
Suggested Next Step
If you want, the next useful document would be a route-by-route migration plan that breaks the current frontend into:
- reusable code
- rewrite-required code
- risky integrations
- milestones for a staged cutover