Skip to content

Frontend Svelte Implementation Plan

Goal

Create a second frontend in tracker-frontend-svelte/ that can be developed in parallel with the current React app, using:

  • Svelte 5
  • TailwindCSS
  • daisyUI
  • multiple curated themes
  • Docker Compose for local development

The target is not a quick rewrite. The goal is a controlled migration path that preserves the backend API, keeps the current app available, and makes it possible to cut over route by route.

Code Style Rules

The Svelte frontend should be written for Svelte 5, not Svelte 4 legacy syntax.

That means:

  • use Svelte 5 runes and current component patterns
  • avoid legacy Svelte 4 reactive syntax unless there is a very specific reason
  • keep components small and composable
  • extract reusable UI and state logic into modules instead of duplicating it
  • prefer feature-level decomposition over large monolithic page files

The migration should intentionally avoid huge single-file components. Complex screens should be split into manageable modules, with shared pieces promoted into src/lib/components/ or src/lib/utils/ when they are reused more than once.

Use a separate folder instead of mixing React and Svelte inside the same frontend package.

Suggested layout:

tracker-frontend-svelte/
├── build/
│   └── dev/
├── public/
├── src/
│   ├── lib/
│   │   ├── api/
│   │   ├── components/
│   │   ├── theme/
│   │   └── utils/
│   ├── routes/
│   ├── app.css
│   ├── app.html
│   └── main.ts
├── package.json
├── tailwind.config.ts
├── vite.config.ts
└── svelte.config.js

Keep the Svelte app self-contained so it can be:

  • started independently in development
  • built independently in CI
  • deployed independently until parity is reached

Docker Plan

Add a new Compose service for the Svelte frontend alongside the existing React service.

Recommended dev service shape:

  • build context: ./tracker-frontend-svelte
  • Dockerfile: build/dev/Dockerfile
  • port mapping: 3101:3000 or similar
  • volume mount: ./tracker-frontend-svelte:/app
  • env file: ./tracker-frontend-svelte/.env
  • dependency on the API dev service, not on the React frontend

This keeps the development workflow consistent with the current frontend:

  • source edits remain hot-reloaded
  • API requests still go through the local backend
  • the new app can be tested without replacing the old one

Use a second production image only after the Svelte app is feature-complete enough to be promoted.

Theme System

This should be a curated daisyUI theme setup, not a single dark/light toggle.

Start with a small, stable set of themes:

  • light
  • dark
  • corporate
  • retro

If the team wants more variety after the first pass, the next sensible additions are:

  • dim
  • night
  • tokyonight
  • nord
  • norddark

The theme system should have three layers:

  1. tailwind.config.ts defines the allowed daisyUI themes.
  2. app.html applies the initial theme before the app renders.
  3. A Svelte theme selector updates the active theme and persists it in localStorage.

That gives you:

  • no flash of the wrong theme on first paint
  • browser color-scheme alignment
  • a single source of truth for supported themes
  • a path to expand styling without redesigning the whole app

Theme Files

Use a small theme module similar to the Cortex pattern.

Suggested files:

  • src/lib/theme/index.ts
  • src/lib/theme/themes.ts
  • src/lib/components/ThemeSelector.svelte

Responsibilities:

  • resolve the current theme from localStorage
  • fall back to the system theme when nothing is stored
  • set document.documentElement.dataset.theme
  • set document.documentElement.style.colorScheme
  • expose the curated theme list to the selector

The selector should live in the app shell so every page gets the same theme controls.

Startup Behavior

Implement theme bootstrapping in app.html so the page starts with the right theme before Svelte mounts.

The boot script should:

  • read the stored theme key
  • validate it against the supported theme list
  • fall back to prefers-color-scheme
  • set the root data-theme
  • set the browser color-scheme

This matters more in Svelte than it might seem, because daisyUI themes affect a lot of surface styling. If the initial theme is applied late, the user will see a jarring flash.

Svelte 5 Setup

The first Svelte milestone should be thin and boring:

  • Svelte 5 project scaffolding
  • Vite dev server
  • Tailwind and daisyUI wired together
  • app shell layout
  • theme selector
  • API client wrapper
  • auth/session bootstrap

Avoid porting large feature pages before the shell is stable.

UI Migration Order

The UI should move in this order:

  1. app shell
  2. theme selector
  3. buttons, inputs, selects, textareas
  4. modal and drawer primitives
  5. cards, tabs, badges, alerts
  6. table and pagination primitives
  7. login and auth flows
  8. dashboard and tracker list pages
  9. location CRUD and import flows
  10. campaign management
  11. map-heavy screens

This order front-loads the shared design system and reduces duplicated styling work.

DRY Structure Guidance

Keep the new app DRY by design:

  • shared form controls should be reused across login, locations, campaigns, and reports
  • map controls should be separate from map page containers
  • modal shells should be shared instead of reimplemented per feature
  • table layout and pagination should be centralized
  • theme logic should live in one module and one selector component

If a page starts to grow large, split it by responsibility rather than keeping everything in one component. Good boundaries are:

  • page container
  • data loading
  • state and derived values
  • presentational components
  • feature-specific controls
  • API adapter or store logic

That keeps the Svelte app maintainable while the rewrite is still in flight.

Custom Component Replacement Priority

Replace the most reusable custom React components first.

Good first candidates:

  • layout shell
  • top navigation
  • sidebar
  • theme switcher
  • button variants
  • form fields
  • modal shells
  • dropdown menus
  • table wrappers
  • pagination controls

These components are the best place to introduce daisyUI because they appear across many routes.

Lower priority components:

  • map overlays
  • tracker history visualisations
  • complex batch-action dialogs
  • Leaflet custom controls
  • route-specific dashboards with dense filtering logic

Those should be ported after the shared primitives are stable.

Leaflet Plan

Keep Leaflet.

The migration should replace React wrappers, not the map library itself. The Svelte version should use:

  • direct Leaflet integration where practical
  • Svelte lifecycle hooks for map setup and teardown
  • small wrapper components for reusable map UI

The main risk is not Leaflet itself. The risk is rebuilding the current interaction model cleanly without leaking DOM and state issues across route changes and modal opens.

Suggested Phase Breakdown

Phase 1: Scaffold

  • create tracker-frontend-svelte/
  • add the Svelte build and dev container
  • add Tailwind and daisyUI
  • add the theme system
  • add the app shell

Phase 2: Shared Foundation

  • implement API client and auth/session handling
  • port the theme selector
  • port the top-level layout components
  • establish a reusable component library for form and layout primitives

Phase 3: Core Routes

  • login
  • dashboard
  • trackers
  • locations
  • reports

Phase 4: Complex Features

  • campaigns
  • Leaflet-driven maps
  • editable maps
  • import flows

Phase 5: Cutover

  • compare parity route by route
  • remove dead React-only code paths
  • switch deployment traffic when the Svelte app is stable

Risks To Track

  • theme palette drift if the allowed theme list is not centralized
  • extra UI churn if custom components are rebuilt before the theme system is stable
  • Leaflet DOM sizing issues during mount and unmount
  • duplicated API logic if the new app diverges from the existing request layer
  • scope creep if the visual refresh becomes a redesign

Practical Recommendation

If the team wants better styling flexibility, the best combination is:

  • Svelte 5 for the new frontend
  • TailwindCSS for utility-level layout
  • daisyUI for component primitives
  • a curated theme switcher from day one

That gives you more visual options without turning the migration into a purely bespoke CSS project.