Cache Pipeline (Notion + Search + Build Artifacts)
This document explains how cache and generated artifacts move through the build pipeline in this repository.
Why This Exists
The project prebuilds Notion and route data before Next.js compilation to:
- reduce Notion API pressure during static generation
- avoid rate-limit bursts (429) in production builds
- keep search/navigation data static and fast at runtime
- generate redirect maps once, then serve them at edge/CDN speed
Pipeline Order
The prebuild step runs in this order (from package.json):
npm run build:searchnpm run build:metadata(optional/manual today, enabled when metadata sync is needed)npm run build:contentnpm run build:redirectsnpm run build:edge-datanpm run validate:redirects
Then next build runs.
Artifact Map
1) public/search-index.json
Generated by: scripts/build-search-index.mjs
Purpose:
- canonical static index of Notion pages
- search payload consumed by the client
- source of truth for menu grouping and route metadata
- source input for redirects and edge redirect data
Read by:
src/lib/search.ts(client-side search fetch)src/app/layout.tsx(header/menu data)src/lib/notion-cover.ts(cover/tag/link lookup artifacts)scripts/build-content-cache.mjs(list of pages to cache)scripts/build-redirects.mjsandscripts/build-edge-data.mjs
2) public/.notion-cache/*.json
Generated by: scripts/build-content-cache.mjs
Purpose:
- per-page recordMap cache for Notion pages
- used during Next production build instead of live Notion calls
Read by:
src/lib/notion-server.tswhenNEXT_PHASE === "phase-production-build"- all static page generators that call
getBuildCachedNotionPage(...)
Behavior:
- sequential downloads with retry/backoff
- skip existing files by default
--forceto refresh all- optional
--allow-failuresmode
3) public/metadata-cache.json
Generated by: scripts/build-metadata-cache.mjs
Purpose:
- AI-enriched metadata layer per pattern (description + UX/UI signals)
- safe Notion sync helper for
DescriptionandVersion - stores
VotesUp/VotesDowningestion for quality loops - keeps generation stats (
processed,skippedByDelta,geminiFailures, etc.)
Read by:
- metadata/debug workflows and local quality checks
- future snippet and recommendation layers
Input dependencies:
public/search-index.json(base pattern inventory)- Notion database rows (properties and sync target)
Notes:
- This artifact is additive and does not replace
search-index.jsonor.notion-cache. - Build flow to propagate descriptions to front surfaces remains:
npm run build:metadatanpm run build:searchnpm run build:content
4) public/_redirects
Generated by: scripts/build-redirects.mjs
Purpose:
- Netlify redirect rules for high-value legacy URL patterns
- mainly folder + Notion ID -> canonical slug redirects
Notes:
- constrained to Netlify free-tier redirect limits
- non-core redirect cases are handled by edge function logic
5) netlify/redirect-data.json
Generated by: scripts/build-edge-data.mjs
Purpose:
- edge lookup maps for redirector function
- slug map and normalized Notion ID map
Read by:
netlify/edge-functions/redirector.ts
6) .next/
Generated by: next build
Purpose:
- deployable Next.js build output
- Netlify publish target in this repo (
publish = ".next")
7) out/
Status in this repo:
- ignored in git, but not current deploy output
- kept as a standard Next export artifact path only
Runtime Usage Summary
At runtime, the app mostly uses prebuilt static files:
- search/menu/covers from
public/search-index.json - pre-cached Notion recordMaps during build phase from
public/.notion-cache - metadata enrichment from
public/metadata-cache.jsonwhen metadata tooling is enabled - redirect maps from
public/_redirectsand edge redirect data
This shifts expensive/variable work to prebuild and keeps user-facing requests fast and deterministic.
Netlify Cache Persistence
Plugin: netlify/plugins/notion-cache/index.js
- restores
public/.notion-cachebefore build - saves it after successful build
- also saves partial cache on build error
This makes subsequent deploys incremental and avoids re-fetching unchanged pages.
Environment Variables (Most Relevant)
Search/build-index and Notion fetch behavior:
NOTION_API_KEYNOTION_TOKEN(if needed for private content)NOTION_FETCH_RETRY_ATTEMPTSNOTION_FETCH_BASE_DELAY_MSNOTION_FETCH_MAX_DELAY_MSNOTION_FETCH_TIMEOUT_MSNOTION_FAIL_FAST
Metadata generation specific:
GEMINI_API_KEYPATTERN_METADATA_MODELPATTERN_METADATA_GEMINI_TIMEOUT_MSPATTERN_METADATA_NOTION_TIMEOUT_MSPATTERN_METADATA_RETRY_ATTEMPTSPATTERN_METADATA_NOTION_DELAY_MSPATTERN_METADATA_GEMINI_DELAY_MS
Content-cache specific:
NOTION_CONTENT_DELAY_MSNOTION_CONTENT_RETRY_ATTEMPTSNOTION_CONTENT_TIMEOUT_MSNOTION_CONTENT_429_DELAY_MS
Local Commands
Run only search index:
npm run build:search
Generate/sync pattern metadata descriptions:
npm run build:metadata
Metadata dry-run:
npm run build:metadata:dry
Build/update Notion content cache:
npm run build:content
Force-refresh all cached pages:
npm run build:content -- --force
Run full prebuild pipeline:
npm run prebuild
Failure Modes and Fixes
- search-index missing
- Symptom: menu/search empty, redirect build fails
- Fix: run
npm run build:search
- notion-cache misses during build
- Symptom:
[notion-cache] miss ...logs and potential 404 in prerender - Fix: run
npm run build:contentbeforenext build
- metadata descriptions not visible on front pages
- Symptom: pattern pages still show missing/old descriptions after metadata run
- Fix: run
npm run build:searchafternpm run build:metadata, then rebuild/deploy
- too many Notion retries/timeouts
- Symptom: slow or failing prebuild
- Fix: increase timeout/retry env values, keep sequential content-cache mode
- redirect count too high
- Symptom: warning/error in redirect build
- Fix: keep only essential static redirects and rely on edge maps for scale
Quick Mental Model
build-search-index: discover and normalize content metadatabuild-metadata-cache: generate and optionally sync AI description intelligencebuild-content-cache: snapshot full page content for build-time renderingbuild-redirects+build-edge-data: generate canonical redirect plumbingnext build: compile app using those prepared artifacts