# Runbook: SSR Outage — Inertia Server-Side Rendering Failure

## Trigger

- Deploy-time SSR health gate (Step 14b in `deploy.sh`) returns failures.
- Scheduled SSR health monitor (`ssr-health-check`) logs `critical` and sets `ssr_health_failures` Cache key.
- `/health` endpoint reports SSR degraded.
- Crawlers report blank pages; Core Web Vitals show zero LCP from server HTML.

## Symptoms

- Marketing pages (`/`, `/features`, `/pricing`, `/recover`, etc.) return HTTP 200 but with an empty `<div id="app">` — no `<h1>`, no rendered content in the page source.
- Googlebot / other crawlers see the blank shell; SEO rankings drop within days.
- SSR monitor `Cache::get('ssr_health_failures')` returns non-null.
- Application log contains `SEO2-012: SSR health monitor detected failures` at `critical` level.
- The regular Inertia app still works for logged-in users (client-side hydration succeeds), masking the issue from manual QA.

## Diagnosis

### 1. Confirm SSR is the issue

```bash
curl -s -A "Googlebot/2.1" https://rankwizai.com/ | grep -c '<h1'
# Returns 0 → SSR is broken; returns >0 → SSR is working
```

### 2. Check the Inertia SSR server process

```bash
# Is the SSR Node process running?
ps aux | grep 'node.*artisan inertia:start-ssr'

# Is it listening on the configured port?
ss -tlnp | grep 13714   # default Inertia SSR port
```

### 3. Check SSR port configuration

```bash
grep INERTIA_SSR_PORT .env          # should be 13714 (or the value in config/inertia.php)
grep INERTIA_SSR_ENABLED .env       # must be true in production
```

### 4. Check SSR server logs

```bash
# Supervisor log for the SSR process
sudo tail -f /var/log/supervisor/rankwizai-ssr.log

# Or application log
tail -100 storage/logs/laravel.log | grep -i ssr
```

### 5. Test SSR port directly

```bash
curl -sf http://localhost:13714/  # should return Inertia SSR health response
```

### 6. Check the PHP-FPM / proxy configuration

If SSR is running but pages still render empty, the issue may be that PHP cannot reach the SSR server (firewall, wrong port, proxy).

```bash
# From the PHP host, test connectivity to SSR port
curl -sf http://127.0.0.1:13714/
```

## Resolution

### A. SSR process crashed or never started

```bash
# Restart via supervisor (if configured)
sudo supervisorctl restart rankwizai-ssr

# Or start manually
cd /path/to/rankwizai
php artisan inertia:start-ssr
```

### B. SSR build is outdated (stale JS bundle)

The SSR bundle (`bootstrap/ssr/ssr.js`) must be rebuilt after any frontend change:

```bash
npm run build
sudo supervisorctl restart rankwizai-ssr
```

### C. INERTIA_SSR_ENABLED is false or not set

```bash
# In .env:
INERTIA_SSR_ENABLED=true
INERTIA_SSR_URL=http://127.0.0.1:13714

# Clear config cache and restart
php artisan config:cache
sudo supervisorctl restart rankwizai-ssr
```

### D. Port conflict

```bash
# Find what is using port 13714
lsof -i :13714

# Kill the conflicting process and restart SSR
sudo supervisorctl restart rankwizai-ssr
```

### E. Node.js not found or wrong version

```bash
node --version    # must be ≥18 (same as the Vite build Node version)
which node

# If wrong path, update supervisor config with the full node binary path:
# command=/path/to/node /path/to/rankwizai/artisan inertia:start-ssr
```

## Escalation

If SSR cannot be restored within 15 minutes:

1. Set `INERTIA_SSR_ENABLED=false` and `php artisan config:cache` + `supervisorctl restart rankwizai-ssr`.
   - This disables SSR. Pages will render client-side only. Googlebot sees an empty shell but the application stays functional for users.
   - Log the incident as a SEO impact event.

2. Re-enable and fix SSR before the next crawl cycle (typically 24–48 hours).

3. After SSR is restored, verify with:
```bash
curl -s https://rankwizai.com/ | grep -c '<h1'   # must be > 0
curl -s https://rankwizai.com/features | grep -c '<h1'
curl -s https://rankwizai.com/pricing | grep -c '<h1'
curl -s https://rankwizai.com/recover | grep -c '<h1'
```
