Revalidate Hook
Invalidate frontend cache when content changes
Deprecated. Prefer
autoModeand opt collections/globals in viacustom.revalidate. This page applies whenmode: 'legacyMode'is set.
Usage
import { revalidateHook } from '@adsign/payload-adsign-plugin';
export const Pages: CollectionConfig = {
hooks: {
afterOperation: [
revalidateHook({
collection: 'pages',
cacheTagFields: ['slug'],
}),
],
},
};Options
| Option | Type | Description |
|---|---|---|
collection | string | Collection slug (required) |
cacheTagFields | string[] | Fields to use as cache tags |
collections | string[] | Additional collections to revalidate |
globals | string[] | Globals to revalidate |
documents | Document[] | Specific documents to revalidate |
revalidateRelationships | boolean | object | Incoming fan-out — docs that reference this one (denylist) |
revalidateRelated | string[] | Outgoing fan-out — own relationship/upload field names to follow |
Examples
Revalidate with cache tag fields:
revalidateHook({
collection: 'articles',
cacheTagFields: ['slug'],
collections: ['articles'],
})Revalidate related documents (useful for media):
revalidateHook({
collection: 'media',
revalidateRelationships: true,
})Scope the incoming fan-out (denylist — everything is included unless set to false):
revalidateHook({
collection: 'media',
revalidateRelationships: {
collections: { products: false }, // fan out to all referencing collections except products
globals: { menu: false }, // ...and all referencing globals except menu
},
})Follow the outgoing fan-out by naming own relationship fields:
revalidateHook({
collection: 'campaigns',
revalidateRelated: ['author'], // follow `author`, but not the costly `products` list
})In autoMode, outgoing fan-out works the same way through
custom.revalidate: fields a join declares are
followed automatically, and revalidateRelated: ['fieldName'] is the allowlist
for anything else.
Setup
- Configure in Payload:
adsignPlugin({
siteName: 'My Site',
domain: 'example.com',
revalidation: {
url: process.env.REVALIDATE_URL,
secret: process.env.REVALIDATE_SECRET,
batch: true,
},
})- Create API route in your frontend Next.js app:
import { revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest): Promise<Response> {
const { secret, tag, tags } = await request.json();
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ message: 'Invalid secret' }, { status: 401 });
}
const resolved = Array.isArray(tags) ? tags : typeof tag === 'string' ? [tag] : [];
if (resolved.length === 0 || !resolved.every((t) => typeof t === 'string' && t.length > 0)) {
return NextResponse.json({ message: 'Missing or invalid tag(s)' }, { status: 400 });
}
for (const t of resolved) {
revalidateTag(t, { expire: 0 });
}
return NextResponse.json({ revalidated: true, now: Date.now() });
}If the frontend already depends on @adsign/payload-adsign-plugin, use
revalidateFromPayload from @adsign/payload-adsign-plugin/next instead — it
handles both shapes for you. Don't add the plugin as a dependency just for
this route; it peer-depends on payload@^3.0.0.