fix(analytics): stop UMAMI_NOT_CONFIGURED returning 409 — caused dev server hangs

Root cause of recurring dev server hangs:
/api/v1/website-analytics threw CodedError('UMAMI_NOT_CONFIGURED') which
rendered as HTTP 409. React Query default-retries on 4xx (we set retry=1
globally), so every page render fired the umami queries → 409 →
retry → 409. Each request queried system_settings to resolve umami
credentials. Six analytics widgets on the /website-analytics page +
two on the dashboard glance tile × 2 (initial + retry) = 16 system_settings
queries on first paint. Combined with React Query refetching on mount,
the postgres pool (max=20) saturated and the server appeared hung.

Fix: return 200 with `{ data: null, notConfigured: true }` instead of
4xx. Not-configured is a steady empty state, not a transient error —
no retry loop. Updated WebsiteGlanceTile (hides itself) and
WebsiteAnalyticsShell (renders configure-umami CTA) to check the new
notConfigured flag.

Also includes from in-flight work: package.json dev script binds
0.0.0.0 so iPhone on LAN can reach the dev server, and BrandedAuthShell
uses fixed/inset-0 + flex to lock the login surface to the viewport so
iOS Safari doesn't rubber-band-scroll the card.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 16:10:40 +02:00
parent eaa01d25f9
commit 606bf19fb5
6 changed files with 32 additions and 19 deletions

View File

@@ -30,11 +30,17 @@ interface BrandedAuthShellProps {
export function BrandedAuthShell({ children, branding }: BrandedAuthShellProps) {
const logoUrl = branding?.logoUrl || DEFAULT_LOGO_URL;
const altText = branding?.appName || 'Port Nimara';
// fixed inset-0 anchors the auth surface to the viewport directly —
// iOS Safari ignores overflow-hidden on inner divs for body-level
// scrolling, so a regular `h-[100dvh] overflow-hidden` wrapper doesn't
// stop the rubber-band bounce. Pinning to the viewport via position
// fixed does. The fixed-position shell then uses flex to center the
// card within the visible area.
return (
<div className="relative min-h-screen min-h-[100dvh] flex items-center justify-center px-4 py-8">
<div className="fixed inset-0 flex items-center justify-center px-4 py-8 overscroll-none">
<div
aria-hidden
className="fixed inset-0 -z-10"
className="absolute inset-0 -z-10"
style={{
backgroundImage: `url('${DEFAULT_BG_URL}')`,
backgroundSize: 'cover',