feat: adopt Cache Components#422
Draft
ignmandagaran wants to merge 12 commits into
Draft
Conversation
- Bump next + eslint-config-next to 16.3.0-canary.60 line (16.3 needed for Cache Components: instant export + codemod + dev-overlay validation) - Switch dev/build scripts to Turbopack (Next 16 default); drop --webpack - Remove webpack() glsl loader config (mirrored by existing turbopack.rules) - Remove experimental.ppr (flag removed in Next 16; superseded by cacheComponents) - Remove experimental_ppr segment config from blog route
- next-sanity 12.1.6 -> 13.1.1 (native Cache Components support: cacheLife profile, 'use cache'-aware fetches, tag-based Live invalidation) - react/react-dom 19.0.1 -> 19.2.7 (satisfies next-sanity peer ^19.2.3; React 19.2 is what Next 16 targets) - @sanity/client ^7.23.0, sanity/@sanity/vision ^5.29.0 (v13 peer floors) - @types/react(-dom) ^19.2 Build verified green; no behavior change (cacheComponents not yet enabled).
Enable Next.js Cache Components (cacheComponents: true) with next-sanity v13's Live integration, and walk every route to a passing build. Content routes now Partial-Prerender (static shell + streamed data); index/landing pages prerender static. Config - next.config: cacheComponents: true + Sanity cacheLife profile (Sanity Live drives on-demand revalidation, so the default 15min TTL is replaced). Sanity data layer (src/service/sanity) - sanityFetch (Live), sanityFetchCached (Live wrapped in "use cache" — cached published reads, still Live-invalidated via cacheTag), sanityFetchStatic (non-Live client.fetch for generateStaticParams/generateMetadata). - Translate removed route-segment config: drop force-static (post/showcase/ careers [slug]) and dynamic/fetchCache/revalidate (scores API). Shared shell - ContentWrapper: isolate usePathname() behind <Suspense>; dynamic-param routes (all canvas-blacklisted) fall back to page content in the plain container. - Navbar/Footer: stream interactive (motion) content via <Suspense>; cache the shared layout fetches (counts, company info). - Root layout: draftMode + SanityLive behind Suspense. Routes - post/showcase/careers/blog [slug]: split static vs Live fetch, defer params behind <Suspense>, cache content with "use cache". - home/showcase/people/services index: cache published list fetchers. - .md endpoints + sitemap: cache their data so the handlers prerender. - brands: deterministic mobile trim (was Math.random) + stream motion title. - lab: instant = false (request-time user-agent redirect, documented Block). AGENTS.md/CLAUDE.md regenerated by next dev for Next 16.
… workarounds motion@12.0.0-alpha.2 evaluated Math.random() during render (an SSR/prerender hazard under Cache Components); the stable line is prerender-safe. Upgrading lets the navbar, footer, and brands render back in the static shell instead of being streamed behind <Suspense> to dodge the hazard. - motion 12.0.0-alpha.2 -> ^12.42.0 - MotionValue constructor now requires an initial value: new MotionValue() -> new MotionValue(0) (postprocessing, inspectables, use-fade-animation) - locked-door: guard lockedDoor before animate() (stricter v12 overloads reject the possibly-undefined target) - Remove the navbar/footer/brands <Suspense> motion workarounds - Copyright year now resolves on the client (reading the current year at render is unstable IO; was previously masked by the footer Suspense wrap) Build green (89/89); content routes still Partial Prerender.
Turbopack does not run this project's Tailwind v3 PostCSS pipeline (verified with minimal and full postcss configs, ESM and CJS): `@tailwind`/`@apply` pass through unprocessed, so the site renders with ~85 CSS rules, no custom fonts, no brand styling. Turbopack also can't load the GLSL shaders (no loader equivalent). Cache Components is bundler-agnostic, so reverting the bundler keeps the entire adoption intact — content routes still Partial Prerender, index pages static. - dev/build scripts back to --webpack - restore the webpack() GLSL raw-loader/glslify-loader config - restore postcss.config.mjs (postcss-import + tailwindcss/nesting + tailwindcss) Verified: dev renders fully styled (819 CSS rules, Geist font, black bg, shaders load); `next build --webpack` green with cacheComponents (◐ routes preserved). Revisiting Turbopack later would require migrating Tailwind v3 -> v4 (native Turbopack support via @tailwindcss/postcss).
Trim the explanatory comments added during adoption to concise one-liners (why, not what), matching surrounding comment density.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The blog index only awaits params and renders cached fetchers ("use cache"),
so the params read doesn't gate any uncached work — the route still prerenders
(`/blog` and category pages stay static with the full post list in the HTML;
the optional catch-all stays Partial Prerender). Verified via prod build.
careers/[slug] has no unstable client components, so the wrap was unnecessary — its pages now prerender static. post/[slug] and showcase/[slug] keep theirs (a verified build fails without them: client embeds/gallery read Date.now()/runtime data at prerender); added a comment noting why each is load-bearing.
The Mux player reads Date.now() at render, which can't run during prerender under Cache Components. Load it via dynamic(ssr: false) wrapped in <Suspense> with a skeleton that renders the Mux poster (the video's first frame, so no layout shift). This makes <Video> self-contained, so showcase/[slug] no longer needs a page-level Suspense (its only prerender blocker was the gallery video). - video-mux.tsx: the Mux renderer, lazy-loaded client-only - video.tsx: dynamic(ssr:false) + Suspense + poster VideoSkeleton - showcase/[slug]: drop the now-redundant page-level Suspense Verified: build green (89/89), Mux player absent from prerendered HTML (no hazard), poster in the static shell, videos load + play client-side.
post/[slug] had three client embeds blocking prerender. With all handled, the
route drops its page-level Suspense and prerenders.
- tweet: wrap getTweet() in "use cache" + cacheLife('max') (tweets are
immutable) — fetched once and cached instead of hitting the syndication API
per request
- sandbox: load Sandpack via dynamic(ssr: false) + Suspense with a skeleton
(it reads Date.now() at render); split into sandbox-impl.tsx
- post/[slug]: drop the now-redundant page-level Suspense
3 tasks
…e) (#423) * prototype(canvas-route-groups): scaffolding for structural canvas Replaces the usePathname + BLACKLISTED_PATHS check with a route-group approach: - CanvasLayer: the single persistent canvas, mounted once in the root layout, visibility driven by the isCanvasInPage store flag (no usePathname). - SetCanvasMode: client effect setter a group layout renders to declare canvas on/off — runs client-side, so no prerender hazard, no <Suspense>. - PageShell: the (pages) main+Footer chrome, extracted so both the canvas and plain groups can share it. Wiring (route moves + root/layout swap) is the next step; see notes. * prototype(canvas-route-groups): wire structural canvas via route groups Replace ContentWrapper's usePathname + BLACKLISTED_PATHS with route groups: - (canvas)/ and (plain)/ groups; (content)/ sub-layout shares PageShell chrome - root layout mounts the persistent CanvasLayer (no usePathname, no Suspense) - SetCanvasMode in each group layout toggles canvasVisible; isCanvasInPage stays sticky so the WebGL Scene persists across navigations - showcase index (canvas) / [slug] (plain) split across groups - not-found sets canvas mode; 21 cross-refs + contact path updated Build green (89/89). Runtime canvas behavior pending browser QA.
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.
Summary
Adopts Next.js Cache Components (
cacheComponents: true) across the site. Content routes now Partial Prerender (static shell + streamed request-time data); index/landing pages prerender fully static. Sanity data is cached via next-sanity v13's Live integration, so cached content still revalidates on-demand through Sanity Live.Getting there required a few foundational upgrades (Cache Components needs Next 16.3 + the v13 Sanity integration). A Turbopack switch was attempted and reverted — it doesn't process this project's Tailwind v3 setup (details below) — so we stay on webpack, which Cache Components supports fine.
Built with the
next-cache-components-adoptionskill.Changes
export const instant+ dev-overlay validation; canary-only until 16.3 ships stable).cacheLifeprofile wired intonext.configso Sanity Live drives revalidation.Math.random()at render (SSR hazard under Cache Components); stable is prerender-safe.sanityFetch(Live, draft/preview) ·sanityFetchCached(Live +"use cache", published render) ·sanityFetchStatic(non-Live,generateStaticParams/generateMetadata).post/showcase/careers/blog[slug]→<Suspense>forparams+"use cache"content; home/showcase/people/services index → cached list fetchers;.mdendpoints + sitemap cached;labis a documentedinstant = falseBlock (request-time UA redirect).@tailwind/@applypass through → unstyled site) and can't load the GLSL shaders. Cache Components is bundler-agnostic, so the adoption is unaffected.Verification
next build --webpackgreen — 89/89 pages, content routes◐ Partial Prerender, index pages○ Static.Follow-ups
next+eslint-config-nextto 16.3.x stable when released.@tailwindcss/postcss) — out of scope here.Checklist
pnpm lintpasses for changed files (repo has pre-existing lint debt in untouched files)