Dashboard still white on real phone browsers; no error boundary hides the cause #61

Closed
opened 2026-07-29 05:35:16 -07:00 by westfarn · 0 comments
Owner

Problem

After #54 / #55 / #56, the dashboard (/) still goes white on a real phone browser, while /analytics/, /feedback/ and other routes render fine on the same phone. In desktop mobile emulation the dashboard renders correctly, so the failure is device-specific and cannot be reproduced locally.

Reported behavior: brief flash of UI, then white. Navigating to a nonexistent URL renders NotFound fine; navigating back to / blanks again.

Why the cause is invisible

The app has no React error boundary anywhere (grep for componentDidCatch / ErrorBoundary returns nothing). Any throw during render or in an effect therefore unmounts the whole tree and leaves an empty #root — a blank white page with no on-device way to read the exception. This matches the symptom exactly, including why a fresh load of another route works and why returning to / blanks again.

Secondary problem: responsive layout

The chat shell does not fit small viewports:

  • width: 100vw on the page shell clips content at the right edge
  • height: 100vh is unreliable while mobile URL bars show/hide, pushing the input row off screen
  • The input row (attach, model select, textarea, send) has no shrinkable flex children, so it overflows instead of compressing
  • No safe-area insets on header, drawer, or input area
  • Long unbroken strings and wide code blocks can push message bubbles past the viewport

Expected behavior

  • A render failure shows a readable error (message, stack, URL, user agent) that can be copied from the phone, instead of a white screen
  • The chat screen fits any viewport with no horizontal scrolling, and the input row stays reachable with the keyboard open

Proposed fix

  • Add a route-scoped AppErrorBoundary around the route tree that renders the failure details plus Reload / Copy details actions
  • Replace 100vw with 100%, adopt 100dvh for the chat shell, add min-width: 0 to flex children, apply env(safe-area-inset-*) padding, and wrap long content in message bubbles
  • Pause the particle canvas while the tab is hidden, honor prefers-reduced-motion, and cap particle count

Blocking

Worth fixing before the Capacitor Android wrap (#20): the same blank-screen failure mode is significantly harder to inspect inside a WebView.

Test plan

  • Phone browser: sign in and land on / — chat renders, or the error card shows the real exception
  • Phone browser: no horizontal scroll, full input row visible
  • Phone browser: input row reachable with keyboard open
  • Long code block stays inside the bubble
  • Desktop layout and background animation unchanged
## Problem After #54 / #55 / #56, the dashboard (`/`) **still goes white on a real phone browser**, while `/analytics/`, `/feedback/` and other routes render fine on the same phone. In desktop mobile emulation the dashboard renders correctly, so the failure is device-specific and cannot be reproduced locally. Reported behavior: brief flash of UI, then white. Navigating to a nonexistent URL renders NotFound fine; navigating back to `/` blanks again. ## Why the cause is invisible The app has **no React error boundary anywhere** (`grep` for `componentDidCatch` / `ErrorBoundary` returns nothing). Any throw during render or in an effect therefore unmounts the whole tree and leaves an empty `#root` — a blank white page with no on-device way to read the exception. This matches the symptom exactly, including why a fresh load of another route works and why returning to `/` blanks again. ## Secondary problem: responsive layout The chat shell does not fit small viewports: - `width: 100vw` on the page shell clips content at the right edge - `height: 100vh` is unreliable while mobile URL bars show/hide, pushing the input row off screen - The input row (attach, model select, textarea, send) has no shrinkable flex children, so it overflows instead of compressing - No safe-area insets on header, drawer, or input area - Long unbroken strings and wide code blocks can push message bubbles past the viewport ## Expected behavior - A render failure shows a readable error (message, stack, URL, user agent) that can be copied from the phone, instead of a white screen - The chat screen fits any viewport with no horizontal scrolling, and the input row stays reachable with the keyboard open ## Proposed fix - Add a route-scoped `AppErrorBoundary` around the route tree that renders the failure details plus Reload / Copy details actions - Replace `100vw` with `100%`, adopt `100dvh` for the chat shell, add `min-width: 0` to flex children, apply `env(safe-area-inset-*)` padding, and wrap long content in message bubbles - Pause the particle canvas while the tab is hidden, honor `prefers-reduced-motion`, and cap particle count ## Blocking Worth fixing before the Capacitor Android wrap (#20): the same blank-screen failure mode is significantly harder to inspect inside a WebView. ## Test plan - [ ] Phone browser: sign in and land on `/` — chat renders, or the error card shows the real exception - [ ] Phone browser: no horizontal scroll, full input row visible - [ ] Phone browser: input row reachable with keyboard open - [ ] Long code block stays inside the bubble - [ ] Desktop layout and background animation unchanged
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ai_ml_operations/chat_web_app#61