Skip to content

Instantly share code, notes, and snippets.

@manuel-schoebel
Created March 6, 2024 09:47
Show Gist options
  • Select an option

  • Save manuel-schoebel/e32b430336a02621cb92bf60ade2663e to your computer and use it in GitHub Desktop.

Select an option

Save manuel-schoebel/e32b430336a02621cb92bf60ade2663e to your computer and use it in GitHub Desktop.
Next.js revalidation for headless cms
// route handler enabling draft mode
import { getPageByPath } from "@/lib/api/getPageByPath";
import { defaultLocale } from "@/config/i18n";
import { draftMode } from "next/headers";
import { redirect } from "next/navigation";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const secret = searchParams.get("secret");
const path = searchParams.get("path");
const locale = searchParams.get("locale");
const disable = searchParams.get("disable");
// Check the secret and next parameters
// This secret should only be known to this route handler and the CMS
console.log("secret", secret, process.env.FRONTEND_API_TOKEN);
if (secret !== process.env.FRONTEND_API_TOKEN) {
return new Response("Invalid token", { status: 401 });
}
if (disable) {
draftMode().disable();
// response with disabled success message
return new Response("disabled", { status: 200 });
}
if (!path) {
return new Response("No path given", { status: 401 });
}
const page = await getPageByPath(path, locale || defaultLocale, true);
if (!page?.attributes?.path) {
return new Response("invalid path", { status: 401 });
}
draftMode().enable();
redirect(page.attributes?.path);
}
import { GetPageDocument, PublicationState } from "@/graphql/generated/graphql";
import { getClient } from "@/lib/graphqlRequestClient";
import { draftMode } from "next/headers";
import { cache as reactCache } from "react";
export const getPageByPath = reactCache(
async (path: string, locale: string, isDraft?: boolean) => {
// using next helper methods you can see if draft mode is enabled
// essentially it is just a cookie set by the draftmode api call
const { isEnabled } = draftMode();
const client = getClient();
const filters = {
path: {
eq: path,
},
};
const response = await client.request(GetPageDocument, {
locale,
filters,
limit: 1,
offset: 0,
publicationState:
isDraft || isEnabled ? PublicationState.Preview : PublicationState.Live,
});
if (!response?.pages?.data || response?.pages?.data.length === 0) {
return;
}
const [page] = response?.pages?.data;
return page;
}
);
// route handler enabling draft mode
import { getPageByPath } from "@/lib/api/getPageByPath";
import { defaultLocale } from "@/config/i18n";
import { revalidatePath } from "next/cache";
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { secret, path, locale } = await request.json();
// Check the secret and next parameters
// This secret should only be known to this route handler and the CMS
if (secret !== process.env.FRONTEND_API_TOKEN) {
return new Response("Invalid token", { status: 401 });
}
if (!path) {
return new Response("Invalid path", { status: 401 });
}
const page = await getPageByPath(path, locale || defaultLocale);
if (!page?.attributes?.path) {
return new Response("invalid path", { status: 401 });
}
const revalidationPath = `/${locale}${path}`;
try {
revalidatePath(revalidationPath);
} catch (e) {
console.error("error revalidating", e);
throw e;
}
return NextResponse.json({ revalidate: true });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment