
Your single-page application returns 200 OK. The HTML shell loads. But the screen is blank, the JavaScript bundle failed to execute, and every user sees a white page.
Traditional uptime monitoring says the site is up. Your users say it is broken.
SPAs built with React, Vue, Angular, or Next.js break in ways that status-code checks cannot detect. The server responds successfully because the server's job is just to deliver an HTML file and some JavaScript. Whether that JavaScript actually renders a working UI is a different question entirely.
This guide explains why SPA monitoring needs a different approach and how to set up checks that catch the failures your users actually experience.
Why SPAs Break Differently
In a traditional server-rendered application, the server builds the full HTML page. If the server fails, the response is a 500 error. Monitoring catches it immediately.
In a SPA:
- Server sends a minimal HTML shell (almost always 200 OK)
- Browser downloads JavaScript bundles
- JavaScript executes and renders the UI
- UI makes API calls to fetch data
- Data renders into the page
Failure can happen at any step after 1, and step 1 still returns 200. This means:
- Bundle download fails — CDN issue, cache invalidation problem, or deployment mismatch. Status: 200. Page: blank.
- JavaScript execution error — Runtime exception, missing polyfill, browser incompatibility. Status: 200. Page: white screen or error boundary.
- Hydration failure — SSR/SSG frameworks like Next.js can deliver HTML that fails to hydrate client-side. Status: 200. Page: static but non-interactive.
- API dependency fails — The shell loads but data endpoints return errors. Status: 200. Page: empty states or broken layouts.
- Auth token expired — User session invalid, redirect loop, or infinite loading spinner. Status: 200. Page: unusable.
A monitoring tool that only checks HTTP status codes will report "up" for all of these.
What to Monitor in a SPA
1) Content Validation (Not Just Status Code)
The single most important change: validate that the response body contains expected content.
For a SPA, check that the rendered page includes:
- A known text string that only appears when the app renders successfully (e.g., your app name in the navigation, a specific heading, or a data-testid attribute)
- Absence of known error indicators (e.g., "Something went wrong", "ChunkLoadError", blank body)
This catches the majority of SPA-specific failures: blank pages, broken bundles, and render errors.
2) Key API Endpoints
SPAs depend on APIs for data. Monitor the critical ones directly:
- Authentication endpoint (login, token refresh)
- Primary data endpoint (dashboard data, user profile, product listing)
- Health or status endpoint if available
If the API is down, the SPA shell loads but the app is functionally broken. Monitoring both the page and its API dependencies gives you full coverage.
3) JavaScript Bundle Availability
Your SPA's JavaScript bundles are usually served from a CDN or static host. If they are unavailable, the app cannot render.
Monitor:
- The main bundle URL (check that it returns 200 with correct Content-Type)
- Critical chunk URLs if you use code splitting
After deployments, old chunk URLs may 404 if users have cached HTML pointing to previous bundle hashes. This is a common SPA failure mode.
4) Client-Side Route Checks
SPAs use client-side routing. A URL like /dashboard or /settings does not correspond to a server-side route — the server returns the same HTML shell for every path.
This means:
- A broken route handler returns 200 with an empty or error view
- Navigation between routes can fail without any server-side signal
- Deep links can break after deployments if route configuration changes
Monitor key routes by requesting them and validating that route-specific content appears in the response. For SSR/SSG apps (Next.js, Nuxt), the server pre-renders route content — validate that the expected content is present.
5) Authentication Flows
SPAs handle authentication client-side. Monitor:
- Login page renders correctly
- Token refresh endpoint responds
- Protected routes redirect properly when unauthenticated
Auth failures in SPAs often manifest as infinite redirect loops or perpetual loading spinners — both invisible to status-code-only checks.
SPA Failure Modes and Detection
| Failure Mode | What Users See | Detection Method |
|---|---|---|
| Bundle download failure | Blank white page | Content validation (expected text absent) |
| JavaScript runtime error | White screen or error boundary | Content validation + error string detection |
| Hydration failure (SSR) | Static page, no interactivity | Content validation for dynamic elements |
| API dependency down | Empty data, broken layouts | Direct API endpoint monitoring |
| CDN outage | Slow or failed asset loading | Bundle URL monitoring + response time |
| Stale chunk after deploy | ChunkLoadError for some users | Monitor versioned chunk URLs post-deploy |
| Auth token expiry | Redirect loops, login failures | Auth endpoint monitoring + content validation |
| CORS misconfiguration | API calls blocked, data missing | API endpoint checks from external origin |
| Environment variable missing | App renders with broken config | Content validation for config-dependent UI |
Framework-Specific Tips
React (Create React App, Vite)
- Check for the root element content: if
<div id="root"></div>is empty, the app failed to mount - Monitor for React error boundary messages in production builds
- After deployments, verify that hashed bundle URLs resolve
Next.js / Remix (SSR/SSG)
- Pre-rendered pages should contain full HTML content — validate it
- Monitor both the page response and the
/_next/data/API routes - Check that ISR (Incremental Static Regeneration) pages are fresh
- Verify middleware redirects work correctly after deployment
Vue / Nuxt
- Check for the
<div id="app">mount point containing rendered content - For Nuxt, validate SSR output includes route-specific data
- Monitor
/_nuxt/asset paths after deployments
Angular
- Verify the
<app-root>element contains rendered content - Monitor lazy-loaded module chunk availability
- Check that service worker updates do not serve stale shells
Practical Setup: 15-Minute Version
For immediate coverage of a SPA:
- Homepage check with content validation — Verify your app name or a known UI element appears in the response body. Run every minute from multiple regions.
- Critical API endpoint check — Monitor your primary data API with auth headers. Validate response shape.
- Auth endpoint check — Verify login or token refresh returns expected response.
- Post-deploy bundle check — After each deployment, confirm the new main bundle URL resolves.
- Response time alert — Set a threshold at 2-3x your normal p95. SPAs with slow bundles degrade UX before they fully break.
This catches blank pages, API outages, auth failures, and broken deployments.
How Webalert Helps
Webalert catches the SPA failures that status-code-only tools miss:
- Content validation — Check that response bodies contain expected text, catching blank pages and render failures
- HTTP/HTTPS checks with custom headers for authenticated routes
- Response time monitoring — Detect slow bundle loading and API latency
- Multi-region checks — Catch CDN and routing issues that affect specific geographies
- Heartbeat monitoring — Verify build and deployment pipelines complete
- Multi-channel alerts — Email, SMS, Slack, Discord, Teams, webhooks
- Status pages — Communicate frontend incidents clearly to users
See features and pricing for details.
Summary
- SPAs return 200 OK even when completely broken — status code checks are insufficient.
- Use content validation to verify the app actually renders expected UI.
- Monitor critical API endpoints that the SPA depends on for data.
- Check JavaScript bundle availability, especially after deployments.
- Validate key client-side routes, not just the homepage.
- Monitor authentication flows for redirect loops and token failures.
- Start with 4-5 targeted checks: homepage with content validation, primary API, auth endpoint, bundle URL, and response time threshold.
The best SPA monitoring verifies what users see, not what the server sends.