Contents

Widget Caching

You published Maya's homepage hero and the live site still shows the old one. It will catch up within a minute. This page is why that wait exists, and how to make it shorter, longer, or gone.

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 passWhat happensWhen you reach for it
NothingCached for 60 secondsAlmost everything. This is the default.
{ next: { revalidate: 300 } }Cached for five minutesA widget that changes a few times a day.
{ cache: 'no-store' }Fetched fresh on every requestA widget that must be current the moment you publish.
{ next: { tags: ['hero'] } }Cached for 60 seconds, and taggedYou 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