brand
無料Apply this site's visual identity — colours, type, logo files and fixed brand strings. Use for any page, component, social asset or document that should look like the site.
日本語の概要は準備中です。原文の説明を表示しています。
Publishing content or deploying site-os — what caches exist, what refreshes them, and how to prove a change is actually live. Use when publishing a post or product, launching a page, deploying, or when someone says a change "isn't showing".
インストールする前に、エージェントに与えられる指示の中身を確認できます。
1. Next ISR cache on the origin disk cleared by revalidateFor()
2. Cloudflare edge ~300 cities cleared by a PURGE, not by revalidate
3. Browser per visitor cleared by a new content hash
They do not know about each other. revalidatePath refreshes the origin and
nothing else. That is the single most common misunderstanding here.
A new post, product, job or copy edit is data, not code. The route
/products/[slug] is a wildcard compiled once at deploy; it already serves
every product that will ever exist.
admin saves → row in Postgres
→ revalidateFor({kind, slug}) origin marked stale + Cloudflare purged
→ next request regenerates that ONE page
Never run pnpm build to publish content. A rebuild is only needed when the
template changes — moving a button, adding a field, changing a layout.
Three registries, each keyed by type. Adding one is an entry, never a migration:
lib/content-revalidation.ts which paths a change invalidates
lib/structured-data.ts the schema.org JSON-LD for it
lib/fulfilment.ts how a purchase is delivered
All three are exhaustive Records, so a new kind is a compile error until
its entry exists. That is deliberate — it is what stops the next content type
shipping with no structured data, which is exactly how blog posts ended up
with none.
60s /products/[slug], /templates price and offer dates
300s /blog, /blog/[slug], /careers published content
3600s /, /about, /services, /contact marketing copy
86400s /privacy /terms /refund-policy legal text
The layout is a CEILING, not a default: Next takes the LOWEST revalidate across matched segments, so a page can never be cached longer than its layout allows. Setting the layout low silently caps every page beneath it.
These are worst cases. revalidateFor() pushes changes immediately; the window
only catches a write path that forgot to call it.
A dynamic route without generateStaticParams emits no-store, however
short its revalidate. Next cannot know the slugs, so it gives up and renders
per request. This left all ten blog posts uncrawled by Google. Any
[slug] route that should be cached needs it.
Route segment config is INERT in a 'use client' file. export const dynamic = 'force-dynamic' there looks right and does nothing. Use a segment
layout.tsx instead.
Cloudflare does NOT cache HTML by default (it is extension-based: js/css/images).
Without a rule every page shows cf-cache-status: DYNAMIC whatever s-maxage says.
Since 2026-09-30 the zone has one rule, "Cache public HTML (respect origin)":
match host is www.example.com or example.com
and path does NOT start with /api/ /admin /account /go/ /login /auth
/complete-profile /data-deletion/request /_next/image
action Eligible for cache
Edge TTL: use cache-control if present, bypass if not (origin stays in control)
Cache key: Ignore query string (Free plan cannot exclude only utm_*)
Consequences: a route is cached at the edge only if the origin sends s-maxage
(so no-store/private/Set-Cookie responses are never cached); a NEW public
route is cached automatically, a new private route must be added to the exclusion
list. Query strings are ignored, so a public page must never vary its HTML on
?param — use a path segment instead (this is why drafts live at /preview).
Attribution does not depend on utm_*: /go/<slug> sets the vb_attr cookie.
A deploy replaces the container, so the previous build's JavaScript chunks are gone. Cached HTML still references them by hash, and a visitor served that HTML gets a 404 on the chunk and a page with no JavaScript.
src/instrumentation.ts purges Cloudflare on boot to close this. It requires
CLOUDFLARE_CACHE_PURGE_TOKEN and CLOUDFLARE_ZONE_ID in the environment
(not app_secrets — instrumentation is compiled for the edge runtime too and
cannot import the crypto-dependent secrets module). Without them it logs a
warning and the stale-chunk window is live.
Read the build output and the live headers. Both have lied in ways that reasoning would not have caught.
pnpm build # ○ static ● static per slug ƒ per request
# the last two columns are revalidate and expire
curl -sI https://www.example.com/blog/<slug> \
| grep -iE 'cache-control|cf-cache-status'
# want: s-maxage=N, stale-while-revalidate · cf-cache-status: HIT
# no-store or DYNAMIC means it is NOT cached
Confirm the server you measured is the one you built. A stale process
holding the port produced a completely wrong reading once — check the log for
EADDRINUSE before believing any measurement.
1. edit the row directly in Postgres → page should NOT change (proves it is cached)
2. go through the app's write path → page changes at once (proves revalidation)
If step 1 changes the page, nothing is cached. If step 2 does not, the write
path is not calling revalidateFor().
In this order:
cf-cache-status — HIT means the edge is serving an old copy. Purge:
the purge server action purgeCloudflareCache() (no UI button yet) or wait out the window.revalidateFor()? A row edited straight in the
database does not, by design./products/<slug>/preview (never read searchParams on a cached page: it throws DYNAMIC_SERVER_USAGE and 500s).sitemap lastmod real row timestamps, refreshed by revalidateFor
IndexNow Bing + Yandex, automatic on publish
Google NO push API for ordinary pages. Sitemap + the manual
Request Indexing button are the only levers.
Do not build a "tell Google" automation. It does not exist, and the Indexing
API is restricted to JobPosting and BroadcastEvent — using it for ordinary
pages risks the property.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Apply this site's visual identity — colours, type, logo files and fixed brand strings. Use for any page, component, social asset or document that should look like the site.
日本語の概要は準備中です。原文の説明を表示しています。
Use FIRST when someone asks for a new feature or a change to an existing one — before any schema, code or test. Works out what is actually being asked for, whether to build it or integrate a third party (Trustpilot, Stripe, Calendly and the like), where the data lives, who may do what, and what happens when the vendor is down. Produces a decision, then hands to feature-schema.
日本語の概要は準備中です。原文の説明を表示しています。
Use when a new feature needs a table, column or capability — evolving the schema so the new thing joins the permission, audit and RLS contract instead of sitting outside it. Covers the DDL/DML split, the resource/capability wiring, and the self-verifying migration.
日本語の概要は準備中です。原文の説明を表示しています。
Use after building a feature — explore it in a real browser to find what nobody predicted, then turn each finding into a deterministic test that guards it forever. Covers the agentic pass, what to generate vs hand-write, and how to skip honestly when a capability is missing.
日本語の概要は準備中です。原文の説明を表示しています。
Handling secrets, keys and credentials for site-os — reading vigyan-secrets.md safely, moving keys into app_secrets, rotating, and responding to an exposure. Use whenever a task touches a key, token, password, .env file, app_secrets, encryption, or the secrets document.
日本語の概要は準備中です。原文の説明を表示しています。
Audit a page or the whole yoursite site (or a new site) for indexing readiness — cache headers, sitemap, robots, canonical, JSON-LD, internal links — and check the publish pipeline (Cloudflare purge/warm, IndexNow, GSC, Bing). Use before/after publishing content or launching a site.
日本語の概要は準備中です。原文の説明を表示しています。