Conversation
- prefetch route-tab links so tab clicks reuse a cached payload instead of paying an uncached server round trip each time - add loading.tsx boundaries (dashboard root and each section) so clicks paint within a frame; section-level files keep the header and tabs mounted while only the content area swaps - link the sidebar Account item and the checkout page straight to /dashboard/account/billing. The /dashboard/account redirect stub stays for old links, but no internal link pays the extra hop anymore. The stub also dropped query params, which silently ate the plan-change success toast. - set QueryClient defaults (staleTime 60s, no focus refetch, retry 1); mutations already invalidate their keys, so the user's own changes stay instant. Device messages and webhook deliveries get a 15s staleTime since they change from outside the tab. - replace the axios getCachedSession TTL cache with a token seeded from the server session in Providers and kept in sync by a session bridge. Requests attach the token synchronously; /api/auth/session is only a deduped fallback, instead of a refetch every 2 minutes with a thundering herd on expiry. - swap the billing card's 16px loading spinner for a card-shaped skeleton so the tab no longer looks blank while loading Tests: interceptor seeding/dedupe/signed-out behavior, provider defaults and token seeding, nav active-state matching, tab prefetch, billing loading state, plus e2e coverage for direct-to-billing navigation and an at-most-one-session-call budget guard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The messaging pages now stream behind a loading.tsx boundary, so their HTML can paint before React hydrates. Tests that filled the To field or dropped a CSV immediately after page.goto raced that window: the input was there, the handlers were not, and the interaction was silently lost. Under parallel workers the race lost often enough to fail runs at random. Both specs now navigate through a helper that waits for the client-side devices fetch, which only fires after hydration effects run, so the form is proven interactive before the test touches it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The API guide imported react-syntax-highlighter's default entry, which is the highlight.js build with every language compiled in. It also applied Prism themes to it, and the two use different class names, so the samples were largely uncoloured on top of being heavy. Switch to PrismLight and register the six languages the guide actually renders. GoogleOAuthProvider wrapped the whole app but only the login and register pages use it, so the Google Identity SDK initialised on every dashboard page. Move it inside LoginWithGoogle, which is where both consumers go through. Total client chunks drop from 3.1M to 2.3M. Also fixes four e2e tests that were relying on page.goto returning a fully loaded page. Adding loading.tsx introduced a short skeleton state that did not exist before, and each test measured or interacted during it. They now wait on real signals instead of timing: - bulk send waits for the dropzone row cap, which comes from useSubscription inside that page's own hook. The previous wait on the devices response was wrong: the dashboard layout requests the same query key, so it can resolve before the page hydrates. - the mobile overflow sweep and the API guide replace networkidle, which needs a 500ms window with zero connections that link prefetching keeps pushing out of reach. - the footer/tab-bar check re-scrolls as the page grows, instead of scrolling once while the skeleton is still short. - the overflow sweep measures the billing tab rather than /dashboard/account, a redirect stub with no layout of its own whose client-side redirect tore down the measurement. A new test asserts the samples carry Prism token markup in all five languages, so a revert to the highlight.js entry fails instead of silently dropping the colours. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n refetch The effect depended on the whole session object. SessionProvider returns a new object on every refetch, and React compares deps by reference, so an identical session still ran the cleanup and the body again: the widget was destroyed and its script re-injected even though nothing about the user had changed, closing any chat the user had open. It now depends on the individual strings the effect actually reads, which compare by value, so it only re-initialises when the metadata genuinely changes. Two related leaks fixed at the same time: - cleanup called destroy() but left the script tag in the document, so every re-run added another one for the life of the page. It is now removed. - a script whose src is already cached can finish loading after cleanup ran, and initialising then left a widget behind that nothing would destroy. That late load is now ignored. Tests cover all four behaviours and fail against the previous version. Also gives the API guide page focus before the clipboard test: writeText rejects on an unfocused document, which is where a page sits while other workers run, and granting clipboard permissions does not cover it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DialogContent is a CSS grid, and an implicit grid track has a min-content floor. `break-words` does not reduce min-content size, so a long unbreakable URL in any child pushed every child past the card's max-width instead of wrapping. In message history that left the message box, the delivery error panel and the action button rendered hundreds of pixels outside the dialog, off the side of the screen. An explicit minmax(0,1fr) column removes that floor, after which break-words can do its job. This fixes every dialog in the app, not just this one: any long URL, API key or gateway ID hit the same track. Also makes the details dialog the single scroll container, matching api-keys and the webhook payload modal, instead of capping the message body at 224px behind a scrollbar nested in a scrollbar. And the list row preview now wraps, so a URL-heavy message fills both clamped lines rather than being cut off partway through the first. Covered by an e2e regression test at 375px and 1280px that asserts the dialog does not scroll sideways and that the action button stays inside it. Verified failing before this change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
perf(web): make dashboard navigation fast
fix(web): keep long message text inside the details dialog
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.