Skip to content

Add Next.js ISR cache, routes, and revalidation APIs - #14320

Open
HarveyPeachey wants to merge 4 commits into
latestfrom
nextjs-internal-isr
Open

Add Next.js ISR cache, routes, and revalidation APIs#14320
HarveyPeachey wants to merge 4 commits into
latestfrom
nextjs-internal-isr

Conversation

@HarveyPeachey

@HarveyPeachey HarveyPeachey commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

This introduces Next.js internal ISR support for article pages and wires secure on-demand revalidation so content updates can invalidate cached pages without full redeploys.

Code changes

  • Added a custom ISR cache handler and wired it through Next.js config.
  • Added ISR article route handling with static paths/props for article and media-article variants.
  • Added authenticated revalidation API endpoints for article and service revalidation.
  • Added tests for article and service revalidation API handlers.
  • Added a shared revalidation auth utility.
  • Merged latest into the branch and resolved dependency conflicts in ws-nextjs-app/package.json.

Testing

  • Added/updated unit tests for the new revalidation API handlers.

Useful links

  • Simorgh ISR/revalidation app branch: nextjs-internal-isr

@HarveyPeachey
HarveyPeachey requested a review from a team as a code owner August 14, 2026 11:40
Copilot AI lite review requested due to automatic review settings August 14, 2026 11:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds internal Next.js ISR support for article pages in the ws-nextjs-app, including a custom cache handler (memory/S3), rewrites to route selected services’ /articles/* traffic to an ISR-enabled page, and authenticated on-demand revalidation endpoints for both individual articles and whole services.

Changes:

  • Added a custom Next.js cacheHandler implementation with optional S3 backing and a service-level invalidation helper.
  • Introduced an ISR article route (/articles-isr/*) plus rewrites for a rollout set of services driven by SIMORGH_ISR_ROLLOUT_SERVICES.
  • Added authenticated /api/revalidate/article and /api/revalidate/service endpoints with unit tests and a shared auth utility.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ws-nextjs-app/utilities/revalidation/auth.ts Shared logic to extract/validate the revalidation secret from header or query string.
ws-nextjs-app/pages/api/revalidate/service/index.api.ts Service-wide cache invalidation API endpoint using the cache handler helper.
ws-nextjs-app/pages/api/revalidate/service/index.api.test.ts Unit tests covering auth + required params + happy path for service invalidation.
ws-nextjs-app/pages/api/revalidate/article/index.api.ts Article path on-demand revalidation endpoint using res.revalidate.
ws-nextjs-app/pages/api/revalidate/article/index.api.test.ts Unit tests for auth/validation and successful article revalidation response payload.
ws-nextjs-app/pages/[service]/articles-isr/handleArticleRouteStatic.ts New static data handler for ISR article pages (fetch + shouldRender + props shaping).
ws-nextjs-app/pages/[service]/articles-isr/[[...variant]].page.tsx ISR article page entrypoint with getStaticPaths seeded from Most Read and fallback: 'blocking'.
ws-nextjs-app/package.json Dependency changes related to ISR/cache handler wiring (currently contains merge conflict markers).
ws-nextjs-app/next.config.js Wires custom cache handler + adds rewrites for rollout services from env var.
ws-nextjs-app/cache-handler.js New Next.js cache handler implementation with in-memory and optional S3 storage + service invalidation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +81 to 83
<<<<<<< HEAD
"@aws-sdk/client-s3": "3.919.0",
"autoprefixer": "10.5.4",
Comment on lines +114 to +122
const {
topStories = null,
features = null,
latestMedia = null,
mostRead = null,
billboardCuration = null,
mediaCuration = null,
portraitVideoItems = null,
} = secondaryData || {};
Comment on lines +45 to +66
export default async (context: GetStaticPropsContext<Params>) => {
const pathname = buildCanonicalPathname(context.params);

if (!pathname) {
return {
notFound: true,
};
}

const { service } = context.params as Params;

const { isAmp } = getPathExtension(pathname);
const { variant } = parseRoute(pathname);

const { data } = await getPageData({
id: pathname,
service,
variant: variant || undefined,
resolvedUrl: pathname,
pageType: ARTICLE_PAGE,
isAmp,
});
Comment on lines +19 to +25
const cache = new Map();
const serviceKeyIndex = new Map();

const ARTICLE_SERVICE_REGEX = /\/([a-z0-9-]+)\/articles\//i;

const cacheBackend = (process.env.SIMORGH_ISR_CACHE_BACKEND || 'memory').trim();
const cacheBucket = process.env.SIMORGH_ISR_CACHE_BUCKET;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants