Short answer: Yes.
The Adblock Compiler is currently a multi-page application (MPA) where each
public/*.html file is an independent page that triggers a full browser reload on
every navigation. Converting to a Single Page Application (SPA) would meaningfully
improve the user experience, developer experience, and long-term maintainability.
mindmap
root((public/))
index["index.html — Admin dashboard"]
compiler["compiler.html — Compiler UI"]
adminStorage["admin-storage.html — Storage admin"]
test["test.html — API tester"]
e2e["e2e-tests.html — E2E test runner"]
validation["validation-demo.html"]
websocket["websocket-test.html"]
Each page is isolated. Navigation between them triggers a full browser reload,
re-downloads shared CSS/JS, and discards all in-memory state (form inputs, results,
theme settings not yet flushed to localStorage).
In the current MPA, clicking "Compiler" from the dashboard causes the browser to:
- Send a new HTTP request
- Download and parse
compiler.html - Re-download shared CSS and JS modules
- Re-initialise theme, chart libraries, and event listeners
With a SPA, navigation is handled entirely in JavaScript — the URL changes, the current "page" component is swapped out, and the rest of the shell (navigation, theme, cached data) stays intact. Page transitions feel instant.
With an MPA, sharing data between pages requires localStorage, sessionStorage,
URL parameters, or a server round-trip. With a SPA, all views share the same
JavaScript heap:
compiler result → still in memory when navigating to "Test" page
theme selection → applied once, persisted in the Vue/Angular state
API health data → fetched once at app startup, reused everywhere
This eliminates redundant API calls and simplifies state management.
The current pages duplicate:
- Theme toggle HTML, CSS, and JS (repeated in every
.htmlfile) - Navigation markup and link styling
- Shared CSS variable declarations
- Loading spinner HTML patterns
A SPA consolidates these into reusable components that render once and are shared across all views. Changes to the navigation or theme toggle are made in one place.
Modern SPA frameworks paired with Vite automatically split the app bundle by route. Code for the "Admin Storage" page is never downloaded unless the user navigates there. This improves Time to Interactive (TTI) for all users.
The existing Vite configuration already supports this via @vitejs/plugin-vue — no additional tooling changes are required.
SPAs enable skeleton screens, optimistic updates, and progressive loading that are impossible with full-page reloads:
- Show the navigation shell instantly
- Stream in stats as they arrive from the API
- Display "Compiling…" inline without a blank white flash
Component-based SPAs are significantly easier to unit test:
- Each component can be rendered in isolation
- State changes are predictable and inspectable
- Mocking API calls is straightforward
- End-to-end tests navigate within the same page context (no cross-page coordination)
SPAs are the natural foundation for Progressive Web Apps (PWAs). Adding a service worker for offline support, app-shell caching, and push notifications is straightforward once the app is already an SPA.
The Vite build system already ships @vitejs/plugin-vue:
// vite.config.ts (excerpt)
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
export default defineConfig({
plugins: [vue(), vueJsx()],
// ...
});This means .vue Single-File Components can already be
imported and bundled without any additional tooling changes. Adding a new SPA
entry point requires only:
- A new
*.htmlentry invite.config.tsrollupOptions.input - A
main.tsthat mounts the Vue root - Route components for each current page
Add a new public/app.html entry that mounts a Vue 3 SPA alongside the
existing MPA pages. Users can opt in to the new SPA experience while the
existing pages remain untouched.
Migrate pages one at a time from static HTML into Vue route components:
- Home dashboard (
index.html→/) — stats, chart, health status - Compiler (
compiler.html→/compiler) — form, results, SSE streaming - Test (
test.html→/test) — API test runner - Admin Storage (
admin-storage.html→/admin) — storage management
Once all pages are ported and the SPA is stable, the legacy .html files can be
removed and the SPA entry can become the single index.html.
For this project, Vue 3 is the recommended choice:
| Criterion | Vue 3 | Angular |
|---|---|---|
| Learning curve | Low | High |
| Bundle size | Small | Large |
| TypeScript | Optional (excellent) | Required |
| Official router | ✅ Vue Router 4 | ✅ Angular Router |
| State management | ✅ Pinia (official) | ✅ Signals + RxJS |
| Vite integration | ✅ First-class | Partial |
| Cloudflare Workers | ✅ | ✅ |
Vue 3 balances a low learning curve, excellent TypeScript support, first-class Vite
integration, and an official router and state management library. The project's
existing Vite setup already has @vitejs/plugin-vue installed and active.
docs/VITE.md— Vite integration guide