Skip to main content

SPA Guard

A family of packages for resilient single-page applications with automatic retry, cache busting, and error reporting.

What is SPA Guard?

SPA Guard handles the "white screen of death" that occurs when your SPA's JavaScript chunks fail to load — whether from network issues, deployment cache invalidation, CDN problems, or static asset 404s. It automatically retries loading, shows user-friendly fallback UI, and reports errors via beacons.

Package Family

The spa-guard functionality is split into 7 separate packages, each with a focused responsibility:

PackageDescriptionPeer Dependencies
@ovineko/spa-guardCore runtime, error handling, schema, i18nNone
@ovineko/spa-guard-reactReact hooks, components, error boundariesreact@^19
@ovineko/spa-guard-react-routerReact Router v7 error boundary integrationreact@^19, react-router@^7
@ovineko/spa-guard-viteVite plugin (injects runtime script at build time)vite@^8||^7
@ovineko/spa-guard-nodeServer-side HTML cache with ETag/304, pre-compression, i18nparse5@^8
@ovineko/spa-guard-fastifyFastify beacon endpoint plugin and HTML cache handlerfastify@^5||^4
@ovineko/spa-guard-eslintESLint rules for enforcing spa-guard patternseslint@^9||^10

Architecture

Configuration flows from the Vite plugin at build time into the runtime:

Two-Level Retry Strategy

  1. Module-level retry (lazyWithRetry in spa-guard-react): Retries the individual import() call with configurable delays before the component fails.
  2. Page-level retry (retryOrchestrator in core): If module retry fails, schedules a full page reload with cache busting.

Retry State Machine

The orchestrator maintains an explicit phase:

  • idle — no retry in progress
  • scheduled — a reload has been scheduled; concurrent triggers are deduplicated
  • fallback — retries exhausted, fallback UI is shown; further triggers are ignored

Quick Start

1. Install packages

pnpm add @ovineko/spa-guard @ovineko/spa-guard-react
pnpm add -D @ovineko/spa-guard-vite

2. Add the Vite plugin

import { spaGuardVitePlugin } from "@ovineko/spa-guard-vite";
import { defineConfig } from "vite";

export default defineConfig({
plugins: [spaGuardVitePlugin()],
});

3. Use lazyWithRetry in your React app

import { Suspense } from "react";
import { lazyWithRetry } from "@ovineko/spa-guard-react";

const LazyHome = lazyWithRetry(() => import("./pages/Home"));

export function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyHome />
</Suspense>
);
}

4. Call recommendedSetup

import { recommendedSetup } from "@ovineko/spa-guard/runtime";

const cleanup = recommendedSetup();

See individual package pages for detailed API documentation and configuration options.