-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: add next 14 revalidate example [TOL-1602] #436
Merged
+527
−0
Merged
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# This is the Space ID from your Contentful space. | ||
CONTENTFUL_SPACE_ID= | ||
# This is the Content Delivery API - access token, which is used for fetching published data from your Contentful space. | ||
CONTENTFUL_ACCESS_TOKEN= | ||
# This is the Content Preview API - access token, which is used for fetching draft data from your Contentful space. | ||
CONTENTFUL_PREVIEW_ACCESS_TOKEN= | ||
# This can be any value you want. It must be URL friendly as it will be send as a query parameter to enable draft mode. | ||
CONTENTFUL_PREVIEW_SECRET= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
/public/live-preview.mjs | ||
/public/live-preview.umd.js | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts | ||
|
||
.next | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Next.js GraphQL Contentful live preview SDK example | ||
|
||
This is an example project that demonstrates how to use the `@contentful/live-preview` SDK with a Next.js application that runs only on the server. | ||
|
||
The live preview SDK will be in an seperate [script](./public/_live-preview.ts), reload the page after **related** content changes and enables the inspector mode for your application. | ||
|
||
|
||
It's important that you use the CPA (Content Preview API) when using this functionality. | ||
|
||
## 1. Installation | ||
|
||
Install the dependencies: | ||
|
||
```bash | ||
npm install | ||
``` | ||
|
||
## 2. Environment variables | ||
|
||
To run this project, you will need to add the following environment variables to your `.env.local` file: | ||
|
||
- `CONTENTFUL_SPACE_ID`: This is the Space ID from your Contentful space. | ||
- `CONTENTFUL_ACCESS_TOKEN`: This is the Content Delivery API - access token, which is used for fetching **published** data from your Contentful space. | ||
- `CONTENTFUL_PREVIEW_ACCESS_TOKEN`: This is the Content Preview API - access token, which is used for fetching **draft** data from your Contentful space. | ||
- `CONTENTFUL_PREVIEW_SECRET`: This can be any value you want. It must be URL friendly as it will be send as a query parameter to enable draft mode. | ||
|
||
## 3. Setting up the content model | ||
|
||
You will need to set up a content model within your Contentful space. For this project, we need a `Post` content type with the following fields: | ||
|
||
- `slug` | ||
- `title` | ||
- `description` | ||
|
||
Once you've set up the `Post` content model, you can populate it with some example entries. | ||
|
||
## 4. Setting up Content preview URL | ||
|
||
In order to enable the live preview feature in your local development environment, you need to set up the Content preview URL in your Contentful space. | ||
|
||
`http://localhost:3000/api/draft?secret=<CONTENTFUL_PREVIEW_SECRET>&slug={entry.fields.slug}` | ||
|
||
Replace `<CONTENTFUL_PREVIEW_SECRET>` with its respective value in `.env.local`. | ||
|
||
## 5. Running the project locally | ||
|
||
To run the project locally, you can use the `npm run dev` command. You can now use the live preview feature. |
6 changes: 6 additions & 0 deletions
6
examples/next-14-app-router-ssr/app/api/disable-draft/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { draftMode } from 'next/headers'; | ||
|
||
export async function GET(request: Request) { | ||
draftMode().disable(); | ||
return new Response('Draft mode is disabled'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// route handler with secret and slug | ||
import { getPreviewPostBySlug } from '@/lib/api-graphql'; | ||
import { cookies, draftMode } from 'next/headers'; | ||
import { redirect } from 'next/navigation'; | ||
|
||
export async function GET(request: Request) { | ||
// Parse query string parameters | ||
const { searchParams } = new URL(request.url); | ||
const secret = searchParams.get('secret'); | ||
const slug = searchParams.get('slug'); | ||
|
||
// This secret should only be known to this route handler and the CMS | ||
if (secret !== process.env.CONTENTFUL_PREVIEW_SECRET || !slug) { | ||
return new Response('Invalid token', { status: 401 }); | ||
} | ||
|
||
// Fetch the headless CMS to check if the provided `slug` exists | ||
// getPostBySlug would implement the required fetching logic to the headless CMS | ||
const post = await getPreviewPostBySlug(slug); | ||
|
||
// If the slug doesn't exist prevent draft mode from being enabled | ||
if (!post) { | ||
return new Response('Invalid slug', { status: 401 }); | ||
} | ||
|
||
// Enable Draft Mode by setting the cookie | ||
draftMode().enable(); | ||
|
||
// Override cookie header for draft mode for usage in live-preview | ||
// https://github.com/vercel/next.js/issues/49927 | ||
const cookieStore = cookies(); | ||
const cookie = cookieStore.get('__prerender_bypass')!; | ||
cookies().set({ | ||
name: '__prerender_bypass', | ||
value: cookie?.value, | ||
httpOnly: true, | ||
path: '/', | ||
secure: true, | ||
sameSite: 'none', | ||
}); | ||
|
||
// Redirect to the path from the fetched post | ||
// We don't redirect to searchParams.slug as that might lead to open redirect vulnerabilities | ||
redirect(`/posts/${post.slug}`); | ||
} |
20 changes: 20 additions & 0 deletions
20
examples/next-14-app-router-ssr/app/api/revalidate/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// route handler with secret and slug | ||
import { revalidatePath } from 'next/cache'; | ||
import { redirect } from 'next/navigation'; | ||
|
||
function getQSParamFromURL(key: string, url: string): string | null { | ||
if (!url) return ''; | ||
const search = new URL(url).search; | ||
const urlParams = new URLSearchParams(search); | ||
return urlParams.get(key); | ||
} | ||
|
||
export async function GET(request: Request) { | ||
// Parse query string parameters | ||
const path = getQSParamFromURL('pathname', request.url); | ||
if (path) { | ||
revalidatePath(path); | ||
redirect(path); | ||
} | ||
return new Response('OK'); | ||
} |
27 changes: 27 additions & 0 deletions
27
examples/next-14-app-router-ssr/app/components/post-layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { ContentfulLivePreview } from '@contentful/live-preview'; | ||
import { Post } from '../../lib/api-graphql'; | ||
|
||
export default function PostLayout({ post }: { post: Post }) { | ||
return ( | ||
<> | ||
<h1 | ||
{...ContentfulLivePreview.getProps({ | ||
entryId: post.sys.id, | ||
fieldId: 'title', | ||
locale: 'en-US', | ||
})} | ||
> | ||
{post.title} | ||
</h1> | ||
<p | ||
{...ContentfulLivePreview.getProps({ | ||
entryId: post.sys.id, | ||
fieldId: 'description', | ||
locale: 'en-US', | ||
})} | ||
> | ||
{post.description} | ||
</p> | ||
</> | ||
); | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import type { Metadata } from 'next'; | ||
import { Inter } from 'next/font/google'; | ||
import { draftMode } from 'next/headers'; | ||
import Script from 'next/script'; | ||
|
||
const inter = Inter({ subsets: ['latin'] }); | ||
|
||
export const metadata: Metadata = { | ||
title: 'Next app with app router and reload entry change', | ||
description: 'Generated by create next app', | ||
}; | ||
|
||
export default function RootLayout({ children }: { children: React.ReactNode }) { | ||
const { isEnabled } = draftMode(); | ||
|
||
return ( | ||
<html lang="en"> | ||
<body className={inter.className}>{children}</body> | ||
|
||
{isEnabled && <Script src="/live-preview.mjs" />} | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { getAllPostsForHome } from '@/lib/api-graphql'; | ||
import { Metadata } from 'next'; | ||
import { draftMode } from 'next/headers'; | ||
import Link from 'next/link'; | ||
|
||
export const metadata: Metadata = { | ||
title: 'Contentful live preview example with Next.js and GraphQL', | ||
}; | ||
|
||
export default async function Home() { | ||
const { isEnabled } = draftMode(); | ||
|
||
const posts = await getAllPostsForHome(isEnabled); | ||
|
||
if (!posts || posts.length === 0) { | ||
return ( | ||
<main> | ||
<p>No posts found.</p> | ||
</main> | ||
); | ||
} | ||
|
||
return ( | ||
<> | ||
{posts.map((post) => ( | ||
<Link href={`/posts/${post.slug}`} key={post.sys.id}> | ||
{post.title} | ||
</Link> | ||
))} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { draftMode } from 'next/headers'; | ||
import { getAllPostsWithSlug, getPost } from '../../../lib/api-graphql'; | ||
|
||
import PostLayout from '../../components/post-layout'; | ||
|
||
export default async function Post({ params }: { params: { slug: string } }) { | ||
const { isEnabled } = draftMode(); | ||
|
||
const { post } = await getPost(params.slug, isEnabled); | ||
|
||
console.log({ post, isEnabled }); | ||
if (!post) { | ||
const formattedPost = `Post ${params.slug} not found`; | ||
return <h1>{formattedPost}</h1>; | ||
} | ||
|
||
return <PostLayout post={post} />; | ||
} | ||
|
||
export async function generateStaticParams() { | ||
const posts = await getAllPostsWithSlug(); | ||
|
||
return posts?.map((post) => ({ | ||
slug: post.slug, | ||
})); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add some more information how this example differs from the other Next.js examples? Right now it is not very clear to me what the benefits are of this one vs the other examples
Maybe even adding that to the general READ me in the Next js section