본문으로 건너뛰기
cccskills
무료GitHub에 공개

publish-and-verify

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)

  • SKILL.md6.6 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Publishing, caching and proving it landed

The three caches, and what clears each

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.

Publishing content — no rebuild, ever

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.

Adding a new content type

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.

Cache windows

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.

Two traps that cost real time

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 only caches HTML because of a Cache Rule

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.

Deploying

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.

Proving it — never trust the diff

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.

Proving a content change propagated

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().

When someone says "it isn't showing"

In this order:

  1. 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.
  2. Did the write path call revalidateFor()? A row edited straight in the database does not, by design.
  3. Is it actually published? Drafts render only at /products/<slug>/preview (never read searchParams on a cached page: it throws DYNAMIC_SERVER_USAGE and 500s).
  4. Only then suspect the code.

Search engines

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.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

aryannema/vigyan-site-os22026년 10월 2일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

aryannema/vigyan-site-os22026년 10월 2일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

aryannema/vigyan-site-os22026년 10월 2일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

aryannema/vigyan-site-os22026년 10월 2일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

aryannema/vigyan-site-os22026년 10월 2일 업데이트

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.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

aryannema/vigyan-site-os22026년 10월 2일 업데이트

aryannema의 스킬 모두 보기

이 스킬의 문제 신고