├── .editoconfig ├── .eslintrc.json ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── config.js ├── gatsby-browser.js ├── gatsby-config.js ├── gatsby-node.js ├── gatsby-ssr.js ├── gatsby ├── createCategories.js ├── createPages.js ├── createPosts.js ├── createTags.js └── createUsers.js ├── img ├── screenshot-demo.gatsby-wpgraphql-blog-example.netlify.com.png └── screenshot-demo.wpgraphql.com.png ├── package-lock.json ├── package.json ├── src ├── components │ ├── CategoriesWidget │ │ └── index.js │ ├── HomepageLayout │ │ └── index.js │ ├── PostEntry │ │ └── index.js │ ├── PostEntryMeta │ │ └── index.js │ ├── RecentCommentsWidget │ │ └── index.js │ ├── RecentPostsWidget │ │ └── index.js │ ├── Seo │ │ └── index.js │ ├── SiteHeader │ │ └── index.js │ ├── SiteLayout.js │ ├── SiteMenu │ │ └── index.js │ └── style.css ├── images │ ├── gatsby-astronaut.png │ ├── gatsby-icon.png │ ├── gatsby-logo.png │ └── wpgraphql-logo.png ├── layouts │ └── SiteLayout │ │ └── index.js ├── pages │ └── 404.js ├── templates │ ├── blog.js │ ├── categoriesArchive.js │ ├── category.js │ ├── page.js │ ├── post.js │ ├── tag.js │ ├── tagsArchive.js │ └── user.js └── utils │ └── index.js └── yarn.lock /.editoconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": [ 4 | "google", 5 | "eslint:recommended", 6 | "plugin:flowtype/recommended", 7 | "plugin:react/recommended", 8 | "prettier", 9 | "prettier/flowtype", 10 | "prettier/react" 11 | ], 12 | "plugins": ["flowtype", "prettier", "react"], 13 | "parserOptions": { 14 | "ecmaVersion": 2016, 15 | "sourceType": "module", 16 | "ecmaFeatures": { 17 | "jsx": true 18 | } 19 | }, 20 | "env": { 21 | "browser": true, 22 | "es6": true, 23 | "node": true, 24 | "jest": true 25 | }, 26 | "globals": { 27 | "before": true, 28 | "spyOn": true, 29 | "__PATH_PREFIX__": true 30 | }, 31 | "rules": { 32 | "arrow-body-style": [ 33 | "error", 34 | "as-needed", 35 | { "requireReturnForObjectLiteral": true } 36 | ], 37 | "consistent-return": ["error"], 38 | "no-console": "off", 39 | "no-inner-declarations": "off", 40 | "prettier/prettier": "error", 41 | "quotes": ["error", "backtick"], 42 | "react/display-name": "off", 43 | "react/jsx-key": "warn", 44 | "react/no-unescaped-entities": "warn", 45 | "react/prop-types": "off", 46 | "require-jsdoc": "off", 47 | "valid-jsdoc": "off" 48 | }, 49 | "overrides": [ 50 | { 51 | "files": [ 52 | "packages/**/gatsby-browser.js", 53 | "packages/gatsby/cache-dir/**/*" 54 | ], 55 | "env": { 56 | "browser": true 57 | }, 58 | "globals": { 59 | "___loader": false, 60 | "___emitter": false 61 | } 62 | }, 63 | { 64 | "files": ["**/cypress/integration/**/*", "**/cypress/support/**/*"], 65 | "globals": { 66 | "cy": false, 67 | "Cypress": false 68 | } 69 | } 70 | ], 71 | "settings": { 72 | "react": { 73 | "version": "16.4.2" 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | .idea 64 | 65 | # Yarn 66 | yarn-error.log 67 | .pnp/ 68 | .pnp.js 69 | # Yarn Integrity file 70 | .yarn-integrity 71 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 10.15.1 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.min.js 2 | **/node_modules/** 3 | flow-typed 4 | 5 | # webfont demo styles 6 | **/specimen_files 7 | 8 | # built sites 9 | benchmarks/**/public 10 | e2e-tests/**/public 11 | examples/**/public 12 | integration-tests/**/public 13 | www/public 14 | 15 | # cache-dirs 16 | **/.cache 17 | 18 | # ignore built packages 19 | packages/**/*.js 20 | !packages/gatsby/cache-dir/**/*.js 21 | !packages/*/src/**/*.js 22 | packages/gatsby/cache-dir/commonjs/**/*.js 23 | 24 | # fixtures 25 | **/__testfixtures__/** 26 | **/__tests__/fixtures/** 27 | 28 | infrastructure 29 | 30 | # coverage 31 | coverage 32 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": false, 4 | "tabWidth": 2, 5 | "trailingComma": "es5" 6 | } 7 | -------------------------------------------------------------------------------- /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 | # DEPRECATED 2 | ---- 3 | This repository serves as an example of how to build a Gatsby site using WordPress as the CMS, WPGraphQL as the API and Gatsby Source GraphQL as the data source. 4 | 5 | This example repo should no longer be considered "the best" way to use Gatsby and GraphQL anymore. Instead of using Gatsby Source GraphQL, we recommend using [Gatsby Source WordPress Experimental](https://github.com/gatsbyjs/gatsby-source-wordpress-experimental), which will soon become the official Gatsby Source WordPress. 6 | 7 | You can read more about why previous versions of Gatsby Source WordPress and Gatsby Source GraphQL are not ideal, and why Gatsby is investing in the new Gatsby Source WordPress Experimental plugin in this WPTavern article: https://wptavern.com/new-gatsby-source-wordpress-plugin-now-in-beta 8 | 9 | ---- 10 | 11 |

12 | 13 | Gatsby 14 | 15 | 16 | Gatsby 17 | 18 |

19 |

20 | Gatsby + WPGraphQL Blog Example 21 |

22 | 23 | This is an example Gatsby site using WPGraphQL as the source. 24 | 25 | ## WordCamp Talk 26 | This repo was created specifically for showcasing the capabilities of WPGraphQL and how it can be used in many ways. One particular use is with GatsbyJS. The WordCamp talk this repo was created for can be seen here: https://wordpress.tv/2019/03/08/jason-bahl-building-static-sites-with-wordpress-gatsby-and-wpgraphql/ 27 | 28 | ## Setup 29 | 30 | Quick video showing setup of the Gatsby site locally: https://www.youtube.com/watch?v=QkIuuZ5gZNk 31 | 32 | ## WordPress Source 33 | 34 | The WordPress where the content is managed lives here: [https://demo.wpgraphql.com](https://demo.wpgraphql.com) 35 | 36 | ![Screenshot of the WordPress source site](./img/screenshot-demo.wpgraphql.com.png) 37 | 38 | 39 | ## Gatsby Site 40 | 41 | The Live Gatsby site is at: [https://gatsby-wpgraphql-blog-example.netlify.com/](https://gatsby-wpgraphql-blog-example.netlify.com/) 42 | 43 | ![Screenshot of the Gatsby site](./img/screenshot-demo.gatsby-wpgraphql-blog-example.netlify.com.png) 44 | 45 | ### Features 46 | 47 | Below are features of the Gatsby site that are all sourced via WPGraphQL Queries, so the data is 48 | managed in WordPress, but is pulled into the Gatsby site and rendered there: 49 | 50 | - :white_check_mark: Menus 51 | - :white_check_mark: Pages 52 | - :white_check_mark: Paginated Blogroll/homepage 53 | - :white_check_mark: Single Posts 54 | - :white_check_mark: Authors 55 | - :white_check_mark: Categories 56 | - :white_check_mark: Tags 57 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | wordPressUrl: `https://demo.wpgraphql.com`, 3 | } 4 | 5 | export default config 6 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Browser APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/browser-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Gatsby WPGraphQL Source Demo`, 4 | description: `Gatsby demo site with WPGraphQL as the source.`, 5 | author: `@wpgraphql`, 6 | wordPressUrl: `https://wpgraphqldemo.wpengine.com`, 7 | }, 8 | plugins: [ 9 | // Include Ant Design component library. 10 | { 11 | resolve: `gatsby-plugin-antd`, 12 | options: { 13 | style: true, 14 | }, 15 | }, 16 | { 17 | resolve: `gatsby-plugin-less`, 18 | options: { 19 | javascriptEnabled: true, 20 | modifyVars: { 21 | // DEFAULTS FOR ANT DESIGN 22 | // Full list of variables can be found here: 23 | // https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less 24 | // @primary-color: #1890ff; 25 | "layout-header-background": `#0e2339`, 26 | // primary color for all components 27 | "primary-color": `#1890ff`, 28 | // @link-color: #1890ff; 29 | "link-color": `#1890ff`, 30 | // @success-color: #52c41a; 31 | "success-color": `#52c41a`, 32 | // @warning-color: #faad14; 33 | "warning-color": `#faad14`, 34 | // @error-color: #f5222d; 35 | "error-color": `#f5222d`, 36 | // @font-size-base: 14px; 37 | // major text font size 38 | "font-size-base": `16px`, 39 | // @heading-color: rgba(0, 0, 0, .85); 40 | "heading-color": `rgba(0, 0, 0, .85)`, 41 | // @text-color: rgba(0, 0, 0, .65); 42 | "text-color": `rgba(0, 0, 0, .65)`, 43 | // @text-color-secondary : rgba(0, 0, 0, .45); 44 | "text-color-secondary": `rgba(0, 0, 0, .45)`, 45 | // @disabled-color : rgba(0, 0, 0, .25); 46 | "disabled-color": `rgba(0, 0, 0, .25)`, 47 | // @border-radius-base: 4px; 48 | "border-radius-base": `4px`, 49 | // @border-color-base: #d9d9d9; 50 | "border-color-base": `#d9d9d9`, 51 | // @box-shadow-base: 0 2px 8px rgba(0, 0, 0, .15); 52 | "box-shadow-base": `0 2px 8px rgba(0, 0, 0, .15)`, 53 | }, 54 | }, 55 | }, 56 | // Setup WPGraphQL.com to be the source 57 | { 58 | resolve: `gatsby-source-graphql`, 59 | options: { 60 | // This type will contain remote schema Query type 61 | typeName: `WPGraphQL`, 62 | // This is field under which it's accessible 63 | fieldName: `wpgraphql`, 64 | // Url to query from 65 | url: `https://demo.wpgraphql.com/graphql`, 66 | }, 67 | }, 68 | `gatsby-plugin-react-helmet`, 69 | { 70 | resolve: `gatsby-source-filesystem`, 71 | options: { 72 | name: `images`, 73 | path: `${__dirname}/src/images`, 74 | }, 75 | }, 76 | `gatsby-transformer-sharp`, 77 | `gatsby-plugin-sharp`, 78 | { 79 | resolve: `gatsby-plugin-manifest`, 80 | options: { 81 | name: `gatsby-wpgraphql-starter`, 82 | short_name: `starter`, 83 | start_url: `/`, 84 | background_color: `#f0f2f5`, 85 | theme_color: `#001529`, 86 | display: `minimal-ui`, 87 | icon: `src/images/wpgraphql-logo.png`, // This path is relative to the root of the site. 88 | }, 89 | }, 90 | // this (optional) plugin enables Progressive Web App + Offline functionality 91 | // To learn more, visit: https://gatsby.app/offline 92 | `gatsby-plugin-offline`, 93 | ], 94 | } 95 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | const createPosts = require(`./gatsby/createPosts`) 2 | const createPages = require(`./gatsby/createPages`) 3 | const createUsers = require(`./gatsby/createUsers`) 4 | const createCategories = require(`./gatsby/createCategories`) 5 | const createTags = require(`./gatsby/createTags`) 6 | 7 | exports.createPages = async ({ actions, graphql }) => { 8 | await createPosts({ actions, graphql }) 9 | await createPages({ actions, graphql }) 10 | await createUsers({ actions, graphql }) 11 | await createCategories({ actions, graphql }) 12 | await createTags({ actions, graphql }) 13 | } 14 | -------------------------------------------------------------------------------- /gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /gatsby/createCategories.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | module.exports = async ({ actions, graphql }) => { 3 | const GET_CATEGORIES = ` 4 | query GET_CATEGORIES($first: Int, $after: String) { 5 | wpgraphql { 6 | categories(first: $first, after: $after) { 7 | pageInfo { 8 | hasNextPage 9 | endCursor 10 | } 11 | nodes { 12 | id 13 | categoryId 14 | slug 15 | } 16 | } 17 | } 18 | } 19 | ` 20 | const { createPage } = actions 21 | const allTags = [] 22 | const fetchTags = async variables => 23 | await graphql(GET_CATEGORIES, variables).then(({ data }) => { 24 | const { 25 | wpgraphql: { 26 | categories: { 27 | nodes, 28 | pageInfo: { hasNextPage, endCursor }, 29 | }, 30 | }, 31 | } = data 32 | nodes.map(category => { 33 | allTags.push(category) 34 | }) 35 | if (hasNextPage) { 36 | return fetchTags({ first: 100, after: endCursor }) 37 | } 38 | return allTags 39 | }) 40 | 41 | await fetchTags({ first: 100, after: null }).then(allTags => { 42 | const categoryTemplate = path.resolve(`./src/templates/category.js`) 43 | 44 | allTags.map(category => { 45 | console.log(`create category: ${category.slug}`) 46 | createPage({ 47 | path: `/blog/category/${category.slug}`, 48 | component: categoryTemplate, 49 | context: category, 50 | }) 51 | }) 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /gatsby/createPages.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | module.exports = async ({ actions, graphql }) => { 3 | const GET_PAGES = ` 4 | query GET_PAGES($first:Int $after:String){ 5 | wpgraphql { 6 | pages( 7 | first: $first 8 | after: $after 9 | where: { 10 | parent: null 11 | } 12 | ) { 13 | pageInfo { 14 | endCursor 15 | hasNextPage 16 | } 17 | nodes { 18 | id 19 | uri 20 | pageId 21 | title 22 | } 23 | } 24 | } 25 | } 26 | ` 27 | const { createPage } = actions 28 | const allPages = [] 29 | const fetchPages = async variables => 30 | await graphql(GET_PAGES, variables).then(({ data }) => { 31 | const { 32 | wpgraphql: { 33 | pages: { 34 | nodes, 35 | pageInfo: { hasNextPage, endCursor }, 36 | }, 37 | }, 38 | } = data 39 | nodes.map(page => { 40 | allPages.push(page) 41 | }) 42 | if (hasNextPage) { 43 | return fetchPages({ first: variables.first, after: endCursor }) 44 | } 45 | return allPages 46 | }) 47 | 48 | await fetchPages({ first: 100, after: null }).then(allPages => { 49 | const pageTemplate = path.resolve(`./src/templates/page.js`) 50 | 51 | allPages.map(page => { 52 | console.log(`create page: ${page.uri}`) 53 | createPage({ 54 | path: `/${page.uri}`, 55 | component: pageTemplate, 56 | context: page, 57 | }) 58 | }) 59 | }) 60 | } 61 | -------------------------------------------------------------------------------- /gatsby/createPosts.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | module.exports = async ({ actions, graphql }) => { 3 | const GET_POSTS = ` 4 | query GET_POSTS($first:Int $after:String){ 5 | wpgraphql { 6 | posts( 7 | first: $first 8 | after:$after 9 | ) { 10 | pageInfo { 11 | endCursor 12 | hasNextPage 13 | } 14 | nodes { 15 | id 16 | uri 17 | postId 18 | title 19 | } 20 | } 21 | } 22 | } 23 | ` 24 | const { createPage } = actions 25 | const allPosts = [] 26 | const blogPages = [] 27 | let pageNumber = 0 28 | const fetchPosts = async variables => 29 | await graphql(GET_POSTS, variables).then(({ data }) => { 30 | const { 31 | wpgraphql: { 32 | posts: { 33 | nodes, 34 | pageInfo: { hasNextPage, endCursor }, 35 | }, 36 | }, 37 | } = data 38 | 39 | const nodeIds = nodes.map(node => node.postId) 40 | const blogTemplate = path.resolve(`./src/templates/blog.js`) 41 | const blogPagePath = !variables.after ? `/` : `/page/${pageNumber}` 42 | 43 | blogPages[pageNumber] = { 44 | path: blogPagePath, 45 | component: blogTemplate, 46 | context: { 47 | ids: nodeIds, 48 | pageNumber: pageNumber, 49 | hasNextPage: hasNextPage, 50 | }, 51 | ids: nodeIds, 52 | } 53 | nodes.map(post => { 54 | allPosts.push(post) 55 | }) 56 | if (hasNextPage) { 57 | pageNumber++ 58 | return fetchPosts({ first: 12, after: endCursor }) 59 | } 60 | return allPosts 61 | }) 62 | 63 | await fetchPosts({ first: 12, after: null }).then(allPosts => { 64 | const postTemplate = path.resolve(`./src/templates/post.js`) 65 | 66 | blogPages.map(blogPage => { 67 | console.log(`createBlogPage ${blogPage.context.pageNumber}`) 68 | createPage(blogPage) 69 | }) 70 | 71 | allPosts.map(post => { 72 | console.log(`create post: ${post.uri}`) 73 | createPage({ 74 | path: `/blog/${post.uri}/`, 75 | component: postTemplate, 76 | context: post, 77 | }) 78 | }) 79 | }) 80 | } 81 | -------------------------------------------------------------------------------- /gatsby/createTags.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | module.exports = async ({ actions, graphql }) => { 3 | const GET_TAGS = ` 4 | query GET_TAGS($first: Int, $after: String) { 5 | wpgraphql { 6 | tags(first: $first, after: $after) { 7 | pageInfo { 8 | hasNextPage 9 | endCursor 10 | } 11 | nodes { 12 | id 13 | tagId 14 | slug 15 | } 16 | } 17 | } 18 | } 19 | ` 20 | const { createPage } = actions 21 | const allTags = [] 22 | const fetchTags = async variables => 23 | await graphql(GET_TAGS, variables).then(({ data }) => { 24 | const { 25 | wpgraphql: { 26 | tags: { 27 | nodes, 28 | pageInfo: { hasNextPage, endCursor }, 29 | }, 30 | }, 31 | } = data 32 | nodes.map(tag => { 33 | allTags.push(tag) 34 | }) 35 | if (hasNextPage) { 36 | return fetchTags({ first: 100, after: endCursor }) 37 | } 38 | return allTags 39 | }) 40 | 41 | await fetchTags({ first: 100, after: null }).then(allTags => { 42 | const tagTemplate = path.resolve(`./src/templates/tag.js`) 43 | 44 | allTags.map(tag => { 45 | console.log(`create tag: ${tag.slug}`) 46 | createPage({ 47 | path: `/blog/tag/${tag.slug}`, 48 | component: tagTemplate, 49 | context: tag, 50 | }) 51 | }) 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /gatsby/createUsers.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) 2 | module.exports = async ({ actions, graphql }) => { 3 | const GET_USERS = ` 4 | query GET_USERS($first: Int) { 5 | wpgraphql { 6 | users(first: $first) { 7 | pageInfo { 8 | hasNextPage 9 | endCursor 10 | } 11 | nodes { 12 | id 13 | userId 14 | slug 15 | } 16 | } 17 | } 18 | } 19 | ` 20 | const { createPage } = actions 21 | const allUsers = [] 22 | const fetchUsers = async variables => 23 | await graphql(GET_USERS, variables).then(({ data }) => { 24 | const { 25 | wpgraphql: { 26 | users: { 27 | nodes, 28 | pageInfo: { hasNextPage, endCursor }, 29 | }, 30 | }, 31 | } = data 32 | nodes.map(user => { 33 | allUsers.push(user) 34 | }) 35 | if (hasNextPage) { 36 | return fetchUsers({ first: 100, after: endCursor }) 37 | } 38 | return allUsers 39 | }) 40 | 41 | await fetchUsers({ first: 100, after: null }).then(allUsers => { 42 | const userTemplate = path.resolve(`./src/templates/user.js`) 43 | 44 | allUsers.map(user => { 45 | console.log(`create user: ${user.slug}`) 46 | createPage({ 47 | path: `/author/${user.slug}`, 48 | component: userTemplate, 49 | context: user, 50 | }) 51 | }) 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /img/screenshot-demo.gatsby-wpgraphql-blog-example.netlify.com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp-graphql/gatsby-wpgraphql-blog-example/6e31fb099be283f385f751315828e92effc77cf9/img/screenshot-demo.gatsby-wpgraphql-blog-example.netlify.com.png -------------------------------------------------------------------------------- /img/screenshot-demo.wpgraphql.com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp-graphql/gatsby-wpgraphql-blog-example/6e31fb099be283f385f751315828e92effc77cf9/img/screenshot-demo.wpgraphql.com.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-default", 3 | "private": true, 4 | "description": "A simple starter to get up and developing quickly with Gatsby", 5 | "version": "0.1.0", 6 | "author": "Kyle Mathews ", 7 | "dependencies": { 8 | "antd": "^3.12.3", 9 | "babel-eslint": "^10.0.1", 10 | "eslint": "^5.6.1", 11 | "eslint-config-google": "^0.10.0", 12 | "eslint-config-prettier": "^3.1.0", 13 | "eslint-plugin-flow-vars": "^0.5.0", 14 | "eslint-plugin-flowtype": "^2.50.3", 15 | "eslint-plugin-import": "^2.14.0", 16 | "eslint-plugin-jsx-a11y": "^6.1.2", 17 | "eslint-plugin-prettier": "^3.0.0", 18 | "eslint-plugin-react": "^7.11.1", 19 | "gatsby": "^2.0.76", 20 | "gatsby-cli": "^2.4.9", 21 | "gatsby-image": "^2.0.20", 22 | "gatsby-plugin-antd": "^2.0.2", 23 | "gatsby-plugin-less": "^2.0.11", 24 | "gatsby-plugin-manifest": "^2.0.9", 25 | "gatsby-plugin-offline": "^2.0.23", 26 | "gatsby-plugin-react-helmet": "^3.0.2", 27 | "gatsby-plugin-sharp": "^2.0.14", 28 | "gatsby-plugin-typography": "^2.2.7", 29 | "gatsby-source-filesystem": "^2.0.8", 30 | "gatsby-source-graphql": "^2.0.8", 31 | "gatsby-transformer-sharp": "^2.1.8", 32 | "less": "^3.9.0", 33 | "lodash": "^4.17.11", 34 | "moment": "^2.24.0", 35 | "prop-types": "^15.6.2", 36 | "react": "^16.6.3", 37 | "react-dom": "^16.6.3", 38 | "react-helmet": "^5.2.0" 39 | }, 40 | "keywords": [ 41 | "gatsby" 42 | ], 43 | "license": "MIT", 44 | "scripts": { 45 | "build": "gatsby build", 46 | "develop": "gatsby develop", 47 | "start": "npm run develop", 48 | "format": "prettier --write \"src/**/*.js\"", 49 | "test": "echo \"Write tests! -> https://gatsby.app/unit-testing\"" 50 | }, 51 | "devDependencies": { 52 | "prettier": "^1.15.2" 53 | }, 54 | "repository": { 55 | "type": "git", 56 | "url": "https://github.com/gatsbyjs/gatsby-starter-default" 57 | }, 58 | "bugs": { 59 | "url": "https://github.com/gatsbyjs/gatsby/issues" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/components/CategoriesWidget/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StaticQuery, graphql, Link } from "gatsby" 3 | 4 | const QUERY = graphql` 5 | { 6 | wpgraphql { 7 | categories { 8 | nodes { 9 | name 10 | slug 11 | link 12 | } 13 | } 14 | } 15 | } 16 | ` 17 | 18 | const CategoriesWidget = () => ( 19 | { 22 | return ( 23 |
24 |

Categories

25 |
    26 | {data.wpgraphql.categories.nodes.map(category => { 27 | return ( 28 |
  • 29 | {category.name} 30 |
  • 31 | ) 32 | })} 33 |
34 |
35 | ) 36 | }} 37 | /> 38 | ) 39 | 40 | export default CategoriesWidget 41 | -------------------------------------------------------------------------------- /src/components/HomepageLayout/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import SiteHeader from "../../components/SiteHeader" 3 | import { Layout, Row, Col, Button } from "antd" 4 | import wpgraphqlLogo from "../../images/wpgraphql-logo.png" 5 | import gatsbyLogo from "../../images/gatsby-logo.png" 6 | 7 | const { Content } = Layout 8 | 9 | const HomepageLayout = ({ pageNumber, location, children }) => ( 10 | 11 | 12 | {!pageNumber ? ( 13 | 18 | 19 |

Gatsby + WPGraphQL Demo

20 | 26 | 27 | 28 | 29 | 30 | Gatsby Logo 35 | 36 | 37 | 38 | + 39 | 40 | 41 | 42 | WPGraphQL Logo 47 | 48 | 49 | 50 | 51 | 52 |
53 |

54 | This is an example of a Gatsby + WPGraphQL site. 55 |

56 |

57 | The content is generated using{` `} 58 | 63 | WPGraphQL 64 | 65 | {` `}to pull content from{` `} 66 | demo.wpgraphql.com 67 |

68 | 73 | 76 | 77 | {` `} 78 | 83 | 86 | 87 | {` `} 88 | 93 | 96 | 97 |
98 | 99 |
100 | ) : null} 101 | 109 | 110 | 117 | {children} 118 | 119 | 120 | 121 |
122 | ) 123 | 124 | export default HomepageLayout 125 | -------------------------------------------------------------------------------- /src/components/PostEntry/index.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from "react" 2 | import { Link, graphql } from "gatsby" 3 | import { Row, Col, Divider } from "antd" 4 | import config from "../../../config" 5 | import PostEntryMeta from "../PostEntryMeta" 6 | 7 | const PostEntry = ({ post }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | {post.title} 17 |

18 |
23 | 24 | 25 | 26 | 27 | ) 28 | } 29 | 30 | export default PostEntry 31 | 32 | export const query = graphql` 33 | fragment PostEntryFragment on WPGraphQL_Post { 34 | id 35 | title 36 | uri 37 | slug 38 | date 39 | content: excerpt 40 | author { 41 | name 42 | slug 43 | avatar(size: 100) { 44 | url 45 | } 46 | } 47 | } 48 | ` 49 | -------------------------------------------------------------------------------- /src/components/PostEntryMeta/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import moment from "moment/moment" 3 | import { Row, Col, Avatar } from "antd" 4 | import { Link } from "gatsby" 5 | 6 | const PostEntryMeta = ({ post }) => ( 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {post.author.name} 19 |
20 | {moment(post.date).format(`MMM Do YY`)} 21 | 22 |
23 | ) 24 | 25 | export default PostEntryMeta 26 | -------------------------------------------------------------------------------- /src/components/RecentCommentsWidget/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StaticQuery, graphql, Link } from "gatsby" 3 | import { createLocalLink } from "../../utils" 4 | 5 | const QUERY = graphql` 6 | { 7 | wpgraphql { 8 | comments(first: 5) { 9 | nodes { 10 | author { 11 | __typename 12 | ... on WPGraphQL_CommentAuthor { 13 | name 14 | } 15 | ... on WPGraphQL_User { 16 | name 17 | } 18 | } 19 | commentedOn { 20 | __typename 21 | ... on WPGraphQL_Post { 22 | id 23 | title 24 | link 25 | } 26 | ... on WPGraphQL_Page { 27 | id 28 | title 29 | link 30 | } 31 | } 32 | } 33 | } 34 | } 35 | } 36 | ` 37 | 38 | const RecentCommentsWidget = () => ( 39 | { 42 | return ( 43 |
44 |

Recent Comments

45 |
    46 | {data.wpgraphql.comments.nodes.map(comment => { 47 | if (`WPGraphQL_Post` === comment.commentedOn.__typename) { 48 | return ( 49 |
  • 50 | {comment.author.name} on{` `} 51 | 52 | {comment.commentedOn.title} 53 | 54 |
  • 55 | ) 56 | } 57 | return null; 58 | })} 59 |
60 |
61 | ) 62 | }} 63 | /> 64 | ) 65 | 66 | export default RecentCommentsWidget 67 | -------------------------------------------------------------------------------- /src/components/RecentPostsWidget/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StaticQuery, graphql, Link } from "gatsby" 3 | import { createLocalLink } from "../../utils" 4 | 5 | 6 | const QUERY = graphql` 7 | { 8 | wpgraphql { 9 | posts(first: 5) { 10 | nodes { 11 | id 12 | title 13 | link 14 | } 15 | } 16 | } 17 | } 18 | ` 19 | 20 | const RecentPostsWidget = () => ( 21 | { 24 | return ( 25 |
26 |

Recent Posts

27 |
    28 | {data.wpgraphql.posts.nodes.map(post => { 29 | return ( 30 |
  • 31 | {post.title} 32 |
  • 33 | ) 34 | })} 35 |
36 |
37 | ) 38 | }} 39 | /> 40 | ) 41 | 42 | export default RecentPostsWidget 43 | -------------------------------------------------------------------------------- /src/components/Seo/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import Helmet from "react-helmet" 4 | import { StaticQuery, graphql } from "gatsby" 5 | 6 | function Seo({ description, lang, meta, keywords, title }) { 7 | return ( 8 | { 11 | const metaDescription = 12 | description || data.site.siteMetadata.description 13 | return ( 14 | 0 56 | ? { 57 | name: `keywords`, 58 | content: keywords.join(`, `), 59 | } 60 | : [] 61 | ) 62 | .concat(meta)} 63 | /> 64 | ) 65 | }} 66 | /> 67 | ) 68 | } 69 | 70 | Seo.defaultProps = { 71 | lang: `en`, 72 | meta: [], 73 | keywords: [], 74 | } 75 | 76 | Seo.propTypes = { 77 | description: PropTypes.string, 78 | lang: PropTypes.string, 79 | meta: PropTypes.array, 80 | keywords: PropTypes.arrayOf(PropTypes.string), 81 | title: PropTypes.string.isRequired, 82 | } 83 | 84 | export default Seo 85 | 86 | const detailsQuery = graphql` 87 | query DefaultSEOQuery { 88 | site { 89 | siteMetadata { 90 | title 91 | description 92 | author 93 | } 94 | } 95 | } 96 | ` 97 | -------------------------------------------------------------------------------- /src/components/SiteHeader/index.js: -------------------------------------------------------------------------------- 1 | import { Link, StaticQuery, graphql } from "gatsby" 2 | import PropTypes from "prop-types" 3 | import React from "react" 4 | import { Layout } from "antd" 5 | import SiteMenu from "../SiteMenu" 6 | import wpgraphqlLogo from "../../images/wpgraphql-logo.png" 7 | 8 | const { Header } = Layout 9 | 10 | const Index = ({ location }) => ( 11 | ( 22 |
23 |
33 | 40 | WPGraphQL Logo 45 | {` `} 46 | {data.site.siteMetadata.title} 47 | 48 |
49 | 50 |
51 | )} 52 | /> 53 | ) 54 | 55 | Index.propTypes = { 56 | siteTitle: PropTypes.string, 57 | } 58 | 59 | Index.defaultProps = { 60 | siteTitle: ``, 61 | } 62 | 63 | export default Index 64 | -------------------------------------------------------------------------------- /src/components/SiteLayout.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import Header from "./SiteHeader" 4 | import { Layout, Row, Col } from "antd" 5 | import "./style.css" 6 | 7 | const { Content, Footer } = Layout 8 | 9 | const SiteLayout = ({ children, location }) => ( 10 | 11 |
12 | 20 | 21 | 28 | {children} 29 | 30 | 31 | 32 |
33 | © {new Date().getFullYear()} | Built with 34 | {` `} 35 | WPGraphQL and{` `} 36 | Gatsby 37 |
38 | 39 | ) 40 | 41 | SiteLayout.propTypes = { 42 | children: PropTypes.node.isRequired, 43 | } 44 | 45 | export default SiteLayout 46 | -------------------------------------------------------------------------------- /src/components/SiteMenu/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Menu } from "antd" 3 | import { Link, StaticQuery, graphql } from "gatsby" 4 | import { createLocalLink } from "../../utils" 5 | 6 | const SubMenu = Menu.SubMenu 7 | const MenuItemGroup = Menu.ItemGroup 8 | 9 | const MENU_QUERY = graphql` 10 | fragment MenuFields on WPGraphQL_MenuItem { 11 | id 12 | label 13 | url 14 | connectedObject { 15 | __typename 16 | } 17 | } 18 | 19 | query GET_MENU_ITEMS { 20 | wpgraphql { 21 | menuItems(where: { location: PRIMARY }) { 22 | nodes { 23 | ...MenuFields 24 | childItems { 25 | nodes { 26 | ...MenuFields 27 | childItems { 28 | nodes { 29 | ...MenuFields 30 | childItems { 31 | nodes { 32 | ...MenuFields 33 | childItems { 34 | nodes { 35 | ...MenuFields 36 | childItems { 37 | nodes { 38 | ...MenuFields 39 | childItems { 40 | nodes { 41 | ...MenuFields 42 | childItems { 43 | nodes { 44 | ...MenuFields 45 | childItems { 46 | nodes { 47 | ...MenuFields 48 | childItems { 49 | nodes { 50 | ...MenuFields 51 | } 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | ` 74 | 75 | const renderMenuItem = menuItem => { 76 | const link = createLocalLink(menuItem.url) 77 | if (menuItem.childItems && menuItem.childItems.nodes.length) { 78 | return renderSubMenu(menuItem) 79 | } else { 80 | return ( 81 | 82 | {link ? ( 83 | {menuItem.label} 84 | ) : ( 85 | menuItem.label 86 | )} 87 | 88 | ) 89 | } 90 | } 91 | 92 | const renderSubMenu = menuItem => ( 93 | 94 | 95 | {menuItem.childItems.nodes.map(item => renderMenuItem(item))} 96 | 97 | 98 | ) 99 | 100 | const SiteMenu = ({ location }) => ( 101 | { 104 | if (data.wpgraphql.menuItems) { 105 | return ( 106 | 115 | {data.wpgraphql.menuItems.nodes.map(menuItem => { 116 | if (menuItem.childItems.nodes.length) { 117 | return renderSubMenu(menuItem) 118 | } else { 119 | return renderMenuItem(menuItem) 120 | } 121 | })} 122 | 123 | ) 124 | } else { 125 | return null 126 | } 127 | }} 128 | /> 129 | ) 130 | 131 | export default SiteMenu 132 | -------------------------------------------------------------------------------- /src/components/style.css: -------------------------------------------------------------------------------- 1 | img { 2 | max-width: 100%; 3 | height: auto; 4 | } 5 | 6 | iframe { 7 | max-width: 100%; 8 | } 9 | 10 | * { 11 | word-break: break-word; 12 | } 13 | -------------------------------------------------------------------------------- /src/images/gatsby-astronaut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp-graphql/gatsby-wpgraphql-blog-example/6e31fb099be283f385f751315828e92effc77cf9/src/images/gatsby-astronaut.png -------------------------------------------------------------------------------- /src/images/gatsby-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp-graphql/gatsby-wpgraphql-blog-example/6e31fb099be283f385f751315828e92effc77cf9/src/images/gatsby-icon.png -------------------------------------------------------------------------------- /src/images/gatsby-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp-graphql/gatsby-wpgraphql-blog-example/6e31fb099be283f385f751315828e92effc77cf9/src/images/gatsby-logo.png -------------------------------------------------------------------------------- /src/images/wpgraphql-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp-graphql/gatsby-wpgraphql-blog-example/6e31fb099be283f385f751315828e92effc77cf9/src/images/wpgraphql-logo.png -------------------------------------------------------------------------------- /src/layouts/SiteLayout/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const SiteLayout = ({location}) => { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import SiteLayout from "../components/SiteLayout" 4 | import Seo from "../components/Seo" 5 | 6 | const NotFoundPage = ({ location }) => ( 7 | 8 | 9 |

NOT FOUND

10 |

You just hit a route that doesn't exist... the sadness.

11 |
12 | ) 13 | 14 | export default NotFoundPage 15 | -------------------------------------------------------------------------------- /src/templates/blog.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react" 2 | import { graphql, navigate } from "gatsby" 3 | import { Button, Col, Row } from "antd" 4 | import CategoriesWidget from "../components/CategoriesWidget" 5 | import RecentCommentsWidget from "../components/RecentCommentsWidget" 6 | import RecentPostsWidget from "../components/RecentPostsWidget" 7 | import PostEntry from "../components/PostEntry" 8 | import HomepageLayout from "../components/HomepageLayout" 9 | import Seo from "../components/Seo" 10 | 11 | class IndexPage extends Component { 12 | renderPreviousLink = () => { 13 | const { 14 | pageContext: { pageNumber }, 15 | } = this.props 16 | 17 | let previousLink = null 18 | 19 | if (!pageNumber) { 20 | return null 21 | } else if (1 === pageNumber) { 22 | previousLink = `/` 23 | } else if (1 < pageNumber) { 24 | previousLink = `/page/${pageNumber - 1}` 25 | } 26 | 27 | return ( 28 | 31 | ) 32 | } 33 | 34 | renderNextLink = () => { 35 | const { 36 | pageContext: { hasNextPage, pageNumber }, 37 | } = this.props 38 | 39 | if (hasNextPage) { 40 | return ( 41 | 47 | ) 48 | } else { 49 | return null 50 | } 51 | } 52 | 53 | render() { 54 | const { 55 | data, 56 | location, 57 | pageContext: { pageNumber }, 58 | } = this.props 59 | const blogPageNumber = pageNumber ? ` Page ${pageNumber}` : `` 60 | return ( 61 | 62 | 63 | 64 | 65 | {data && 66 | data.wpgraphql && 67 | data.wpgraphql.posts.nodes.map(post => ( 68 |
69 | 70 |
71 | ))} 72 | 73 | 74 | 75 | 76 | 77 | 78 |
79 | 88 | 89 | 90 | {this.renderPreviousLink()} 91 | 92 | 93 | 94 | 95 | {this.renderNextLink()} 96 | 97 | 98 | 99 |
100 | ) 101 | } 102 | } 103 | 104 | export default IndexPage 105 | 106 | export const query = graphql` 107 | query GET_POSTS($ids: [ID]) { 108 | wpgraphql { 109 | posts(where: { in: $ids }) { 110 | nodes { 111 | ...PostEntryFragment 112 | } 113 | } 114 | } 115 | } 116 | ` 117 | -------------------------------------------------------------------------------- /src/templates/categoriesArchive.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | const CategoriesArchiveTemplate = props => { 4 | return ( 5 |
6 |

Category Archive...

7 |
8 | ) 9 | } 10 | 11 | export default CategoriesArchiveTemplate 12 | -------------------------------------------------------------------------------- /src/templates/category.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import SiteLayout from "../components/SiteLayout" 3 | import { graphql } from "gatsby" 4 | import { Row, Col, Divider } from "antd" 5 | import CategoriesWidget from "../components/CategoriesWidget" 6 | import RecentCommentsWidget from "../components/RecentCommentsWidget" 7 | import RecentPostsWidget from "../components/RecentPostsWidget" 8 | import PostEntry from "../components/PostEntry" 9 | import Seo from "../components/Seo" 10 | 11 | const CategoryTemplate = props => { 12 | const { 13 | location, 14 | data: { 15 | wpgraphql: { category }, 16 | }, 17 | } = props 18 | return ( 19 | 20 | 21 | 22 | 23 |

Category: {category.name}

24 | 25 | {category.posts.nodes && 26 | category.posts.nodes.map(post => )} 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 |
35 | ) 36 | } 37 | 38 | export default CategoryTemplate 39 | 40 | export const pageQuery = graphql` 41 | query GET_CATEGORY($id: ID!) { 42 | wpgraphql { 43 | category(id: $id) { 44 | id 45 | name 46 | slug 47 | posts(first: 100) { 48 | nodes { 49 | ...PostEntryFragment 50 | } 51 | } 52 | } 53 | } 54 | } 55 | ` 56 | -------------------------------------------------------------------------------- /src/templates/page.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { graphql } from "gatsby" 3 | import { Row, Col, Divider } from "antd" 4 | import SiteLayout from "../components/SiteLayout" 5 | import CategoriesWidget from "../components/CategoriesWidget" 6 | import RecentCommentsWidget from "../components/RecentCommentsWidget" 7 | import RecentPostsWidget from "../components/RecentPostsWidget" 8 | import Seo from "../components/Seo" 9 | 10 | const Page = props => { 11 | const { 12 | location, 13 | data: { 14 | wpgraphql: { page }, 15 | }, 16 | } = props 17 | const { title, content } = page 18 | return ( 19 | 20 | 21 | 22 | 23 |

{title}

24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ) 39 | } 40 | 41 | export default Page 42 | 43 | export const pageQuery = graphql` 44 | query GET_PAGE($id: ID!) { 45 | wpgraphql { 46 | page(id: $id) { 47 | title 48 | content 49 | uri 50 | } 51 | } 52 | } 53 | ` 54 | -------------------------------------------------------------------------------- /src/templates/post.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from "react" 2 | import { graphql } from "gatsby" 3 | import { Row, Col, Divider, Tag } from "antd" 4 | import SiteLayout from "../components/SiteLayout" 5 | import CategoriesWidget from "../components/CategoriesWidget" 6 | import RecentCommentsWidget from "../components/RecentCommentsWidget" 7 | import RecentPostsWidget from "../components/RecentPostsWidget" 8 | import PostEntryMeta from "../components/PostEntryMeta" 9 | import Seo from "../components/Seo" 10 | 11 | const renderTermNodes = (nodes, title) => ( 12 |
13 | {title} 14 | {` `} 15 | {nodes.map(term => ( 16 | {term.name} 17 | ))} 18 |
19 | ) 20 | 21 | const renderTerms = (categoryNodes = [], tagNodes = []) => ( 22 | 23 | 24 | {categoryNodes ? renderTermNodes(categoryNodes, `Categories: `) : null} 25 | {tagNodes && tagNodes.length ? renderTermNodes(tagNodes, `Tags: `) : null } 26 | 27 | ) 28 | 29 | const Post = props => { 30 | const { 31 | location, 32 | data: { 33 | wpgraphql: { post }, 34 | }, 35 | } = props 36 | const { title, content } = post 37 | return ( 38 | 39 | 40 | 41 | 42 |

{title}

43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | {post.categories.nodes.length || post.tags.nodes.length 51 | ? renderTerms(post.categories.nodes, post.tags.nodes) 52 | : null} 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | ) 64 | } 65 | 66 | export default Post 67 | 68 | export const pageQuery = graphql` 69 | query GET_POST($id: ID!) { 70 | wpgraphql { 71 | post(id: $id) { 72 | title 73 | content 74 | uri 75 | author { 76 | name 77 | slug 78 | avatar { 79 | url 80 | } 81 | } 82 | tags { 83 | nodes { 84 | name 85 | link 86 | } 87 | } 88 | categories { 89 | nodes { 90 | name 91 | link 92 | } 93 | } 94 | } 95 | } 96 | } 97 | ` 98 | -------------------------------------------------------------------------------- /src/templates/tag.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import SiteLayout from "../components/SiteLayout" 3 | import { graphql } from "gatsby" 4 | import { Row, Col } from "antd" 5 | import CategoriesWidget from "../components/CategoriesWidget" 6 | import RecentCommentsWidget from "../components/RecentCommentsWidget" 7 | import RecentPostsWidget from "../components/RecentPostsWidget" 8 | import PostEntry from "../components/PostEntry" 9 | import Seo from "../components/Seo" 10 | 11 | const TagTemplate = props => { 12 | const { 13 | location, 14 | data: { 15 | wpgraphql: { tag }, 16 | }, 17 | } = props 18 | return ( 19 | 20 | 21 |

{tag.name}

22 | 23 | 24 | {tag.posts.nodes && 25 | tag.posts.nodes.map(post => )} 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | ) 35 | } 36 | 37 | export default TagTemplate 38 | 39 | export const pageQuery = graphql` 40 | query GET_TAG($id: ID!) { 41 | wpgraphql { 42 | tag(id: $id) { 43 | id 44 | name 45 | slug 46 | posts(first: 100) { 47 | nodes { 48 | ...PostEntryFragment 49 | } 50 | } 51 | } 52 | } 53 | } 54 | ` 55 | -------------------------------------------------------------------------------- /src/templates/tagsArchive.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | const TagsArchiveTemplate = props => { 4 | return ( 5 |
6 |

Tag Archive...

7 |
8 | ) 9 | } 10 | 11 | export default TagsArchiveTemplate 12 | -------------------------------------------------------------------------------- /src/templates/user.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import SiteLayout from "../components/SiteLayout" 3 | import { Row, Col } from "antd" 4 | import { graphql } from "gatsby" 5 | import CategoriesWidget from "../components/CategoriesWidget" 6 | import RecentCommentsWidget from "../components/RecentCommentsWidget" 7 | import RecentPostsWidget from "../components/RecentPostsWidget" 8 | import PostEntry from "../components/PostEntry" 9 | import Seo from "../components/Seo" 10 | 11 | const User = props => { 12 | const { 13 | location, 14 | data: { 15 | wpgraphql: { user }, 16 | }, 17 | } = props 18 | return ( 19 | 20 | 21 | 22 | 23 |

{user.name}

24 |

Latest Posts

25 | {user.posts.nodes.map(post => ( 26 | 27 | ))} 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |
36 | ) 37 | } 38 | 39 | export default User 40 | 41 | export const pageQuery = graphql` 42 | query user($id: ID!) { 43 | wpgraphql { 44 | user(id: $id) { 45 | name 46 | avatar { 47 | url 48 | } 49 | posts { 50 | nodes { 51 | ...PostEntryFragment 52 | } 53 | } 54 | } 55 | } 56 | } 57 | ` 58 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | import config from "../../config" 2 | 3 | export const createLocalLink = url => { 4 | if (`#` === url) { 5 | return null 6 | } 7 | return url ? url.replace(config.wordPressUrl, ``) : url 8 | } 9 | --------------------------------------------------------------------------------