Repository navigation
feat(search): stream /search from the app router with SSR seeding - #947
Draft
thostetler wants to merge 10 commits into
Draft
thostetler wants to merge 10 commits into
thostetler wants to merge 10 commits into
Conversation
Bundle sizeShared by all pages: 629.8 kB (+2.0 kB) 🔴
…and 15 more routes changed. First load = polyfills + shared |
thostetler
force-pushed
the
feature/ssr-search-results
branch
from
October 5, 2026 02:54
426142c to
4c4300c
Compare
The color-mode anti-flash CSS needs the palette but not the rest of Chakra's theme, so theme-tokens.ts now holds the colors and config and theme.ts composes from it. The landing and abstract tours import shepherd.js dynamically instead of mounting react-shepherd's provider on every route. bundle-sizes.mjs reads Next's route-bundle-stats.json so app router routes appear in the report alongside pages router ones.
Query building, boost-type application, pagination maths, app-mode resolution, and the prefs cookie move out of hooks and into plain functions so an app router route can call the same code the pages router one does. searchIdentity.ts hashes a query the same way for the server-rendered seed and the client query, so React Query treats them as one cache entry instead of refetching on mount.
next/router and next/navigation expose different shapes for the same concepts, so components need one contract that works under either while the two routers coexist. Components that read the router directly now go through the adapter. Its pathname is always the resolved path, not the route pattern, because callers build URLs from it.
Adds the root layout, splits providers so both routers share them, and gives server components one session resolver and a server-rendered site-wide alert. Middleware forwards the access token on a request header so a request whose session cookie is not yet written can still resolve a token; the resolver prefers the cookie and falls back to the header. The token travels on request headers only and never reaches the browser.
Moves the search page out of pages/search/index.tsx into components/SearchPage and adds an app router /search route that seeds the primary result list from the server, streaming the facets and the rest of the chrome in behind Suspense with skeletons sized to the loaded page. Median time to first result drops from 14.0s to 1.9s and LCP from 12.6s to 1.3s on a throttled connection. Total blocking time is unchanged at roughly 3.1s, so the page becomes readable sooner but not interactive sooner.
thostetler
force-pushed
the
feature/ssr-search-results
branch
from
October 5, 2026 14:50
4c4300c to
cd73896
Compare
Result cards, the actions toolbar, and the year histogram now reserve the same height loading and loaded, with skeletons matching the real layout. ADS_COMPAT no longer AND-joins the database clause into fq_database on every pass.
useColorModeColors threw during the server render of the Suspense fallback, which dropped the whole seeded result list back to a client fetch. Uses _dark style props instead.
…inert Clamping the author row hid the all-authors trigger on narrow screens, so only the names clamp now. The loading toolbar is inert rather than merely dimmed, and the result-card chrome in the items skeleton is opt-in so the abs and library lists keep a neutral placeholder.
Load the FontAwesome stylesheet at build time instead of letting the core package inject it from JS, so the toolbar icons are sized on first paint rather than after hydration. Render the result meta separators from CSS rather than useBreakpointValue, which resolved to undefined on the server and bunched the row until it hydrated. Group the skeleton header the way SearchPage groups it so the stack emits one gap and not two. Citation links pick up the hover underline the title already had.
The verify-success test waited for the URL with notify still attached, but the app strips that param once the toast consumes it, racing hydration. Assert the redirect target from response.url(), check the toast text, then wait for the settled URL.
This branch has not been deployed
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.
/search now renders on the server and streams, cutting median time to readable results from 13976ms to 1892ms (n=13/arm) and LCP from 12599ms to 1346ms. TBT is unchanged at ~3.1s: the page is readable sooner, not interactive sooner.