diff --git a/docs/advanced-features/preview-mode.md b/docs/advanced-features/preview-mode.md index 7c59b0a1bfafd..e187095401b47 100644 --- a/docs/advanced-features/preview-mode.md +++ b/docs/advanced-features/preview-mode.md @@ -20,6 +20,7 @@ description: Next.js has the preview mode for statically generated pages. You ca
  • Cosmic Example (Demo)
  • ButterCMS Example (Demo)
  • Storyblok Example (Demo)
  • +
  • GraphCMS Example (Demo)
  • diff --git a/docs/basic-features/data-fetching.md b/docs/basic-features/data-fetching.md index 683a2af53cb77..887a3a1e94839 100644 --- a/docs/basic-features/data-fetching.md +++ b/docs/basic-features/data-fetching.md @@ -21,6 +21,7 @@ description: 'Next.js has 2 pre-rendering modes: Static Generation and Server-si
  • Cosmic Example (Demo)
  • ButterCMS Example (Demo)
  • Storyblok Example (Demo)
  • +
  • GraphCMS Example (Demo)
  • Static Tweet Demo
  • diff --git a/docs/basic-features/pages.md b/docs/basic-features/pages.md index 349547872828b..49deaa376643a 100644 --- a/docs/basic-features/pages.md +++ b/docs/basic-features/pages.md @@ -60,6 +60,7 @@ Finally, you can always use **Client-side Rendering** along with Static Generati
  • Cosmic Example (Demo)
  • ButterCMS Example (Demo)
  • Storyblok Example (Demo)
  • +
  • GraphCMS Example (Demo)
  • Static Tweet Demo
  • diff --git a/examples/blog-starter/README.md b/examples/blog-starter/README.md index b6f6392fd2bbc..ae1f84a51473c 100644 --- a/examples/blog-starter/README.md +++ b/examples/blog-starter/README.md @@ -27,6 +27,9 @@ Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_mediu - [Strapi](/examples/cms-strapi) - [Agility CMS](/examples/cms-agilitycms) - [Cosmic](/examples/cms-cosmic) +- [ButterCMS](/examples/cms-buttercms) +- [Storyblok](/examples/cms-storyblok) +- [GraphCMS](/examples/cms-graphcms) ## How to use diff --git a/examples/cms-agilitycms/README.md b/examples/cms-agilitycms/README.md index 9a979957fc355..59a396ed97001 100644 --- a/examples/cms-agilitycms/README.md +++ b/examples/cms-agilitycms/README.md @@ -27,6 +27,7 @@ Once you have access to [the environment variables you'll need](#step-15-set-up- - [Cosmic](/examples/cms-cosmic) - [ButterCMS](/examples/cms-buttercms) - [Storyblok](/examples/cms-storyblok) +- [GraphCMS](/examples/cms-graphcms) - [Blog Starter](/examples/blog-starter) ## How to use diff --git a/examples/cms-buttercms/README.md b/examples/cms-buttercms/README.md index 070a0b2bf08f3..f676cf91e96dd 100644 --- a/examples/cms-buttercms/README.md +++ b/examples/cms-buttercms/README.md @@ -24,6 +24,7 @@ Once you have access to [the environment variables you'll need](#step-2-set-up-e - [Cosmic](/examples/cms-cosmic) - [Strapi](/examples/cms-strapi) - [Storyblok](/examples/cms-storyblok) +- [GraphCMS](/examples/cms-graphcms) - [Blog Starter](/examples/blog-starter) ## How to use diff --git a/examples/cms-contentful/README.md b/examples/cms-contentful/README.md index e02442baf30a4..52dfbd8eedee9 100644 --- a/examples/cms-contentful/README.md +++ b/examples/cms-contentful/README.md @@ -24,6 +24,7 @@ Once you have access to [the environment variables you'll need](#step-5-set-up-e - [Cosmic](/examples/cms-cosmic) - [ButterCMS](/examples/cms-buttercms) - [Storyblok](/examples/cms-storyblok) +- [GraphCMS](/examples/cms-graphcms) - [Blog Starter](/examples/blog-starter) ## How to use diff --git a/examples/cms-cosmic/README.md b/examples/cms-cosmic/README.md index d7c68d82ca834..0d674b50072dd 100644 --- a/examples/cms-cosmic/README.md +++ b/examples/cms-cosmic/README.md @@ -23,6 +23,8 @@ Once you have access to [the environment variables you'll need](#step-3-set-up-e - [Strapi](/examples/cms-strapi) - [Agility CMS](/examples/cms-agilitycms) - [ButterCMS](/examples/cms-buttercms) +- [Storyblok](/examples/cms-storyblok) +- [GraphCMS](/examples/cms-graphcms) - [Blog Starter](/examples/blog-starter) ## How to use diff --git a/examples/cms-datocms/README.md b/examples/cms-datocms/README.md index e7cc1433e007d..cc430ae9122d7 100644 --- a/examples/cms-datocms/README.md +++ b/examples/cms-datocms/README.md @@ -18,6 +18,7 @@ This example showcases Next.js's [Static Generation](https://nextjs.org/docs/bas - [Cosmic](/examples/cms-cosmic) - [ButterCMS](/examples/cms-buttercms) - [Storyblok](/examples/cms-storyblok) +- [GraphCMS](/examples/cms-graphcms) - [Blog Starter](/examples/blog-starter) ## Deploy your own diff --git a/examples/cms-graphcms/.env.local.example b/examples/cms-graphcms/.env.local.example new file mode 100644 index 0000000000000..5e2c25a6305ee --- /dev/null +++ b/examples/cms-graphcms/.env.local.example @@ -0,0 +1,4 @@ +GRAPHCMS_PROJECT_API= +GRAPHCMS_PROD_AUTH_TOKEN= +GRAPHCMS_DEV_AUTH_TOKEN= +GRAPHCMS_PREVIEW_SECRET= \ No newline at end of file diff --git a/examples/cms-graphcms/README.md b/examples/cms-graphcms/README.md new file mode 100644 index 0000000000000..c67f9247559e8 --- /dev/null +++ b/examples/cms-graphcms/README.md @@ -0,0 +1,122 @@ +# A statically generated blog example using Next.js and GraphCMS + +This example showcases Next.js's [Static Generation](https://nextjs.org/docs/basic-features/pages) feature using [GraphCMS](https://www.graphcms.com/) as the data source. + +## Demo + +- **Live**: [https://next-blog-graphcms.now.sh/](https://next-blog-graphcms.now.sh/) +- **Preview Mode**: [https://next-blog-graphcms.now.sh/api/preview...](https://next-blog-graphcms.now.sh/api/preview?secret=PHHsT9YmZjHxjxuzt8Jie2XkieME&slug=technical-seo-with-graphcms) + +### [https://next-blog-graphcms.now.sh/](https://next-blog-graphcms.now.sh/) + +### Related examples + +- [WordPress](/examples/cms-wordpress) +- [DatoCMS](/examples/cms-datocms) +- [Sanity](/examples/cms-sanity) +- [TakeShape](/examples/cms-takeshape) +- [Prismic](/examples/cms-prismic) +- [Contentful](/examples/cms-contentful) +- [Strapi](/examples/cms-strapi) +- [Agility CMS](/examples/cms-agilitycms) +- [Cosmic](/examples/cms-cosmic) +- [ButterCMS](/examples/cms-buttercms) +- [Storyblok](/examples/cms-storyblok) +- [Blog Starter](/examples/blog-starter) + +## Deploy your own + +Once you have access to [the environment variables you'll need](#step-3-set-up-environment-variables), deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/git?s=https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms&env=GRAPHCMS_PROJECT_API,GRAPHCMS_PROD_AUTH_TOKEN,GRAPHCMS_DEV_AUTH_TOKEN,GRAPHCMS_PREVIEW_SECRET&envDescription=Required%20to%20connect%20the%20app%20with%20GraphCMS&envLink=https://vercel.link/cms-graphcms-env) + +## How to use + +### Using `create-next-app` + +Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: + +```bash +npm init next-app --example cms-graphcms cms-graphcms-app +# or +yarn create next-app --example cms-graphcms cms-graphcms-app +``` + +### Download manually + +Download the example: + +```bash +curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/cms-graphcms +cd cms-graphcms +``` + +## Configuration + +### Step 1. Create an account and a project in GraphCMS + +First, [create an account in GraphCMS](https://app.graphcms.com). + +### Step 2. Create a new GraphCMS project + +After creating an account, create a new project from the **Blog Starter template** - be sure to include the example content. + +### Step 3. Set up environment variables + +Copy the `.env.local.example` file in this directory to `.env.local` (which will be ignored by Git): + +```bash +cp .env.local.example .env.local +``` + +Inside your project dashboard, navigate to **Settings > API Access page**. + +Then set each variable in `.env.local`: + +- `GRAPHCMS_PROJECT_API`: Set it to the API endpoint under **Endpoints**, at the top of the page. +- `GRAPHCMS_PROD_AUTH_TOKEN`: Copy the `NEXT_EXAMPLE_CMS_GCMS_PROD_AUTH_TOKEN` token under **Existing tokens**, at the bottom of the page. This will only query content that is published. +- `GRAPHCMS_DEV_AUTH_TOKEN`: Copy the `NEXT_EXAMPLE_CMS_GCMS_DEV_AUTH_TOKEN` token under **Existing tokens**, at the bottom of the page. This will only query content that is in draft. +- `GRAPHCMS_PREVIEW_SECRET` can be any random string (but avoid spaces), like `MY_SECRET` - this is used for [Preview Mode](https://nextjs.org/docs/advanced-features/preview-mode). + +### Step 4. Run Next.js in development mode + +```bash +npm install +npm run dev + +# or + +yarn install +yarn dev +``` + +Your blog should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/zeit/next.js/discussions). + +### Step 5. Try preview mode + +In GraphCMS, go to one of the posts in your project and: + +- **Update the title**. For example, you can add `[Draft]` in front of the title. +- After you edit the document save the article as a draft, but **DO NOT** click **Publish**. By doing this, the post will be in the draft stage. + +Now, if you go to the post page on localhost, you won't see the updated title. However, if you use **Preview Mode**, you'll be able to see the change ([Documentation](/docs/advanced-features/preview-mode.md)). + +To view the preview, transform the url to the following format: `http://localhost:3000/api/preview?secret=&slug=` where `` is the same secret you defined in the `.env.local` file and `` is the slug of one of the posts you want to preview. + +You should now be able to see the updated title. To exit the preview mode, you can click on _"Click here to exit preview mode"_ at the top. + +### Step 6. Deploy on Vercel + +You can deploy this app to the cloud with [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). + +#### Deploy Your Local Project + +To deploy your local project to Vercel, push it to GitHub/GitLab/Bitbucket and [import to Vercel](https://vercel.com/import/git?utm_source=github&utm_medium=readme&utm_campaign=next-example). + +**Important**: When you import your project on Vercel, make sure to click on **Environment Variables** and set them to match your `.env.local` file. + +#### Deploy from Our Template + +Alternatively, you can deploy using our template by clicking on the Deploy button below. + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/git?s=https://github.com/vercel/next.js/tree/canary/examples/cms-graphcms&env=GRAPHCMS_PROJECT_API,GRAPHCMS_PROD_AUTH_TOKEN,GRAPHCMS_DEV_AUTH_TOKEN,GRAPHCMS_PREVIEW_SECRET&envDescription=Required%20to%20connect%20the%20app%20with%20GraphCMS&envLink=https://vercel.link/cms-graphcms-env) diff --git a/examples/cms-graphcms/components/alert.js b/examples/cms-graphcms/components/alert.js new file mode 100644 index 0000000000000..74b887c1a0460 --- /dev/null +++ b/examples/cms-graphcms/components/alert.js @@ -0,0 +1,42 @@ +import Container from './container' +import cn from 'classnames' +import { EXAMPLE_PATH } from '../lib/constants' + +export default function Alert({ preview }) { + return ( +
    + +
    + {preview ? ( + <> + This page is a preview.{' '} + + Click here + {' '} + to exit preview mode. + + ) : ( + <> + The source code for this blog is{' '} + + available on GitHub + + . + + )} +
    +
    +
    + ) +} diff --git a/examples/cms-graphcms/components/avatar.js b/examples/cms-graphcms/components/avatar.js new file mode 100644 index 0000000000000..2dcc7eee10693 --- /dev/null +++ b/examples/cms-graphcms/components/avatar.js @@ -0,0 +1,8 @@ +export default function Avatar({ name, picture }) { + return ( +
    + {name} +
    {name}
    +
    + ) +} diff --git a/examples/cms-graphcms/components/container.js b/examples/cms-graphcms/components/container.js new file mode 100644 index 0000000000000..fc1c29dfb0747 --- /dev/null +++ b/examples/cms-graphcms/components/container.js @@ -0,0 +1,3 @@ +export default function Container({ children }) { + return
    {children}
    +} diff --git a/examples/cms-graphcms/components/cover-image.js b/examples/cms-graphcms/components/cover-image.js new file mode 100644 index 0000000000000..e1830c8286bc7 --- /dev/null +++ b/examples/cms-graphcms/components/cover-image.js @@ -0,0 +1,28 @@ +import cn from 'classnames' +import Link from 'next/link' + +export default function CoverImage({ title, url, slug }) { + const image = ( + {`Cover + ) + + return ( +
    + {slug ? ( + + {image} + + ) : ( + image + )} +
    + ) +} diff --git a/examples/cms-graphcms/components/date.js b/examples/cms-graphcms/components/date.js new file mode 100644 index 0000000000000..eac5681378bfd --- /dev/null +++ b/examples/cms-graphcms/components/date.js @@ -0,0 +1,6 @@ +import { parseISO, format } from 'date-fns' + +export default function Date({ dateString }) { + const date = parseISO(dateString) + return +} diff --git a/examples/cms-graphcms/components/footer.js b/examples/cms-graphcms/components/footer.js new file mode 100644 index 0000000000000..dbde8ff306efd --- /dev/null +++ b/examples/cms-graphcms/components/footer.js @@ -0,0 +1,30 @@ +import Container from './container' +import { EXAMPLE_PATH } from '../lib/constants' + +export default function Footer() { + return ( + + ) +} diff --git a/examples/cms-graphcms/components/header.js b/examples/cms-graphcms/components/header.js new file mode 100644 index 0000000000000..562e7e3eebb6a --- /dev/null +++ b/examples/cms-graphcms/components/header.js @@ -0,0 +1,12 @@ +import Link from 'next/link' + +export default function Header() { + return ( +

    + + Blog + + . +

    + ) +} diff --git a/examples/cms-graphcms/components/hero-post.js b/examples/cms-graphcms/components/hero-post.js new file mode 100644 index 0000000000000..fd2f17cb5b3d8 --- /dev/null +++ b/examples/cms-graphcms/components/hero-post.js @@ -0,0 +1,37 @@ +import Avatar from '../components/avatar' +import Date from '../components/date' +import CoverImage from '../components/cover-image' +import Link from 'next/link' + +export default function HeroPost({ + title, + coverImage, + date, + excerpt, + author, + slug, +}) { + return ( +
    +
    + +
    +
    +
    +

    + + {title} + +

    +
    + +
    +
    +
    +

    {excerpt}

    + +
    +
    +
    + ) +} diff --git a/examples/cms-graphcms/components/intro.js b/examples/cms-graphcms/components/intro.js new file mode 100644 index 0000000000000..5931b3c5961bd --- /dev/null +++ b/examples/cms-graphcms/components/intro.js @@ -0,0 +1,28 @@ +import { CMS_NAME, CMS_URL } from '../lib/constants' + +export default function Intro() { + return ( +
    +

    + Blog. +

    +

    + A statically generated blog example using{' '} + + Next.js + {' '} + and{' '} + + {CMS_NAME} + + . +

    +
    + ) +} diff --git a/examples/cms-graphcms/components/layout.js b/examples/cms-graphcms/components/layout.js new file mode 100644 index 0000000000000..99d95353131e0 --- /dev/null +++ b/examples/cms-graphcms/components/layout.js @@ -0,0 +1,16 @@ +import Alert from '../components/alert' +import Footer from '../components/footer' +import Meta from '../components/meta' + +export default function Layout({ preview, children }) { + return ( + <> + +
    + +
    {children}
    +
    +