From b37fa0aab80180ec837915d31874ed4eff142824 Mon Sep 17 00:00:00 2001 From: Nicola B Date: Sat, 10 Jul 2021 17:14:26 -0400 Subject: [PATCH 1/7] Add blog link to site menu --- src/components/menu/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/menu/index.js b/src/components/menu/index.js index 16c50c09..7991acdc 100644 --- a/src/components/menu/index.js +++ b/src/components/menu/index.js @@ -46,6 +46,13 @@ const Menu = () => { > Sponsorship + ) From 72768711296d84400d1a16593fd936f6a3060af2 Mon Sep 17 00:00:00 2001 From: Nicola B Date: Sat, 10 Jul 2021 17:14:55 -0400 Subject: [PATCH 2/7] Create basic blog index page --- src/pages/blog.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/pages/blog.js diff --git a/src/pages/blog.js b/src/pages/blog.js new file mode 100644 index 00000000..054dee06 --- /dev/null +++ b/src/pages/blog.js @@ -0,0 +1,17 @@ +import React from 'react' +import Layout from '../layouts/default' +import SEO from '../components/seo' + +const Blog = ({ data }) => ( + + +
+

Blog

+
+
+ {/* Iterate over blog posts */} +
+
+) + +export default Blog \ No newline at end of file From ebe9c160e84d76bac2a953df78c8620e03fdf910 Mon Sep 17 00:00:00 2001 From: Nicola B Date: Sat, 10 Jul 2021 18:28:34 -0400 Subject: [PATCH 3/7] Increase screen width size for showing mobile menu style - to accomodate the additional "blog" menu link --- src/components/menu/menu.module.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/menu/menu.module.css b/src/components/menu/menu.module.css index 2caed623..0e924c37 100644 --- a/src/components/menu/menu.module.css +++ b/src/components/menu/menu.module.css @@ -25,7 +25,7 @@ .small { display: none; - @media screen and (max-width: 60em) { + @media screen and (max-width: 68em) { display: block; .links { z-index: 1; @@ -48,7 +48,7 @@ } } - @media screen and (max-width: 60em) { + @media screen and (max-width: 68em) { display: none; } } From 469c08e347782ec5743f8867e5c6e948872d9f28 Mon Sep 17 00:00:00 2001 From: Nicola B Date: Sat, 10 Jul 2021 18:28:53 -0400 Subject: [PATCH 4/7] Add blog post component to CMS config file --- static/admin/config.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/static/admin/config.yml b/static/admin/config.yml index fc08d331..136748b5 100644 --- a/static/admin/config.yml +++ b/static/admin/config.yml @@ -286,3 +286,34 @@ collections: name: 'url_source' widget: 'string' required: false + + - name: 'posts' + identifier_field: slug + label: 'Blog Posts' + label_singular: 'Blog Post' + description: 'Add, edit, or delete blog posts here.' + delete: true + create: true + folder: 'content/posts' + extension: 'json' + fields: + - label: 'Title' + name: 'title' + widget: 'string' + required: true + - label: 'Subtitle' + name: 'subtitle' + widget: 'string' + required: true + - label: 'Date' + name: 'date' + widget: 'date' + required: true + - label: 'slug' + name: 'Slug' + widget: 'string' + required: true + - label: 'Body' + name: 'body' + widget: 'markdown' + required: true \ No newline at end of file From 94963b9a99d843bccfefd474d8522eec462e20a0 Mon Sep 17 00:00:00 2001 From: Nicola B Date: Sat, 10 Jul 2021 19:17:17 -0400 Subject: [PATCH 5/7] Add posts to blog index page --- content/posts/first-post.json | 7 +++++ src/components/posts/index.js | 15 +++++++++ src/components/posts/post.module.css | 7 +++++ src/pages/blog.js | 46 ++++++++++++++++++++-------- static/admin/config.yml | 6 +--- 5 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 content/posts/first-post.json create mode 100644 src/components/posts/index.js create mode 100644 src/components/posts/post.module.css diff --git a/content/posts/first-post.json b/content/posts/first-post.json new file mode 100644 index 00000000..42253db6 --- /dev/null +++ b/content/posts/first-post.json @@ -0,0 +1,7 @@ +{ + "title": "My First Post", + "subtitle": "Subtitle of my first post", + "date": "July 10, 2021", + "slug": "my-first-post.json", + "body": "Body of my first post" +} diff --git a/src/components/posts/index.js b/src/components/posts/index.js new file mode 100644 index 00000000..8cf6a642 --- /dev/null +++ b/src/components/posts/index.js @@ -0,0 +1,15 @@ +import React from 'react' +import styles from './post.module.css' +import { Link } from 'gatsby' +import { parameterize } from '../../utils/helpers' + +const Post = ({ post }) => ( +
+ + {post.title} + + {post.date} +
+) + +export default Post diff --git a/src/components/posts/post.module.css b/src/components/posts/post.module.css new file mode 100644 index 00000000..5c289102 --- /dev/null +++ b/src/components/posts/post.module.css @@ -0,0 +1,7 @@ +.post { + padding-bottom: 1em; +} + +.date { + padding-left: 1em; +} diff --git a/src/pages/blog.js b/src/pages/blog.js index 054dee06..85f5af02 100644 --- a/src/pages/blog.js +++ b/src/pages/blog.js @@ -1,17 +1,39 @@ import React from 'react' +import { graphql } from 'gatsby' import Layout from '../layouts/default' import SEO from '../components/seo' +import Post from '../components/posts' -const Blog = ({ data }) => ( - - -
-

Blog

-
-
- {/* Iterate over blog posts */} -
-
-) +const Blog = ({ data }) => { + const posts = data.allPostsJson.nodes + return ( + + +
+

Blog

+
+
+ {posts.map(post => ( + + ))} +
+
+ ) +} -export default Blog \ No newline at end of file +export default Blog + +export const postsQuery = graphql` + query { + allPostsJson { + nodes { + id + subtitle + title + body + date + slug + } + } + } +` diff --git a/static/admin/config.yml b/static/admin/config.yml index 136748b5..e3c494dc 100644 --- a/static/admin/config.yml +++ b/static/admin/config.yml @@ -309,11 +309,7 @@ collections: name: 'date' widget: 'date' required: true - - label: 'slug' - name: 'Slug' - widget: 'string' - required: true - label: 'Body' name: 'body' widget: 'markdown' - required: true \ No newline at end of file + required: true From 51a8f01c197d7a401307dabcba58213b42a82579 Mon Sep 17 00:00:00 2001 From: Nicola B Date: Sat, 10 Jul 2021 21:44:24 -0400 Subject: [PATCH 6/7] Restructure blog posts - Create markdown pages for each blog post - Automatically build blog post pages in gatsby-node (in addition to the subpages like code of conduct, but using different template) --- content/blog/a-blog-post/index.md | 16 +++++ content/blog/another-blog-post/index.md | 15 ++++ content/posts/first-post.json | 7 -- gatsby-node.js | 64 +++++++++++++++-- src/components/posts/index.js | 29 +++++--- src/pages/blog.js | 39 ----------- src/pages/blog/index.js | 53 ++++++++++++++ src/templates/blog-post.js | 92 +++++++++++++++++++++++++ static/admin/config.yml | 38 ++++------ 9 files changed, 268 insertions(+), 85 deletions(-) create mode 100644 content/blog/a-blog-post/index.md create mode 100644 content/blog/another-blog-post/index.md delete mode 100644 content/posts/first-post.json delete mode 100644 src/pages/blog.js create mode 100644 src/pages/blog/index.js create mode 100644 src/templates/blog-post.js diff --git a/content/blog/a-blog-post/index.md b/content/blog/a-blog-post/index.md new file mode 100644 index 00000000..3b8da399 --- /dev/null +++ b/content/blog/a-blog-post/index.md @@ -0,0 +1,16 @@ +--- +title: A Blog Post +templateKey: 'blog-post' +date: '2021-05-28T22:40:32.169Z' +description: This is a custom description for SEO and Open Graph purposes, rather than the default generated excerpt. Simply add a description field to the frontmatter. +--- + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vel aliquet tortor. Suspendisse commodo nisl nunc, in pulvinar risus tristique sit amet. Pellentesque interdum est id nunc maximus, sed condimentum urna tempor. Cras risus neque, laoreet id rutrum vitae, consequat vitae urna. In ac neque id metus commodo lobortis. Aenean ornare purus tempor metus pretium dictum. Aliquam vitae interdum arcu. + +Fusce pharetra, dui et ultricies tempor, dui orci tempor libero, eu egestas tortor mauris sit amet quam. Fusce et ex eu lectus luctus lacinia at ac nulla. Donec ultrices urna nulla, sit amet convallis turpis imperdiet accumsan. Duis scelerisque faucibus aliquet. Nulla quis efficitur augue. Donec pellentesque elementum lacinia. Maecenas nec mattis sapien, vitae placerat diam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec ipsum nisi. Vivamus faucibus vestibulum consectetur. Integer placerat erat purus, porta convallis lectus eleifend vitae. Proin at lectus non enim blandit congue. Proin ex neque, ullamcorper ut enim et, lacinia facilisis lorem. Nunc non odio augue. Etiam erat sapien, maximus non vulputate eget, ultrices a turpis. Phasellus ut risus orci. + +Duis auctor imperdiet lectus, in commodo erat molestie eleifend. Donec pretium egestas eros, eget tincidunt nibh tristique quis. Nulla ut tempus tellus. Etiam vel euismod mauris. Nulla eu ante auctor augue viverra lacinia non egestas erat. Ut lacinia nisi elementum dui dignissim mattis. Praesent sollicitudin auctor orci eget tincidunt. Proin egestas eget nulla nec auctor. In bibendum, diam id pharetra porta, felis ante egestas nibh, ac ultricies augue metus ac lorem. Mauris volutpat ipsum at aliquam cursus. Integer velit eros, varius ut ultricies vel, facilisis sit amet dui. Nunc tempor quis massa eu pellentesque. In a mauris porta lectus tempor gravida at a nulla. Integer quis tristique felis, at accumsan augue. Sed finibus, est non vulputate tincidunt, purus ex suscipit dolor, quis dictum metus purus ac neque. Nulla ut nisl ac odio venenatis consectetur. + +Nunc sed pulvinar lectus, a pellentesque elit. Curabitur sed mollis risus, non sagittis ex. Donec sit amet faucibus tellus. Vestibulum tempus mauris eget nunc egestas vestibulum. Praesent tristique nunc nec ipsum cursus fringilla quis in nulla. Nulla a tempor est. Etiam bibendum odio vitae pharetra auctor. + +Suspendisse vehicula lorem et tempus euismod. Sed consequat, nunc non auctor varius, sem leo dignissim justo, in molestie risus sem non ligula. Sed interdum urna congue, faucibus odio quis, ullamcorper sem. Donec risus purus, malesuada nec varius quis, porta quis enim. Maecenas euismod sed mi sed pharetra. Integer porta viverra ante, a fringilla purus. Praesent urna nisl, scelerisque sed tellus ut, aliquam hendrerit justo. diff --git a/content/blog/another-blog-post/index.md b/content/blog/another-blog-post/index.md new file mode 100644 index 00000000..fec9bd78 --- /dev/null +++ b/content/blog/another-blog-post/index.md @@ -0,0 +1,15 @@ +--- +title: Another Blog Post +templateKey: 'blog-post' +date: '2021-06-11T22:40:32.169Z' +--- + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vel aliquet tortor. Suspendisse commodo nisl nunc, in pulvinar risus tristique sit amet. Pellentesque interdum est id nunc maximus, sed condimentum urna tempor. Cras risus neque, laoreet id rutrum vitae, consequat vitae urna. In ac neque id metus commodo lobortis. Aenean ornare purus tempor metus pretium dictum. Aliquam vitae interdum arcu. + +Fusce pharetra, dui et ultricies tempor, dui orci tempor libero, eu egestas tortor mauris sit amet quam. Fusce et ex eu lectus luctus lacinia at ac nulla. Donec ultrices urna nulla, sit amet convallis turpis imperdiet accumsan. Duis scelerisque faucibus aliquet. Nulla quis efficitur augue. Donec pellentesque elementum lacinia. Maecenas nec mattis sapien, vitae placerat diam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec ipsum nisi. Vivamus faucibus vestibulum consectetur. Integer placerat erat purus, porta convallis lectus eleifend vitae. Proin at lectus non enim blandit congue. Proin ex neque, ullamcorper ut enim et, lacinia facilisis lorem. Nunc non odio augue. Etiam erat sapien, maximus non vulputate eget, ultrices a turpis. Phasellus ut risus orci. + +Duis auctor imperdiet lectus, in commodo erat molestie eleifend. Donec pretium egestas eros, eget tincidunt nibh tristique quis. Nulla ut tempus tellus. Etiam vel euismod mauris. Nulla eu ante auctor augue viverra lacinia non egestas erat. Ut lacinia nisi elementum dui dignissim mattis. Praesent sollicitudin auctor orci eget tincidunt. Proin egestas eget nulla nec auctor. In bibendum, diam id pharetra porta, felis ante egestas nibh, ac ultricies augue metus ac lorem. Mauris volutpat ipsum at aliquam cursus. Integer velit eros, varius ut ultricies vel, facilisis sit amet dui. Nunc tempor quis massa eu pellentesque. In a mauris porta lectus tempor gravida at a nulla. Integer quis tristique felis, at accumsan augue. Sed finibus, est non vulputate tincidunt, purus ex suscipit dolor, quis dictum metus purus ac neque. Nulla ut nisl ac odio venenatis consectetur. + +Nunc sed pulvinar lectus, a pellentesque elit. Curabitur sed mollis risus, non sagittis ex. Donec sit amet faucibus tellus. Vestibulum tempus mauris eget nunc egestas vestibulum. Praesent tristique nunc nec ipsum cursus fringilla quis in nulla. Nulla a tempor est. Etiam bibendum odio vitae pharetra auctor. + +Suspendisse vehicula lorem et tempus euismod. Sed consequat, nunc non auctor varius, sem leo dignissim justo, in molestie risus sem non ligula. Sed interdum urna congue, faucibus odio quis, ullamcorper sem. Donec risus purus, malesuada nec varius quis, porta quis enim. Maecenas euismod sed mi sed pharetra. Integer porta viverra ante, a fringilla purus. Praesent urna nisl, scelerisque sed tellus ut, aliquam hendrerit justo. diff --git a/content/posts/first-post.json b/content/posts/first-post.json deleted file mode 100644 index 42253db6..00000000 --- a/content/posts/first-post.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "My First Post", - "subtitle": "Subtitle of my first post", - "date": "July 10, 2021", - "slug": "my-first-post.json", - "body": "Body of my first post" -} diff --git a/gatsby-node.js b/gatsby-node.js index 0b9d094a..da803bb4 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -6,12 +6,30 @@ const path = require('path') const { createFilePath } = require('gatsby-source-filesystem') -exports.createPages = ({ actions, graphql }) => { +exports.createPages = ({ actions, graphql, reporter }) => { const { createPage } = actions - return graphql(` { - allMarkdownRemark(limit: 1000) { + subPages: allMarkdownRemark( + limit: 1000 + filter: { frontmatter: { templateKey: { eq: "subpage" } } } + ) { + edges { + node { + id + frontmatter { + templateKey + } + fields { + slug + } + } + } + } + blogPosts: allMarkdownRemark( + limit: 1000 + filter: { frontmatter: { templateKey: { eq: "blog-post" } } } + ) { edges { node { id @@ -22,16 +40,26 @@ exports.createPages = ({ actions, graphql }) => { templateKey } } + next { + id + } + previous { + id + } } } } `).then(result => { if (result.errors) { - result.errors.forEach(e => console.error(e.toString())) - return Promise.reject(result.errors) + reporter.panicOnBuild( + `There was an error loading the pages and blog posts`, + result.errors + ) + return } - const pages = result.data.allMarkdownRemark.edges + // Create subpages like Code of Conduct + const pages = result.data.subPages.edges pages.forEach(edge => { const id = edge.node.id @@ -41,12 +69,34 @@ exports.createPages = ({ actions, graphql }) => { component: path.resolve( `src/templates/${String(edge.node.frontmatter.templateKey)}.js` ), - // additional data can be passed via context context: { id, }, }) }) + + // Create pages for each blog post + const posts = result.data.blogPosts.edges + // But only if there's at least one markdown file found at "content/blog" (defined in gatsby-config.js) + // `context` is available in the template as a prop and as a variable in GraphQL + if (posts.length > 0) { + posts.forEach((post, index) => { + const previousPostId = post.previous ? post.previous.id : null + const nextPostId = post.next ? post.next.id : null + + createPage({ + path: post.node.fields.slug, + component: path.resolve( + `src/templates/${String(post.node.frontmatter.templateKey)}.js` + ), + context: { + id: post.node.id, + previousPostId, + nextPostId, + }, + }) + }) + } }) } diff --git a/src/components/posts/index.js b/src/components/posts/index.js index 8cf6a642..f6139fb7 100644 --- a/src/components/posts/index.js +++ b/src/components/posts/index.js @@ -1,15 +1,28 @@ import React from 'react' -import styles from './post.module.css' +// import styles from './post.module.css' import { Link } from 'gatsby' -import { parameterize } from '../../utils/helpers' +// import { parameterize } from '../../utils/helpers' const Post = ({ post }) => ( -
- - {post.title} - - {post.date} -
+
+
+

+ + {post.frontmatter.title} + +

+ {post.frontmatter.date} +

Time to read: {post.timeToRead} minutes

+
+
+

+

+
) export default Post diff --git a/src/pages/blog.js b/src/pages/blog.js deleted file mode 100644 index 85f5af02..00000000 --- a/src/pages/blog.js +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react' -import { graphql } from 'gatsby' -import Layout from '../layouts/default' -import SEO from '../components/seo' -import Post from '../components/posts' - -const Blog = ({ data }) => { - const posts = data.allPostsJson.nodes - return ( - - -
-

Blog

-
-
- {posts.map(post => ( - - ))} -
-
- ) -} - -export default Blog - -export const postsQuery = graphql` - query { - allPostsJson { - nodes { - id - subtitle - title - body - date - slug - } - } - } -` diff --git a/src/pages/blog/index.js b/src/pages/blog/index.js new file mode 100644 index 00000000..97b48f88 --- /dev/null +++ b/src/pages/blog/index.js @@ -0,0 +1,53 @@ +import React from 'react' +import { graphql } from 'gatsby' +import Layout from '../../layouts/default' +import SEO from '../../components/seo' +import Post from '../../components/posts' + +const Blog = ({ data }) => { + const posts = data.allMarkdownRemark.nodes + return ( + + +
+

Blog

+
+
+
    + {posts.map(post => { + return ( +
  1. + +
  2. + ) + })} +
+
+
+ ) +} + +export default Blog + +export const postsQuery = graphql` + query { + allMarkdownRemark( + sort: { fields: [frontmatter___date], order: DESC } + filter: { frontmatter: { templateKey: { eq: "blog-post" } } } + ) { + nodes { + excerpt + fields { + slug + } + frontmatter { + date(formatString: "MMMM DD, YYYY") + title + description + templateKey + } + timeToRead + } + } + } +` diff --git a/src/templates/blog-post.js b/src/templates/blog-post.js new file mode 100644 index 00000000..62aaf768 --- /dev/null +++ b/src/templates/blog-post.js @@ -0,0 +1,92 @@ +import * as React from 'react' +import { Link, graphql } from 'gatsby' + +import Layout from '../layouts/default' +import Seo from '../components/seo' + +const BlogPostTemplate = ({ data }) => { + const post = data.markdownRemark + const { previous, next } = data + + return ( + + +
+
+

{post.frontmatter.title}

+

{post.frontmatter.date}

+
+
+
+ +
+ ) +} + +export default BlogPostTemplate + +export const pageQuery = graphql` + query BlogPostBySlug( + $id: String! + $previousPostId: String + $nextPostId: String + ) { + markdownRemark(id: { eq: $id }) { + id + excerpt(pruneLength: 160) + html + frontmatter { + title + date(formatString: "MMMM DD, YYYY") + description + } + } + previous: markdownRemark(id: { eq: $previousPostId }) { + fields { + slug + } + frontmatter { + title + } + } + next: markdownRemark(id: { eq: $nextPostId }) { + fields { + slug + } + frontmatter { + title + } + } + } +` diff --git a/static/admin/config.yml b/static/admin/config.yml index e3c494dc..a2254a88 100644 --- a/static/admin/config.yml +++ b/static/admin/config.yml @@ -287,29 +287,19 @@ collections: widget: 'string' required: false - - name: 'posts' - identifier_field: slug - label: 'Blog Posts' - label_singular: 'Blog Post' - description: 'Add, edit, or delete blog posts here.' - delete: true + - name: 'blog' + label: 'Blog' + folder: 'content/blog' create: true - folder: 'content/posts' - extension: 'json' + delete: true + slug: 'index' + media_folder: '' + public_folder: '' + path: '{{title}}/index' + editor: + preview: false fields: - - label: 'Title' - name: 'title' - widget: 'string' - required: true - - label: 'Subtitle' - name: 'subtitle' - widget: 'string' - required: true - - label: 'Date' - name: 'date' - widget: 'date' - required: true - - label: 'Body' - name: 'body' - widget: 'markdown' - required: true + - { label: 'Title', name: 'title', widget: 'string' } + - { label: 'Publish Date', name: 'date', widget: 'datetime' } + - { label: 'Description', name: 'description', widget: 'string' } + - { label: 'Body', name: 'body', widget: 'markdown' } From 0bc4fb3fe308d6175cd64e94f70866c582c037bf Mon Sep 17 00:00:00 2001 From: Nicola B Date: Sat, 10 Jul 2021 22:12:50 -0400 Subject: [PATCH 7/7] Remove unused code --- src/components/posts/index.js | 1 - src/components/posts/post.module.css | 7 ------- 2 files changed, 8 deletions(-) diff --git a/src/components/posts/index.js b/src/components/posts/index.js index f6139fb7..aa992afd 100644 --- a/src/components/posts/index.js +++ b/src/components/posts/index.js @@ -1,7 +1,6 @@ import React from 'react' // import styles from './post.module.css' import { Link } from 'gatsby' -// import { parameterize } from '../../utils/helpers' const Post = ({ post }) => (
diff --git a/src/components/posts/post.module.css b/src/components/posts/post.module.css index 5c289102..e69de29b 100644 --- a/src/components/posts/post.module.css +++ b/src/components/posts/post.module.css @@ -1,7 +0,0 @@ -.post { - padding-bottom: 1em; -} - -.date { - padding-left: 1em; -}