From 33ebe696f8bddde28e43b80f57d9e7734e14b3ec Mon Sep 17 00:00:00 2001 From: cws Date: Wed, 9 Dec 2020 00:52:19 +0100 Subject: [PATCH] add cms-ghost --- examples/cms-agilitycms/README.md | 1 + examples/cms-buttercms/README.md | 1 + examples/cms-contentful/README.md | 1 + examples/cms-cosmic/README.md | 1 + examples/cms-datocms/README.md | 1 + examples/cms-ghost/.env.local.example | 2 + examples/cms-ghost/.gitignore | 34 +++++++ examples/cms-ghost/README.md | 90 ++++++++++++++++++ examples/cms-ghost/components/alert.js | 42 ++++++++ examples/cms-ghost/components/avatar.js | 14 +++ examples/cms-ghost/components/container.js | 3 + examples/cms-ghost/components/cover-image.js | 35 +++++++ examples/cms-ghost/components/date.js | 6 ++ examples/cms-ghost/components/footer.js | 30 ++++++ examples/cms-ghost/components/header.js | 12 +++ examples/cms-ghost/components/hero-post.js | 37 +++++++ examples/cms-ghost/components/intro.js | 28 ++++++ examples/cms-ghost/components/layout.js | 18 ++++ .../components/markdown-styles.module.css | 18 ++++ examples/cms-ghost/components/meta.js | 42 ++++++++ examples/cms-ghost/components/more-stories.js | 24 +++++ examples/cms-ghost/components/post-body.js | 12 +++ examples/cms-ghost/components/post-header.js | 26 +++++ examples/cms-ghost/components/post-preview.js | 31 ++++++ examples/cms-ghost/components/post-title.js | 7 ++ .../cms-ghost/components/section-separator.js | 3 + examples/cms-ghost/jsconfig.json | 10 ++ examples/cms-ghost/lib/api.js | 75 +++++++++++++++ examples/cms-ghost/lib/constants.js | 5 + examples/cms-ghost/package.json | 25 +++++ examples/cms-ghost/pages/_app.js | 7 ++ examples/cms-ghost/pages/_document.js | 15 +++ examples/cms-ghost/pages/api/exit-preview.js | 8 ++ examples/cms-ghost/pages/api/preview.js | 28 ++++++ examples/cms-ghost/pages/index.js | 43 +++++++++ examples/cms-ghost/pages/posts/[slug].js | 69 ++++++++++++++ examples/cms-ghost/postcss.config.js | 18 ++++ .../public/favicon/android-chrome-192x192.png | Bin 0 -> 4795 bytes .../public/favicon/android-chrome-512x512.png | Bin 0 -> 14640 bytes .../public/favicon/apple-touch-icon.png | Bin 0 -> 1327 bytes .../public/favicon/browserconfig.xml | 9 ++ .../public/favicon/favicon-16x16.png | Bin 0 -> 595 bytes .../public/favicon/favicon-32x32.png | Bin 0 -> 880 bytes examples/cms-ghost/public/favicon/favicon.ico | Bin 0 -> 15086 bytes .../public/favicon/mstile-150x150.png | Bin 0 -> 3567 bytes .../public/favicon/safari-pinned-tab.svg | 33 +++++++ .../cms-ghost/public/favicon/site.webmanifest | 19 ++++ examples/cms-ghost/styles/index.css | 3 + examples/cms-ghost/tailwind.config.js | 33 +++++++ examples/cms-graphcms/README.md | 1 + examples/cms-kontent/README.md | 1 + examples/cms-prismic/README.md | 1 + examples/cms-sanity/README.md | 1 + examples/cms-storyblok/README.md | 1 + examples/cms-strapi/README.md | 1 + examples/cms-takeshape/README.md | 1 + examples/cms-wordpress/README.md | 1 + 57 files changed, 927 insertions(+) create mode 100644 examples/cms-ghost/.env.local.example create mode 100644 examples/cms-ghost/.gitignore create mode 100644 examples/cms-ghost/README.md create mode 100644 examples/cms-ghost/components/alert.js create mode 100644 examples/cms-ghost/components/avatar.js create mode 100644 examples/cms-ghost/components/container.js create mode 100644 examples/cms-ghost/components/cover-image.js create mode 100644 examples/cms-ghost/components/date.js create mode 100644 examples/cms-ghost/components/footer.js create mode 100644 examples/cms-ghost/components/header.js create mode 100644 examples/cms-ghost/components/hero-post.js create mode 100644 examples/cms-ghost/components/intro.js create mode 100644 examples/cms-ghost/components/layout.js create mode 100644 examples/cms-ghost/components/markdown-styles.module.css create mode 100644 examples/cms-ghost/components/meta.js create mode 100644 examples/cms-ghost/components/more-stories.js create mode 100644 examples/cms-ghost/components/post-body.js create mode 100644 examples/cms-ghost/components/post-header.js create mode 100644 examples/cms-ghost/components/post-preview.js create mode 100644 examples/cms-ghost/components/post-title.js create mode 100644 examples/cms-ghost/components/section-separator.js create mode 100644 examples/cms-ghost/jsconfig.json create mode 100644 examples/cms-ghost/lib/api.js create mode 100644 examples/cms-ghost/lib/constants.js create mode 100644 examples/cms-ghost/package.json create mode 100644 examples/cms-ghost/pages/_app.js create mode 100644 examples/cms-ghost/pages/_document.js create mode 100644 examples/cms-ghost/pages/api/exit-preview.js create mode 100644 examples/cms-ghost/pages/api/preview.js create mode 100644 examples/cms-ghost/pages/index.js create mode 100644 examples/cms-ghost/pages/posts/[slug].js create mode 100644 examples/cms-ghost/postcss.config.js create mode 100644 examples/cms-ghost/public/favicon/android-chrome-192x192.png create mode 100644 examples/cms-ghost/public/favicon/android-chrome-512x512.png create mode 100644 examples/cms-ghost/public/favicon/apple-touch-icon.png create mode 100644 examples/cms-ghost/public/favicon/browserconfig.xml create mode 100644 examples/cms-ghost/public/favicon/favicon-16x16.png create mode 100644 examples/cms-ghost/public/favicon/favicon-32x32.png create mode 100644 examples/cms-ghost/public/favicon/favicon.ico create mode 100644 examples/cms-ghost/public/favicon/mstile-150x150.png create mode 100644 examples/cms-ghost/public/favicon/safari-pinned-tab.svg create mode 100644 examples/cms-ghost/public/favicon/site.webmanifest create mode 100644 examples/cms-ghost/styles/index.css create mode 100644 examples/cms-ghost/tailwind.config.js diff --git a/examples/cms-agilitycms/README.md b/examples/cms-agilitycms/README.md index d53c27ee3e0b7..cad5a6853c1c0 100644 --- a/examples/cms-agilitycms/README.md +++ b/examples/cms-agilitycms/README.md @@ -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 diff --git a/examples/cms-buttercms/README.md b/examples/cms-buttercms/README.md index b455eaa19d133..49493ca3d0fc8 100644 --- a/examples/cms-buttercms/README.md +++ b/examples/cms-buttercms/README.md @@ -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 diff --git a/examples/cms-contentful/README.md b/examples/cms-contentful/README.md index 88690dd7d1a92..ab6c3a682d0d0 100644 --- a/examples/cms-contentful/README.md +++ b/examples/cms-contentful/README.md @@ -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 diff --git a/examples/cms-cosmic/README.md b/examples/cms-cosmic/README.md index c4b795c11612c..d7e90213183c2 100644 --- a/examples/cms-cosmic/README.md +++ b/examples/cms-cosmic/README.md @@ -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 diff --git a/examples/cms-datocms/README.md b/examples/cms-datocms/README.md index 79f501d1fa291..3b394d1b3fbe8 100644 --- a/examples/cms-datocms/README.md +++ b/examples/cms-datocms/README.md @@ -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 diff --git a/examples/cms-ghost/.env.local.example b/examples/cms-ghost/.env.local.example new file mode 100644 index 0000000000000..e60e609d4d49c --- /dev/null +++ b/examples/cms-ghost/.env.local.example @@ -0,0 +1,2 @@ +GHOST_API_URL= +GHOST_API_KEY= diff --git a/examples/cms-ghost/.gitignore b/examples/cms-ghost/.gitignore new file mode 100644 index 0000000000000..1437c53f70bc2 --- /dev/null +++ b/examples/cms-ghost/.gitignore @@ -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 diff --git a/examples/cms-ghost/README.md b/examples/cms-ghost/README.md new file mode 100644 index 0000000000000..fd159c4bc9127 --- /dev/null +++ b/examples/cms-ghost/README.md @@ -0,0 +1,90 @@ +# 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). + +## Demo + +[https://ghost-next-blog.vercel.app/](https://ghost-next-blog.vercel.app/) + +## 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) diff --git a/examples/cms-ghost/components/alert.js b/examples/cms-ghost/components/alert.js new file mode 100644 index 0000000000000..e6fd18b175c8c --- /dev/null +++ b/examples/cms-ghost/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 is 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-ghost/components/avatar.js b/examples/cms-ghost/components/avatar.js new file mode 100644 index 0000000000000..271037ba41c1d --- /dev/null +++ b/examples/cms-ghost/components/avatar.js @@ -0,0 +1,14 @@ +export default function Avatar({ name, picture }) { + return ( +
+ {picture && ( + {name} + )} +
{name}
+
+ ) +} diff --git a/examples/cms-ghost/components/container.js b/examples/cms-ghost/components/container.js new file mode 100644 index 0000000000000..fc1c29dfb0747 --- /dev/null +++ b/examples/cms-ghost/components/container.js @@ -0,0 +1,3 @@ +export default function Container({ children }) { + return
{children}
+} diff --git a/examples/cms-ghost/components/cover-image.js b/examples/cms-ghost/components/cover-image.js new file mode 100644 index 0000000000000..499a8ce501c0e --- /dev/null +++ b/examples/cms-ghost/components/cover-image.js @@ -0,0 +1,35 @@ +import cn from 'classnames' +import Link from 'next/link' +import Imgix from 'react-imgix' + +export default function CoverImage({ title, url, slug }) { + const image = ( + + ) + return ( +
+ {slug ? ( + + {image} + + ) : ( + image + )} +
+ ) +} diff --git a/examples/cms-ghost/components/date.js b/examples/cms-ghost/components/date.js new file mode 100644 index 0000000000000..eac5681378bfd --- /dev/null +++ b/examples/cms-ghost/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-ghost/components/footer.js b/examples/cms-ghost/components/footer.js new file mode 100644 index 0000000000000..102872d195df0 --- /dev/null +++ b/examples/cms-ghost/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-ghost/components/header.js b/examples/cms-ghost/components/header.js new file mode 100644 index 0000000000000..562e7e3eebb6a --- /dev/null +++ b/examples/cms-ghost/components/header.js @@ -0,0 +1,12 @@ +import Link from 'next/link' + +export default function Header() { + return ( +

+ + Blog + + . +

+ ) +} diff --git a/examples/cms-ghost/components/hero-post.js b/examples/cms-ghost/components/hero-post.js new file mode 100644 index 0000000000000..59dd46e301901 --- /dev/null +++ b/examples/cms-ghost/components/hero-post.js @@ -0,0 +1,37 @@ +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 ( +
+
+ +
+
+
+

+ + {title} + +

+
+ +
+
+
+

{excerpt}

+ +
+
+
+ ) +} diff --git a/examples/cms-ghost/components/intro.js b/examples/cms-ghost/components/intro.js new file mode 100644 index 0000000000000..c3003c6196642 --- /dev/null +++ b/examples/cms-ghost/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-ghost/components/layout.js b/examples/cms-ghost/components/layout.js new file mode 100644 index 0000000000000..ff54d53992783 --- /dev/null +++ b/examples/cms-ghost/components/layout.js @@ -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 ( + <> + +
+ +
{children}
+
+