Skip to content
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

Add CMS example for Sanity #10907

Merged
merged 30 commits into from Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e7b41fd
Add start of Sanity CMS example
ijjk Mar 9, 2020
6bcf3d9
Merge remote-tracking branch 'upstream/canary' into example/sanity-cms
ijjk Mar 9, 2020
3b8f0ee
Update cover-image
ijjk Mar 9, 2020
c3ea04e
Clean up example
ijjk Mar 9, 2020
edc38e4
Merge remote-tracking branch 'upstream/canary' into example/sanity-cms
ijjk Mar 9, 2020
a7dfdd5
Apply suggestions from code review
ijjk Mar 10, 2020
95684be
Make changes from review
ijjk Mar 10, 2020
0270e56
Remove extra style
ijjk Mar 10, 2020
0ed7587
Apply suggestions from code review
ijjk Mar 12, 2020
5cef061
Merge remote-tracking branch 'upstream/canary' into example/sanity-cms
ijjk Mar 12, 2020
5ca2042
Make tweaks for preview mode and normalize env naming
ijjk Mar 12, 2020
c7bc255
Merge branch 'example/sanity-cms' of github.com:ijjk/next.js into exa…
ijjk Mar 12, 2020
783108e
Update viewing preview step
ijjk Mar 12, 2020
3ce1e90
Delete author.jpg
chibicode Mar 13, 2020
d8ecc0d
Delete image.jpg
chibicode Mar 13, 2020
dfd7ef6
Merge branch 'canary' into example/sanity-cms
chibicode Mar 13, 2020
e32eaac
Merge branch 'canary' into example/sanity-cms
chibicode Mar 16, 2020
b98f7e8
Update README
chibicode Mar 16, 2020
570ab8c
Fix environment variable names
chibicode Mar 16, 2020
80c487b
Project ID is needed by lambda
chibicode Mar 16, 2020
a6504ba
Improved steps
Mar 18, 2020
03c7a5c
Fixed issue with the project URL example
Mar 18, 2020
6c432ba
Clarify line
Mar 18, 2020
d44cf57
Get the preview post correctly
chibicode Mar 18, 2020
6968ea3
preview = false
chibicode Mar 18, 2020
6a7869c
Get unique posts
chibicode Mar 18, 2020
9f9968e
Show preview mode on index page
chibicode Mar 18, 2020
3068ab3
typo fix and use next latest
Mar 18, 2020
1ec4f95
Merge branch 'canary' into example/sanity-cms
Mar 18, 2020
0e028b3
Added related examples section
Mar 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/advanced-features/preview-mode.md
Expand Up @@ -154,6 +154,7 @@ https://<your-site>/api/preview?secret=<token>&slug=<path>
Take a look at the following examples to learn more:

- [DatoCMS Example](https://github.com/zeit/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.now.sh/))
- [Sanity Example](https://github.com/zeit/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog-sanity.now.sh/))

## More Details

Expand Down
1 change: 1 addition & 0 deletions docs/basic-features/data-fetching.md
Expand Up @@ -429,6 +429,7 @@ function Profile() {
Take a look at the following examples to learn more:

- [DatoCMS Example](https://github.com/zeit/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.now.sh/))
- [Sanity Example](https://github.com/zeit/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog-sanity.now.sh/))

## Learn more

Expand Down
1 change: 1 addition & 0 deletions docs/basic-features/pages.md
Expand Up @@ -247,6 +247,7 @@ We've discussed two forms of pre-rendering for Next.js.
Take a look at the following examples to learn more:

- [DatoCMS Example](https://github.com/zeit/next.js/tree/canary/examples/cms-datocms) ([Demo](https://next-blog-datocms.now.sh/))
- [Sanity Example](https://github.com/zeit/next.js/tree/canary/examples/cms-sanity) ([Demo](https://next-blog-sanity.now.sh/))

## Learn more

Expand Down
1 change: 1 addition & 0 deletions examples/cms-sanity/.env.example
@@ -0,0 +1 @@
NEXT_EXAMPLE_CMS_SANITY_PREVIEW_SECRET=
2 changes: 2 additions & 0 deletions examples/cms-sanity/.gitignore
@@ -0,0 +1,2 @@
.env
.now
140 changes: 140 additions & 0 deletions examples/cms-sanity/README.md
@@ -0,0 +1,140 @@
# A statically generated blog example using Next.js and Sanity

This example showcases Next.js's [Static Generation](/docs/basic-features/pages.md) feature using [Sanity](https://www.sanity.io/) as the data source.

## Demo

### [https://next-blog-sanity.now.sh/](https://next-blog-sanity.now.sh/)

## 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-Sanity cms-Sanity-app
# or
yarn create next-app --example cms-Sanity cms-Sanity-app
ijjk marked this conversation as resolved.
Show resolved Hide resolved
```

### 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-Sanity
ijjk marked this conversation as resolved.
Show resolved Hide resolved
cd cms-sanity
```

## Configuration

### Step 1. Create an account and a project on Sanity

First, [create an account on Sanity](https://sanity.io).

After creating an account, install the Sanity cli from npm `npm i -g @sanity/cli`.

### Step 2. Create a new Sanity project

In a separate folder run `sanity init` to initialize a new studio project.

This will be where we manage our data.

When going through the init phase make sure to select **Yes** to the **Use the default dataset configuration** step and select **Clean project with no predefined schemas** for the **Select project template** step.

After initializing get the `projectId` and `dataset` values from the `sanity.json` file that was generated and add them to `lib/sanity.js` in the example.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

### Step 3. Copy the schema file

After initializing your Sanity studio project there should be a `schemas` folder.

To get up and running we want to copy the schema file from [`./schemas/schema.js`](./schemas/schema.js) to the studio project to use for creating/editing content.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

### Step 4. Populate Content

To add some content go to your Sanity studio project where we added the schema file and run `sanity start`.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

After the project has started and you have navigated to the URL given in the terminal, select **Author** and create a new record.

- You just need **1 Author record**.
- Use dummy data for the text.
- For the image, you can download one from [Unsplash](https://unsplash.com/).

Next, select **Post** and create a new record.

- We recommend creating at least **2 Post records**.
- Use dummy data for the text.
- You can write markdown for the **Content** field.
- For the images, you can download ones from [Unsplash](https://unsplash.com/).
- Pick the **Author** you created earlier.

**Important:** For each post record, you need to click **Publish** after saving. If not, the post will be in the draft state.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

### Step 5. Set up environment variables

First, create a random preview secret.

Next, copy the `.env.example` file in this directory to `.env` (which will be ignored by Git):

```bash
cp .env.example .env
```

Then set each variable on `.env`:

- `NEXT_EXAMPLE_CMS_SANITY_PREVIEW_SECRET` can be any random string (but avoid spaces), like `MY_SECRET` - this is used for [the Preview Mode](/docs/advanced-features/preview-mode.md).

Your `.env` file should look like this:

```bash
NEXT_EXAMPLE_CMS_SANITY_PREVIEW_SECRET=...
```

### Step 6. 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 7. Try preview mode

ijjk marked this conversation as resolved.
Show resolved Hide resolved
On Sanity, go to one of the posts you've created and:

- **Update the title**. For example, you can add `[Draft]` in front of the title.
- Click **Save**, but **DO NOT** click **Publish**. By doing this, the post will be in the draft state.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

Now, if you go to the post page on localhost, you won't see the updated title. However, if you use the **Preview Mode**, you'll be able to see the change ([Documentation](/docs/advanced-features/preview-mode.md)).

To enable the Preview Mode, go to this URL:

```
http://localhost:3000/api/preview?secret=<secret>&slug=<slug>
```

- `<secret>` should be the string you entered for `NEXT_EXAMPLE_CMS_Sanity_PREVIEW_SECRET`.
ijjk marked this conversation as resolved.
Show resolved Hide resolved
- `<slug>` should be the post's `slug` attribute (you can check on Sanity).

You should now be able to see the updated title. To exit the preview mode, you can click **Click here to exit preview mode** at the top.

### Step 8. Deploy on ZEIT Now

You can deploy this app to the cloud with [ZEIT Now](https://zeit.co/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

To deploy on ZEIT Now, you need to set the environment variables with **Now Secrets** using [Now CLI](https://zeit.co/download) ([Documentation](https://zeit.co/docs/now-cli#commands/secrets)).

Install [Now CLI](https://zeit.co/download), log in to your account from the CLI, and run the following commands to add the environment variables. Replace `<NEXT_EXAMPLE_CMS_Sanity_API_TOKEN>` and `<NEXT_EXAMPLE_CMS_Sanity_PREVIEW_SECRET>` with the corresponding strings in `.env`.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

```
now secrets add next_example_cms_sanity_preview_secret <NEXT_EXAMPLE_CMS_SANITY_PREVIEW_SECRET>
```

Then push the project to GitHub/GitLab/Bitbucket and [import to ZEIT Now](https://zeit.co/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) to deploy.
42 changes: 42 additions & 0 deletions examples/cms-sanity/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 (
<div
className={cn('border-b', {
'bg-accent-7 border-accent-7 text-white': preview,
'bg-accent-1 border-accent-2': !preview,
})}
>
<Container>
<div className="py-2 text-center text-sm">
{preview ? (
<>
This is page is a preview.{' '}
<a
href="/api/exit-preview"
className="underline hover:text-cyan duration-200 transition-colors"
>
Click here
</a>{' '}
to exit preview mode.
</>
) : (
<>
The source code for this blog is{' '}
<a
href={`https://github.com/zeit/next.js/tree/canary/examples/${EXAMPLE_PATH}`}
className="underline hover:text-success duration-200 transition-colors"
>
available on GitHub
</a>
.
</>
)}
</div>
</Container>
</div>
)
}
8 changes: 8 additions & 0 deletions examples/cms-sanity/components/avatar.js
@@ -0,0 +1,8 @@
export default function Avatar({ name, picture }) {
return (
<div className="flex items-center">
<img src={picture} className="w-12 h-12 rounded-full mr-4" alt={name} />
<div className="text-xl font-bold">{name}</div>
</div>
)
}
3 changes: 3 additions & 0 deletions examples/cms-sanity/components/container.js
@@ -0,0 +1,3 @@
export default function Container({ children }) {
return <div className="container mx-auto px-5">{children}</div>
}
26 changes: 26 additions & 0 deletions examples/cms-sanity/components/cover-image.js
@@ -0,0 +1,26 @@
import cn from 'classnames'
import Link from 'next/link'

export default function CoverImage({ title, url, slug }) {
const image = (
<img
src={url}
alt={`Cover Image for ${title}`}
className={cn('shadow-small', {
'hover:shadow-medium transition-shadow duration-200': slug,
})}
ijjk marked this conversation as resolved.
Show resolved Hide resolved
/>
)

return (
<div className="-mx-5 sm:mx-0">
{slug ? (
<Link as={`/posts/${slug}`} href="/posts/[slug]">
<a aria-label={title}>{image}</a>
</Link>
) : (
image
)}
</div>
)
}
6 changes: 6 additions & 0 deletions examples/cms-sanity/components/date.js
@@ -0,0 +1,6 @@
import { parseISO, format } from 'date-fns'

export default function Date({ dateString }) {
const date = parseISO(dateString)
return <time dateTime={dateString}>{format(date, 'LLLL d, yyyy')}</time>
}
30 changes: 30 additions & 0 deletions examples/cms-sanity/components/footer.js
@@ -0,0 +1,30 @@
import Container from './container'
import { EXAMPLE_PATH } from '../lib/constants'

export default function Footer() {
return (
<footer className="bg-accent-1 border-t border-accent-2">
<Container>
<div className="py-28 flex flex-col lg:flex-row items-center">
<h3 className="text-4xl lg:text-5xl font-bold tracking-tighter leading-tight text-center lg:text-left mb-10 lg:mb-0 lg:pr-4 lg:w-1/2">
Statically Generated with Next.js.
</h3>
<div className="flex flex-col lg:flex-row justify-center items-center lg:pl-4 lg:w-1/2">
<a
href="https://nextjs.org/docs/basic-features/pages"
className="mx-3 bg-black hover:bg-white hover:text-black border border-black text-white font-bold py-3 px-12 lg:px-8 duration-200 transition-colors mb-6 lg:mb-0"
>
Read Documentation
</a>
<a
href={`https://github.com/zeit/next.js/tree/canary/examples/${EXAMPLE_PATH}`}
className="mx-3 font-bold hover:underline"
>
View on GitHub
</a>
</div>
</div>
</Container>
</footer>
)
}
12 changes: 12 additions & 0 deletions examples/cms-sanity/components/header.js
@@ -0,0 +1,12 @@
import Link from 'next/link'

export default function Header() {
return (
<h2 className="text-2xl md:text-4xl font-bold tracking-tight md:tracking-tighter leading-tight mb-20 mt-8">
<Link href="/">
<a className="hover:underline">Blog</a>
</Link>
.
</h2>
)
}
37 changes: 37 additions & 0 deletions examples/cms-sanity/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 (
<section>
<div className="mb-8 md:mb-16">
<CoverImage slug={slug} title={title} url={coverImage} />
</div>
<div className="md:grid md:grid-cols-2 md:col-gap-16 lg:col-gap-8 mb-20 md:mb-28">
<div>
<h3 className="mb-4 text-4xl lg:text-6xl leading-tight">
<Link as={`/posts/${slug}`} href="/posts/[slug]">
<a className="hover:underline">{title}</a>
</Link>
</h3>
<div className="mb-4 md:mb-0 text-lg">
<Date dateString={date} />
</div>
</div>
<div>
<p className="text-lg leading-relaxed mb-4">{excerpt}</p>
<Avatar name={author.name} picture={author.picture} />
</div>
</div>
</section>
)
}
28 changes: 28 additions & 0 deletions examples/cms-sanity/components/intro.js
@@ -0,0 +1,28 @@
import { CMS_NAME, CMS_URL } from '../lib/constants'

export default function Intro() {
return (
<section className="flex-col md:flex-row flex items-center md:justify-between mt-16 mb-16 md:mb-12">
<h1 className="text-6xl md:text-8xl font-bold tracking-tighter leading-tight md:pr-8">
Blog.
</h1>
<h4 className="text-center md:text-left text-lg mt-5 md:pl-8">
A statically generated blog example using{' '}
<a
href="https://nextjs.org/"
className="underline hover:text-success duration-200 transition-colors"
>
Next.js
</a>{' '}
and{' '}
<a
href={CMS_URL}
className="underline hover:text-success duration-200 transition-colors"
>
{CMS_NAME}
</a>
.
</h4>
</section>
)
}
16 changes: 16 additions & 0 deletions examples/cms-sanity/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 (
<>
<Meta />
<div className="min-h-screen">
<Alert preview={preview} />
<main>{children}</main>
</div>
<Footer />
</>
)
}