Skip to main content
Single-page applications (SPAs) can be challenging to debug because state changes, AJAX requests, and console errors happen dynamically. This recipe shows how to use bdg to systematically investigate SPA issues.

Scenario

You’re debugging a React TodoMVC app at https://demo.playwright.dev/todomvc that exhibits the following problems:
  • Console warnings appear when adding todos
  • Network requests fail intermittently
  • The app doesn’t update after certain actions
You need to correlate console messages with network activity and identify the root cause.

Workflow

1

Start session with network and console collection

Launch bdg and navigate to the app. Both network and console collectors are enabled by default.
bdg https://demo.playwright.dev/todomvc
Wait for the session to start. You’ll see confirmation that Chrome is running.
2

Monitor initial page load

Check what resources loaded and if there are any early console messages.
# View network requests from page load
bdg peek --network --last 20

# Check console for warnings or errors
bdg console
Expected output:
CONSOLE MESSAGES (current page only)

Errors: 0
Warnings: 0
Info/Debug: 2 messages (hidden by default)
If you see React warnings about deprecated APIs or missing keys, note them for later.
3

Interact with the app and watch for issues

Add a todo item using form interaction commands.
# Find the input field
bdg dom query ".new-todo"

# Fill and submit using Enter key (TodoMVC pattern)
bdg dom fill ".new-todo" "Buy groceries"
bdg dom pressKey ".new-todo" Enter
Expected output:
✓ Filled .new-todo with "Buy groceries"
✓ Network stability achieved after 850ms
4

Check for console errors after interaction

After adding the todo, check if new console messages appeared.
bdg console --list
Expected output:
[1] [warning] Warning: Each child in a list should have a unique "key" prop.
    Source: react-dom.development.js:86

[2] [log] Todo added: "Buy groceries"
The warning indicates React is re-rendering without proper keys. This could cause state issues.
5

Monitor network activity during state changes

Check if the app made API calls when you added the todo.
# Filter for XHR and Fetch requests
bdg network list --type XHR,Fetch --last 10

# Or use the API preset
bdg network list --preset api
Expected output:
NETWORK REQUESTS (last 10)

[0] POST /api/todos → 201 Created (125ms)
    Size: 456 B | Type: Fetch
If you see 4xx or 5xx errors, investigate headers and response bodies.
6

Inspect failed requests in detail

If you found failing network requests, get full details including headers and response body.
# Get request ID from network list
bdg network list --filter "status-code:>=400" --json | jq '.data.requests[0].requestId'

# View full request/response details
bdg details network <requestId>
Expected output:
{
  "url": "https://api.example.com/todos",
  "method": "POST",
  "status": 422,
  "responseBody": {
    "error": "Validation failed: title cannot be empty"
  }
}
7

Test edge cases systematically

Reproduce the issue by testing edge cases like empty inputs, special characters, and rapid actions.
# Test empty input
bdg dom fill ".new-todo" ""
bdg dom pressKey ".new-todo" Enter
bdg console

# Test special characters
bdg dom fill ".new-todo" "Test <script>alert('xss')</script>"
bdg dom pressKey ".new-todo" Enter
bdg console

# Test rapid additions
for i in {1..5}; do
  bdg dom fill ".new-todo" "Item $i"
  bdg dom pressKey ".new-todo" Enter
done
bdg console --list
8

Capture final state and export data

Stop the session to capture the final DOM snapshot and export network data.
# Stop session (captures DOM and accessibility tree)
bdg stop

# Export network traffic as HAR file for analysis
bdg network har spa-debug.har

# View DOM snapshot
bdg peek --dom --json | jq '.data.dom.html' | head -50

Analysis Tips

Correlate console errors with network timing

Export both console and network data, then cross-reference timestamps:
bdg stop
cat ~/.bdg/session.json | jq '{
  console: [.data.console[] | {time: .timestamp, text: .text}],
  network: [.data.network[] | {time: .wallTime, url: .url, status: .status}]
}'

Find React warnings about missing keys

bdg console --json | jq '.data.messages[] | select(.text | contains("key prop"))'

Identify XHR failures

bdg network list --preset api --filter "status-code:>=400"

Common SPA Issues

Symptom: Warning: Each child in a list should have a unique "key" prop.Diagnosis: List items are re-rendering inefficiently, which can cause state loss.Investigation:
bdg console | grep -i "key"
bdg dom query "li" --json | jq '.data.nodes | length'
Symptom: Fetch requests fail with CORS errors in console.Diagnosis: Missing Access-Control-Allow-Origin headers.Investigation:
bdg network list --preset api --filter "status-code:>=400"
bdg network headers <requestId> | grep -i "access-control"
Symptom: UI freezes when adding items.Diagnosis: Inefficient state updates triggering excessive DOM operations.Investigation:
# Check if adding one item causes full DOM rebuild
bdg dom query "li" --json | jq '.data.nodes | length'
bdg dom fill ".new-todo" "Test"
bdg dom pressKey ".new-todo" Enter
bdg dom query "li" --json | jq '.data.nodes | length'

Variations

Debug with screenshots for visual confirmation

Capture the UI state before and after actions:
bdg dom screenshot before.png
bdg dom fill ".new-todo" "Test item"
bdg dom pressKey ".new-todo" Enter
bdg dom screenshot after.png

Stream console messages in real-time

Watch console output as you interact with the app:
# In one terminal
bdg console --follow

# In another terminal
bdg dom fill ".new-todo" "Interactive test"
bdg dom pressKey ".new-todo" Enter

Export everything for offline analysis

bdg stop
bdg network har full-session.har
cp ~/.bdg/session.json spa-debug-$(date +%Y%m%d-%H%M%S).json

Next Steps

Console Command

Learn about console filtering and message expansion

Network Monitoring

Deep dive into network inspection and HAR export

Form Interaction

Master form filling and keyboard events

Testing Forms

Systematic form validation testing

Build docs developers (and LLMs) love