Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
81aa4a9
chore: install next-cache-components-adoption skill
ignmandagaran Jun 26, 2026
9548b61
chore: upgrade to Next 16 and switch to Turbopack
ignmandagaran Jun 26, 2026
cb47aa0
chore: upgrade next-sanity to v13 and React to 19.2
ignmandagaran Jun 26, 2026
1fe2933
feat: adopt Cache Components
ignmandagaran Jun 26, 2026
a24cbfd
chore: upgrade motion to 12.42 stable, drop Cache Components Suspense…
ignmandagaran Jun 26, 2026
0fae0b5
revert: use webpack instead of Turbopack — Turbopack breaks Tailwind v3
ignmandagaran Jun 26, 2026
7262ff0
docs: tighten Cache Components comments
ignmandagaran Jun 26, 2026
e315711
refactor: drop unnecessary Suspense wrap on blog index page
ignmandagaran Jun 26, 2026
c2a59bb
refactor: drop Suspense wrap on careers, document it on post/showcase
ignmandagaran Jun 26, 2026
8e585fa
refactor: load Mux video client-only with a poster skeleton
ignmandagaran Jun 26, 2026
bbc1644
perf: cache tweets and load Sandpack client-only (prerender post)
ignmandagaran Jun 26, 2026
317c8b8
feat: structural canvas via route groups (removes usePathname/Suspens…
ignmandagaran Jul 1, 2026
589e04a
fix(lab): restore arcade experiments list
ignmandagaran Jul 17, 2026
0728a70
fix(sitemap): revalidate sitemap.xml on content publish
ignmandagaran Jul 17, 2026
330a14f
chore: remove next-cache-components-adoption skill
ignmandagaran Jul 17, 2026
834b28d
refactor(lab): move mobile redirect to proxy so /lab prerenders
ignmandagaran Jul 17, 2026
3287c3c
chore(deps): move next off 16.3 canary to 16.2.10 stable
ignmandagaran Jul 17, 2026
ccacbc1
docs(agents): add project-specific guidance for Cache Components
ignmandagaran Jul 20, 2026
afa8384
docs(agents): drop next-dev agent-rules block, keep project guidance
ignmandagaran Jul 20, 2026
025acf0
docs(agents): drop next-dev regeneration note
ignmandagaran Jul 20, 2026
189c6c9
refactor(shaders): flatten glslify pragmas so raw-loader alone loads …
ignmandagaran Jul 20, 2026
f6d050b
build: switch dev and build to Turbopack
ignmandagaran Jul 20, 2026
6113dbb
fix(deps): bump postcss off ancient 8.0.0 to restore Tailwind under T…
ignmandagaran Jul 20, 2026
443178b
fix(inspectables): snap wall frames to resting transform on first pla…
ignmandagaran Jul 20, 2026
ae52a85
chore(inspectables): drop explanatory comments
ignmandagaran Jul 20, 2026
48d963a
fix: restore Sanity draft preview and server-render footer year
ignmandagaran Jul 24, 2026
c6a6659
Merge origin/main into adopt-cache-components
ignmandagaran Jul 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Project specifics

- **Next.js 16.2.10 (stable), Turbopack, Cache Components on.** `cacheComponents: true` + `cacheLife: { default: sanity }` in `next.config.ts`. `dev`/`build` run on Turbopack (the Next 16 default — no `--webpack` flag). GLSL shaders load through `raw-loader` only, declared in `turbopack.rules` in `next.config.ts`; shaders must be plain GLSL with **no `glslify` `#pragma`** (the glslify requires were flattened into the `.glsl` files so `raw-loader` suffices). Tailwind v3 + the `postcss.config.mjs` chain (`postcss-import` → `tailwindcss/nesting` → `tailwindcss`) is verified working under Turbopack — `postcss-import` is now an explicit dep.
- **Sanity data has three fetch modes (`src/service/sanity/index.ts`) — pick by context:**
- `sanityFetch` — Live; only valid **inside a `"use cache"` scope** (its `cacheTag()` throws otherwise). For draft/preview render.
- `sanityFetchCached` — Live wrapped in `"use cache"`; the default for published page/route content. Revalidates via Sanity Live tags.
- `sanityFetchStatic` — non-Live plain client. Use in every context that is **not** a `"use cache"` scope: `generateStaticParams`, `generateMetadata`, **server actions**, and uncached route handlers.
- Gotcha: calling the Live `sanityFetch` outside a `"use cache"` scope 500s with `` `cacheTag()` can only be called inside a "use cache" function ``. When in doubt outside a page render, use `sanityFetchStatic`.
- **Request-time logic goes in `src/proxy.ts`, not in pages.** Reading `headers()`/`cookies()` at the top of a page forces it dynamic under Cache Components. Keep pages prerenderable; do per-request work (UA redirects, content negotiation) in the matcher-scoped proxy. Example: `/lab`'s mobile redirect lives in the proxy so the page stays static.
- **Revalidation is tag-based, not time-based.** `<SanityLive />` (root layout) invalidates cached content on publish; the 1-year `cacheLife` is only a backstop. Any new cached fetcher must route through the Sanity helpers above so its tags register.
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
21 changes: 7 additions & 14 deletions next.config.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import type { NextConfig } from "next"
import { sanity } from "next-sanity/live/cache-life"

const nextConfig: NextConfig = {
reactStrictMode: false,
productionBrowserSourceMaps: true,
cacheComponents: true,
// Sanity Live handles on-demand revalidation, so override the 15-min default.
cacheLife: {
default: sanity
},
turbopack: {
rules: {
"*.{glsl,vert,frag,vs,fs}": {
loaders: ["raw-loader", "glslify-loader"],
loaders: ["raw-loader"],
as: "*.js"
}
}
},
experimental: {
ppr: "incremental"
},

images: {
formats: ["image/avif", "image/webp"],
qualities: [75, 90],
Expand All @@ -30,15 +32,6 @@ const nextConfig: NextConfig = {
]
},

webpack: (config) => {
config.module.rules.push({
test: /\.(glsl|vs|fs|vert|frag)$/,
use: ["raw-loader", "glslify-loader"]
})

return config
},

async headers() {
return [
{
Expand Down
33 changes: 15 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"node": "24.x"
},
"scripts": {
"dev": "next dev --webpack",
"build": "next build --webpack",
"dev": "next dev",
"build": "next build",
"prettier": "prettier --write .",
"start": "next start",
"lint": "eslint src sanity next.config.ts sanity.config.ts sanity.cli.ts --ext .js,.jsx,.ts,.tsx",
Expand All @@ -34,9 +34,9 @@
"@react-three/rapier": "^1.5.0",
"@react-three/uikit": "1.0.60",
"@react-three/uikit-default": "1.0.60",
"@sanity/client": "^7.20.0",
"@sanity/client": "^7.23.0",
"@sanity/image-url": "^2.0.3",
"@sanity/vision": "^5.18.0",
"@sanity/vision": "^5.29.0",
"@supabase/ssr": "^0.5.2",
"@supabase/supabase-js": "^2.48.0",
"@use-gesture/react": "^10.3.1",
Expand All @@ -45,31 +45,29 @@
"@vercel/speed-insights": "^1.2.0",
"clsx": "^2.1.1",
"emulators": "^8.3.9",
"glsl-noise": "^0.0.0",
"glslify-loader": "^2.0.0",
"jquery": "^3.7.1",
"js-dos": "^8.3.20",
"leva": "^0.9.35",
"lodash.throttle": "^4.1.1",
"maath": "^0.10.8",
"meshline": "^3.3.1",
"motion": "12.0.0-alpha.2",
"motion": "^12.42.0",
"nanoid": "^5.1.2",
"next": "15.6.0-canary.60",
"next-sanity": "^12.1.6",
"next": "16.2.10",
"next-sanity": "^13.1.1",
"posthog-js": "^1.234.10",
"posthog-node": "^4.11.2",
"r3f-perf": "^7.2.3",
"raw-loader": "^4.0.2",
"react": "19.0.1",
"react": "19.2.7",
"react-device-detect": "^2.2.3",
"react-dom": "19.0.1",
"react-dom": "19.2.7",
"react-error-boundary": "^5.0.0",
"react-hook-form": "^7.54.2",
"react-is": "^19.2.6",
"react-merge-refs": "^2.1.1",
"react-tweet": "^3.2.2",
"sanity": "^5.18.0",
"sanity": "^5.29.0",
"sanity-plugin-media": "^4.3.0",
"sanity-plugin-mux-input": "^2.19.0",
"shiki": "^4.0.2",
Expand All @@ -85,20 +83,19 @@
"devDependencies": {
"@types/lodash.throttle": "^4.1.9",
"@types/node": "^24.13.2",
"@types/react": "^19",
"@types/react-dom": "^19",
"@types/react": "^19.2",
"@types/react-dom": "^19.2",
"@types/three": "^0.170.0",
"@typescript-eslint/eslint-plugin": "^8.27.0",
"@typescript-eslint/parser": "^8.27.0",
"dotenv": "^17.3.1",
"eslint": "^9.23.0",
"eslint-config-next": "15.2.3",
"eslint-config-next": "16.2.10",
"eslint-config-prettier": "^10.1.1",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-simple-import-sort": "^12.1.1",
"glsl-constants": "^2.0.1",
"glslify-loader": "^2.0.0",
"postcss": "^8",
"postcss": "^8.5.10",
"postcss-import": "^16.1.1",
"postcss-nesting": "^13.0.1",
"prettier": "^3.3.3",
"prettier-plugin-glsl": "^0.2.0",
Expand Down
Loading