DS1 (design): speed + trust bugs
Fixes the three DESIGN-SPEC Part 4 + #17 audit findings. 1. React #418 hydration mismatch (landing → dashboard entry). The `maybeSignedIn` value was computed in a useState INITIALIZER that reads localStorage during render: server (no window) → false → emits the marketing tree; a signed-in visitor's first CLIENT render → true → emits the loading placeholder. Whole-subtree server/client mismatch → React discarded and re-rendered the page. Deferred behind a mounted flag so the first client render matches the server; the stored-session check flips post-mount. SSR HTML is no longer discarded. 2. Loading walls → skeletons. New tokenized Skeleton primitive (.vyndr-skeleton, reduced-motion-safe via the global rule). Swapped into every text-wall loader: dashboard slate load ("Loading the slate…"), /desk ("Assembling the pack…"), /ledger ("Loading…"), scan ("Loading the model…"), and the landing redirect placeholder. No bare text loader remains. 3. scan→ledger persistence. Root cause: the scan page read its bearer token from localStorage['sb-token'] — a key written ONLY by the OAuth callback — so email/password users posted /api/scan anonymously and the ledger write (gated on an authed user) was silently skipped. Now uses the authoritative session.access_token (matching the ledger read path). Extracted the row builder to web/src/lib/ledgerRow.js (shared, testable). Tests: +17 (scanLedgerPersistence write→mine round-trip + scope + idempotency; ds1SpeedTrust hydration/skeleton/persistence source invariants). Full suite 233 suites / 2793 green; web build exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -401,6 +401,22 @@ h1, h2, h3, h4, h5, h6 {
|
||||
animation: shimmer 1.5s linear infinite;
|
||||
}
|
||||
|
||||
/* DS1 (§4 — kill loading walls) — the ONE skeleton primitive. Layout-matched
|
||||
dark shimmer blocks replace every text-wall loader. Tokenized (no one-off
|
||||
CSS); the global prefers-reduced-motion rule freezes the sweep to a static,
|
||||
still-visible surface — arrives-then-rests, honored globally. */
|
||||
.vyndr-skeleton {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--bg-surface) 0%,
|
||||
var(--bg-surface-hover) 50%,
|
||||
var(--bg-surface) 100%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s linear infinite;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* S6 (A1 board, LCP) — floored at a VISIBLE state (.6), matching the S33
|
||||
entrance-keyframe rule (a paused frame is never invisible). Starting at
|
||||
opacity 0 also delayed the hero heading's first contentful paint — an
|
||||
|
||||
Reference in New Issue
Block a user