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

Added blog-starter example using Ghost CMS #19990

Merged
merged 12 commits into from
Feb 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/cms-agilitycms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Once you have access to [the environment variables you'll need](#step-15-set-up-
- [Storyblok](/examples/cms-storyblok)
- [GraphCMS](/examples/cms-graphcms)
- [Kontent](/examples/cms-kontent)
- [Ghost](/examples/cms-ghost)
- [Blog Starter](/examples/blog-starter)

## How to use
Expand Down
1 change: 1 addition & 0 deletions examples/cms-buttercms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Once you have access to [the environment variables you'll need](#step-2-set-up-e
- [Storyblok](/examples/cms-storyblok)
- [GraphCMS](/examples/cms-graphcms)
- [Kontent](/examples/cms-kontent)
- [Ghost](/examples/cms-ghost)
- [Blog Starter](/examples/blog-starter)

## How to use
Expand Down
1 change: 1 addition & 0 deletions examples/cms-contentful/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Once you have access to [the environment variables you'll need](#step-5-set-up-e
- [Storyblok](/examples/cms-storyblok)
- [GraphCMS](/examples/cms-graphcms)
- [Kontent](/examples/cms-kontent)
- [Ghost](/examples/cms-ghost)
- [Blog Starter](/examples/blog-starter)

## How to use
Expand Down
1 change: 1 addition & 0 deletions examples/cms-cosmic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Once you have access to [the environment variables you'll need](#step-3-set-up-e
- [Storyblok](/examples/cms-storyblok)
- [GraphCMS](/examples/cms-graphcms)
- [Kontent](/examples/cms-kontent)
- [Ghost](/examples/cms-ghost)
- [Blog Starter](/examples/blog-starter)

## How to use
Expand Down
1 change: 1 addition & 0 deletions examples/cms-datocms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This example showcases Next.js's [Static Generation](https://nextjs.org/docs/bas
- [Storyblok](/examples/cms-storyblok)
- [GraphCMS](/examples/cms-graphcms)
- [Kontent](/examples/cms-kontent)
- [Ghost](/examples/cms-ghost)
- [Blog Starter](/examples/blog-starter)

## Deploy your own
Expand Down
2 changes: 2 additions & 0 deletions examples/cms-ghost/.env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GHOST_API_URL=
GHOST_API_KEY=
34 changes: 34 additions & 0 deletions examples/cms-ghost/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
86 changes: 86 additions & 0 deletions examples/cms-ghost/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# A statically generated blog example using Next.js and Ghost

This example showcases Next.js's [Static Generation](https://nextjs.org/docs/basic-features/pages) feature using [Ghost](https://ghost.org/) as the data source.

> This boilerplate demonstrates simple usage and best practices. If you are looking for a more feature richt Next.js generator for Ghost including the Casper theme,
> check out [next-cms-ghost](https://github.com/styxlab/next-cms-ghost).

## Deploy your own

Once you have access to [the environment variables you'll need](#step-2-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?c=1&s=https://github.com/vercel/next.js/tree/canary/examples/cms-ghost&env=ghost_BUCKET_SLUG,ghost_READ_KEY,ghost_PREVIEW_SECRET&envDescription=Required%20to%20connect%20the%20app%20with%20ghost&envLink=https://vercel.link/cms-ghost-env)

### 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)
- [ButterCMS](/examples/cms-buttercms)
- [Storyblok](/examples/cms-storyblok)
- [GraphCMS](/examples/cms-graphcms)
- [Kontent](/examples/cms-kontent)
- [Blog Starter](/examples/blog-starter)

## How to use

Execute [`create-next-app`](https://github.com/vercel/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
npx create-next-app --example cms-ghost cms-ghost-app
# or
yarn create next-app --example cms-ghost cms-ghost-app
```

### Setp 1. Run Next.js in development mode

To get started, no configuration is needed as this example sources the content from a demo Ghost CMS.

```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/vercel/next.js/discussions).

### Step 2. Set up environment variables

If you already have a Ghost CMS running, you should create new Content API keys in the Ghost Admin panel under Integrations -> Add custom integration.
Once your keys are generated, copy them into the environment variables as follows. Your `.env.local` file should look like this:

```bash
GHOST_API_URL=...
GHOST_API_KEY=...
```

Make sure to use the Content API Key.

### Step 3. Set up Headless Ghost CMS

If you do not have access to a Ghost CMS, you need to create one for your own content. The demo Ghost CMS is running on Hetzner Cloud, which is described in [Ghost CMS on Hetzner Cloud](https://www.jamify.org/2020/04/07/ghost-cms-on-hetzner-cloud/). Note that a Ghost install on localhost is not sufficient for public deploys, as the images on your local computer are not accessible from outside.

### Step 4. 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?c=1&s=https://github.com/vercel/next.js/tree/canary/examples/cms-ghost&env=GHOST_API_URL,GHOST_API_KEY&envDescription=Required%20to%20connect%20the%20app%20with%20ghost&envLink=https://vercel.link/cms-ghost-env)
42 changes: 42 additions & 0 deletions examples/cms-ghost/components/alert.js
Original file line number Diff line number Diff line change
@@ -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>
)
}
14 changes: 14 additions & 0 deletions examples/cms-ghost/components/avatar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function Avatar({ name, picture }) {
return (
<div className="flex items-center">
{picture && (
<img
src={`${picture}?auto=format,compress,enhance&w=100&h=100`}
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-ghost/components/container.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Container({ children }) {
return <div className="container mx-auto px-5">{children}</div>
}
29 changes: 29 additions & 0 deletions examples/cms-ghost/components/cover-image.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import cn from 'classnames'
import Link from 'next/link'
import Image from 'next/image'

export default function CoverImage({ title, url, slug, width, height }) {
const image = (
<Image
src={url}
alt={`Cover Image for ${title}`}
className={cn('shadow-sm', {
'hover:shadow-md transition-shadow duration-200': slug,
})}
layout="responsive"
width={width}
height={height}
/>
)
return (
<div className="sm:mx-0">
{slug ? (
<Link href={`/posts/${slug}`}>
<a aria-label={title}>{image}</a>
</Link>
) : (
image
)}
</div>
)
}
6 changes: 6 additions & 0 deletions examples/cms-ghost/components/date.js
Original file line number Diff line number Diff line change
@@ -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-ghost/components/footer.js
Original file line number Diff line number Diff line change
@@ -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-ghost/components/header.js
Original file line number Diff line number Diff line change
@@ -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>
)
}
43 changes: 43 additions & 0 deletions examples/cms-ghost/components/hero-post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Avatar from './avatar'
import Date from './date'
import CoverImage from './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
title={title}
url={coverImage}
slug={slug}
width={2000}
height={1216}
/>
</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.profile_image} />
</div>
</div>
</section>
)
}
28 changes: 28 additions & 0 deletions examples/cms-ghost/components/intro.js
Original file line number Diff line number Diff line change
@@ -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>
)
}
18 changes: 18 additions & 0 deletions examples/cms-ghost/components/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Alert from './alert'
import Footer from './footer'
import Meta from './meta'
import 'lazysizes'
import 'lazysizes/plugins/parent-fit/ls.parent-fit'

export default function Layout({ preview, children }) {
return (
<>
<Meta />
<div className="min-h-screen">
<Alert preview={preview} />
<main>{children}</main>
</div>
<Footer />
</>
)
}
Loading