├── .gitignore
├── LICENSE
├── README.md
├── gatsby-config.js
├── gatsby-node.js
├── netlify.toml
├── package-lock.json
├── package.json
├── src
├── cms
│ ├── cms.js
│ └── preview-templates
│ │ └── BlogPostPreview.js
├── components
│ ├── Navbar.js
│ ├── RelatedPostsSection.js
│ ├── colors.js
│ ├── footer.js
│ ├── head.js
│ ├── icons.js
│ ├── images
│ │ ├── logo-filled.png
│ │ └── touch
│ │ │ ├── apple-launch-img.png
│ │ │ ├── apple-touch-icon-180x180.png
│ │ │ ├── touch-icon-144x144.png
│ │ │ └── touch-icon-192x192.png
│ ├── rounded-line.js
│ ├── socialMediaButtons.js
│ └── util.js
├── layouts
│ ├── index.js
│ └── style.css
├── pages
│ ├── 404.js
│ ├── index.js
│ ├── its-night-and-theyre-sleeping.md
│ ├── my-succulents-are-doing-just-fine.md
│ ├── so-many-shades-of-green.md
│ ├── some-are-spiky-some-are-smooth.md
│ └── wait-one-of-them-looks-wrinkly.md
└── templates
│ └── blog-post.js
├── static
├── admin
│ └── config.yml
├── favicon.ico
├── img
│ ├── averie-woodard-111823-unsplash.jpg
│ ├── averie-woodard-111829-unsplash.jpg
│ ├── averie-woodard-111831-unsplash.jpg
│ ├── averie-woodard-181273-unsplash.jpg
│ ├── fletcher-clay-217243-unsplash.jpg
│ └── kace-rodriguez-82280-unsplash.jpg
└── preview.png
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project dependencies
2 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
3 | node_modules
4 | .cache/
5 |
6 | # Build directory
7 | public/
8 | static/admin/*.bundle.*
9 | .DS_Store
10 | yarn-error.log
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 gatsbyjs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Gatsby + Netlify (CMS) blog template
2 |
3 | ### Preview the template
4 | Here! [https://gatsby-netlify-cms-blog.netlify.com/](https://gatsby-netlify-cms-blog.netlify.com/)
5 |
6 | 
7 |
8 | ## Quick start
9 |
10 | #### Download it and run it on your local machine
11 |
12 | If you have yet to use Gatsby, install the CLI tool [gatsby-cli](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-cli)
13 |
14 | ```
15 | npm install --global gatsby-cli
16 | ```
17 | (and if you've never used npm, click [here](https://www.npmjs.com/get-npm))
18 |
19 | In terminal:
20 | ```
21 | git clone https://github.com/cjimmy/gatsby-netlify-cms-blog
22 | cd gatsby-netlify-cms-blog
23 | yarn install
24 | gatsby develop
25 | ```
26 |
27 | ### Deploy it
28 | [](https://app.netlify.com/start/deploy?repository=https://github.com/cjimmy/gatsby-netlify-cms-blog)
29 |
30 | ☝️ _What happens when you click on the button?_ It takes you to Netlify, where you have to click a few more things before anything real happens. (It clones this repo, and then deploys it using Netlify to the real internet.) But go ahead and deploy this site (assuming you have a Github account). This start is made for Netlify, so this button isn't just here as any hosting/deployment solution.
31 |
32 | ### Login and write a post
33 | 1. In Netlify web interface, go to the `Identity` section and click `Enable Identity`, allowing you to sign in to the CMS.
34 | 2. In Netlify, **Settings > Identity > Services** click on `Enable Git Gateway`. This is necessary to log in to the CMS. (otherwise you'll get an error `Unexpected token < in JSON at position 0`)
35 | 3. The CMS editor is located at `[YOUR_NETLIFY_SITE].netlify.com/admin/` where you can now sign up for a login.
36 |
37 | ## About
38 | This is a simple blog template based on [Gatsby](https://www.gatsbyjs.org/), and [Netlify CMS](https://www.netlifycms.org)
39 |
40 | It follows the [JAMstack architecture](https://jamstack.org) by using Git as a single source of truth, and [Netlify](https://www.netlify.com) for continuous deployment, and CDN distribution.
41 |
42 | It is largely based on @AustinGreen's [gatsby-start-netlify-cms](https://github.com/AustinGreen/gatsby-starter-netlify-cms) but a little more opinionated and different visual design.
43 |
44 | Some notable structural changes:
45 | * **_Styled Components_ instead of inline styles:** Gatsby likes to inline css styles. I much prefer [styled components](https://www.styled-components.com/) which Gatsby neatly has a module for.
46 | * **Removes Sass** – because we already have _one_ CSS module.
47 | * **Adds react-flexbox-grid** – for a grid system. Not necessary for the example, just makes things pretty.
48 | * **Adds fields to frontmatter** – to have an image for the blog post, add authors, and to fill out the
tag to make it social media friendly. (The frontmatter of a post is kinda like the meta info + head).
49 | * **Removes tag pages** – and instead queries for the top 3 most recent posts that share a common tag.
50 |
51 | ### Other resources and info
52 | * **Gatsby documentation** (v1, not v2):
53 | * **Netlify documentation** (sans CMS):
54 | * **[Netlify CMS Quick Start Guide]** (https://www.netlifycms.org/docs/quick-start/#authentication)
55 |
56 | ## Advanced
57 |
58 | ### Github authentication
59 | Netlify allows [authentication via Github](https://www.netlifycms.org/docs/authentication-backends/) rather than the Netlify identity system. To do this, you have to go into the _organization's_ settings. (Github has a lot of different Settings pages.)
60 |
61 | In there, on the side menu, you'll see a section for OAuth apps.
62 | * `Application name` is what will be shown to users authenticating
63 | * `Homepage URL` is the homepage of the app
64 | * `Application Description` is a description
65 | * `Authorization callback URL` for Netlify should be `https://api.netlify.com/auth/done` per their docs
66 |
67 | With this, you'll get `Client ID` and `Client Secret` that you'll use in the Netlify interface
68 |
69 | ### Add comments
70 | Even though it's a static site, you can take advantage of the continuous deployment: [https://jamstack-comments.netlify.com/](https://jamstack-comments.netlify.com/)
71 |
72 | ### Paginate front page
73 | TODO
74 |
75 | ### Add a subscribe form
76 | Using lambdas hosted on Netlify
77 |
--------------------------------------------------------------------------------
/gatsby-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | siteMetadata: {
3 | title: 'Gatsby-netlify-cms-starter',
4 | },
5 | plugins: [
6 | 'gatsby-plugin-react-helmet',
7 | `gatsby-plugin-styled-components`,
8 | {
9 | resolve: 'gatsby-source-filesystem',
10 | options: {
11 | path: `${__dirname}/src/pages`,
12 | name: 'pages',
13 | },
14 | },
15 | 'gatsby-plugin-sharp',
16 | 'gatsby-transformer-sharp',
17 | {
18 | resolve: 'gatsby-transformer-remark',
19 | options: {
20 | plugins: [],
21 | },
22 | },
23 | {
24 | resolve: 'gatsby-plugin-netlify-cms',
25 | options: {
26 | modulePath: `${__dirname}/src/cms/cms.js`,
27 | },
28 | },
29 | 'gatsby-plugin-netlify', // make sure to keep it last in the array
30 | ],
31 | }
32 |
--------------------------------------------------------------------------------
/gatsby-node.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { createFilePath } = require('gatsby-source-filesystem')
3 |
4 | exports.createPages = ({ boundActionCreators, graphql }) => {
5 | const { createPage } = boundActionCreators
6 |
7 | return graphql(`
8 | {
9 | allMarkdownRemark(limit: 1000) {
10 | edges {
11 | node {
12 | id
13 | fields {
14 | slug
15 | }
16 | frontmatter {
17 | tags
18 | templateKey
19 | }
20 | }
21 | }
22 | }
23 | }
24 | `).then(result => {
25 | if (result.errors) {
26 | result.errors.forEach(e => console.error(e.toString()))
27 | return Promise.reject(result.errors)
28 | }
29 |
30 | const posts = result.data.allMarkdownRemark.edges
31 |
32 | posts.forEach(edge => {
33 | const id = edge.node.id
34 | const slug = edge.node.fields.slug
35 | const tags = edge.node.frontmatter.tags
36 | createPage({
37 | path: slug,
38 | tags: tags,
39 | component: path.resolve(
40 | `src/templates/${String(edge.node.frontmatter.templateKey)}.js`
41 | ),
42 | // additional data can be passed via context
43 | // id and tags gets passed to the graphql query as parameters
44 | context: {
45 | id,
46 | tags
47 | },
48 | })
49 | })
50 | })
51 | }
52 |
53 | exports.onCreateNode = ({ node, boundActionCreators, getNode }) => {
54 | const { createNodeField } = boundActionCreators
55 |
56 | if (node.internal.type === `MarkdownRemark`) {
57 | const value = createFilePath({ node, getNode })
58 | createNodeField({
59 | name: `slug`,
60 | node,
61 | value,
62 | })
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | # config file for netlify to build the project
2 |
3 | #build folder to publish + build command
4 | [build]
5 | publish = "public"
6 | command = "yarn build"
7 |
8 | #build tool versions
9 | [build.environment]
10 | YARN_VERSION = "1.5.1"
11 | YARN_FLAGS = "--no-ignore-optional"
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-netlify-cms",
3 | "description": "Just a starter",
4 | "version": "1.1.3",
5 | "author": "By The Bay",
6 | "dependencies": {
7 | "gatsby": "^1.9.273",
8 | "gatsby-link": "^1.6.37",
9 | "gatsby-plugin-netlify": "^1.0.19",
10 | "gatsby-plugin-netlify-cms": "^1.0.9",
11 | "gatsby-plugin-react-helmet": "^2.0.5",
12 | "gatsby-plugin-sass": "^1.0.17",
13 | "gatsby-plugin-sharp": "^1.6.48",
14 | "gatsby-plugin-styled-components": "^2.0.11",
15 | "gatsby-remark-images": "^1.5.50",
16 | "gatsby-source-filesystem": "^1.5.23",
17 | "gatsby-transformer-remark": "^1.7.44",
18 | "gatsby-transformer-sharp": "^1.6.27",
19 | "immutable": "^3.8.2",
20 | "lodash": "^4.17.5",
21 | "lodash-webpack-plugin": "^0.11.4",
22 | "netlify-cms": "^1.7.0",
23 | "prop-types": "^15.6.0",
24 | "react": "^16.4.1",
25 | "react-flexbox-grid": "^2.1.2",
26 | "react-helmet": "^5.2.0",
27 | "slate": "^0.34.2",
28 | "styled-components": "^3.3.3",
29 | "uuid": "^3.2.1"
30 | },
31 | "keywords": [
32 | "gatsby"
33 | ],
34 | "license": "MIT",
35 | "main": "n/a",
36 | "scripts": {
37 | "start": "npm run develop",
38 | "build": "gatsby build",
39 | "develop": "gatsby develop",
40 | "serve": "gatsby serve",
41 | "format": "prettier --trailing-comma es5 --no-semi --single-quote --write \"{gatsby-*.js,src/**/*.js}\"",
42 | "test": "echo \"Error: no test specified\" && exit 1"
43 | },
44 | "devDependencies": {
45 | "prettier": "^1.7.4"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/cms/cms.js:
--------------------------------------------------------------------------------
1 | import CMS from 'netlify-cms'
2 | import BlogPostPreview from './preview-templates/BlogPostPreview'
3 |
4 |
5 | //-- path is absolute from built project
6 | //-- Gatsby compiles .css files to `styles.css` despite the file in `layouts/`
7 | //-- being named 'style.css'
8 | CMS.registerPreviewStyle('/styles.css')
9 | //-- Tells Netlify CMS what component is rendered for template key 'blog'
10 | CMS.registerPreviewTemplate('blog', BlogPostPreview)
11 |
--------------------------------------------------------------------------------
/src/cms/preview-templates/BlogPostPreview.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { BlogPostTemplate } from '../../templates/blog-post'
4 |
5 | //-- What Netlify CMS uses to render the preview pane
6 | const BlogPostPreview = ({ entry, widgetFor }) => {
7 | console.log(entry)
8 | return(
9 |
20 | )
21 | }
22 |
23 | //-- getIn is from immutable.js
24 | BlogPostPreview.propTypes = {
25 | entry: PropTypes.shape({
26 | getIn: PropTypes.func,
27 | }),
28 | widgetFor: PropTypes.func,
29 | }
30 |
31 | export default BlogPostPreview
32 |
--------------------------------------------------------------------------------
/src/components/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Link from 'gatsby-link'
3 | import Color from './colors'
4 | import styled from 'styled-components'
5 | import logo from './images/logo-filled.png'
6 |
7 | const Nav = styled.div`
8 | position: sticky;
9 | top: 0;
10 | background-color: ${Color('pink')};
11 | height: 50px;
12 | z-index: 10;
13 | width: 100%;
14 | display: flex;
15 | flex-direction: row;
16 | align-items: center;
17 | box-shadow: 0 3px 10px rgba(0,0,0,0.05);
18 | `
19 | const InnerContainer = styled.div`
20 | width: 100%;
21 | display: flex;
22 | justify-content: space-between;
23 | align-items: center;
24 | `
25 | const Flex = styled.div`
26 | display: flex;
27 | `
28 |
29 | const Padding = styled.div`
30 | width: 40px;
31 | `
32 |
33 | const Logo = styled.img`
34 | height: 30px;
35 | width: auto;
36 | `
37 |
38 | const NavLink = styled(Link)`
39 | text-decoration: none;
40 | color: black;
41 | padding: 3px 20px;
42 | `
43 |
44 | const Navbar = (props) => {
45 | const links = navLinks.map( (link,i) => {
46 | return(
47 |