What you can do
You published Maya's homepage hero, refreshed the live site, and the old hero is still there. That is the cache doing its job. This page is how long that wait is, and how to change it.
Two everyday jobs:
- Know when a publish shows up. After you publish, the live site picks up the new snapshot within a minute. No rebuild, no redeploy.
- Choose a different wait. A longer window when the hero barely changes, or no cache at all when the page must show the newest snapshot on every request.
How the minute works
When your app renders a widget with a Staging or Production token, the widget data is fetched once and then reused for 60 seconds. The first visitor after a publish pays for a fresh fetch. Everyone else in that window gets the copy that was just fetched.
Here is the case that surprises people. Maya publishes a new headline, opens the live site ten seconds later, and sees the old one. She publishes again, thinking the first one failed. It did not. The site is still inside its minute. Wait it out, or refresh again after the minute passes, and the new headline is there.
The minute applies to published widgets — Staging and Production tokens. Development tokens are never cached, so the draft you see in Development is always current.
Where the minute comes from
It is a default in @rulecms/widget-react version 23 and later. RuleCMSWidgetServer and fetchRuleCMSWidget send the published-widget request with a 60-second revalidation window, so you get the behavior without writing any cache config yourself.
This only takes effect in frameworks that cache server fetches, which Next.js does. Other frameworks run the fetch on every request, so there is no wait and nothing to configure.
One place is deliberately never cached: widget selection rulesets. A ruleset decides which widget a visitor sees, and that decision is made fresh on every request. The widget it picks is still cached for the minute.
Choose a different window
Pass fetchOptions to override the default. Whatever you pass replaces it, so you stay in control per widget.
| What you pass | What happens | When you reach for it |
|---|---|---|
| Nothing | Cached for 60 seconds | Almost everything. This is the default. |
{ next: { revalidate: 300 } } | Cached for five minutes | A widget that changes a few times a day. |
{ cache: 'no-store' } | Fetched fresh on every request | A widget that must be current the moment you publish. |
{ next: { tags: ['hero'] } } | Cached for 60 seconds, and tagged | You want to clear it on demand from your own code. |
On a published widget:
<RuleCMSWidgetServer
publishedKey={process.env.RULECMS_PUBLISHED_KEY!}
token={process.env.RULECMS_TOKEN!}
fetchOptions={{ next: { revalidate: 300 } }}
/>Clear it the moment you publish
The minute is the longest you ever wait, not a fixed delay. If you tag the fetch, your app can drop the cached copy the instant a publish happens, and the next visitor gets the new snapshot immediately.
Tag the fetch:
<RuleCMSWidgetServer
publishedKey={process.env.RULECMS_PUBLISHED_KEY!}
token={process.env.RULECMS_TOKEN!}
fetchOptions={{ next: { tags: ['rulecms-hero'] } }}
/>Then call revalidateTag('rulecms-hero') from a route in your app when you publish. RuleCMS does not call your app for you — you wire that route to whatever signals a publish on your side, such as a button in your own admin or a scheduled job. Until you do, the 60-second window is what applies.
What to read next
- Publishing — how the snapshot the cache holds gets created in the first place.
- Development integration — tokens, and why Development behaves differently from Staging and Production.
- Widget selection rulesets — the one fetch that is never cached.