├── .gitignore ├── .markdownlint.json ├── .vscode └── spellright.dict ├── LICENSE ├── README.md ├── gatsby-config.js ├── gatsby-node.js ├── package-lock.json ├── package.json └── src ├── components ├── header.js ├── image.js ├── layout.css ├── layout.js └── seo.js ├── images ├── gatsby-astronaut.png └── gatsby-icon.png ├── layouts └── index.js ├── pages ├── 404.js └── index.js ├── templates └── post.js └── utils └── typography.js /.gitignore: -------------------------------------------------------------------------------- 1 | # NPM # 2 | ########## 3 | # Ignore all directories called node_modules in current folder and any subfolders. 4 | node_modules/ 5 | /node_modules/ 6 | 7 | # Packages # 8 | ############ 9 | *.7z 10 | *.dmg 11 | *.gz 12 | *.bz2 13 | *.iso 14 | *.jar 15 | *.rar 16 | *.tar 17 | *.zip 18 | *.tgz 19 | *.map 20 | 21 | # Logs and databases # 22 | ###################### 23 | *.log 24 | *.sql 25 | *.env 26 | 27 | # OS generated files # 28 | ###################### 29 | **.DS_Store* 30 | ehthumbs.db 31 | Icon? 32 | Thumbs.db 33 | ._* 34 | 35 | # Vim generated files # 36 | ###################### 37 | *.un~ 38 | 39 | # SASS # 40 | ########## 41 | **/.sass-cache 42 | **/.sass-cache/* 43 | **/.map 44 | 45 | # Composer # 46 | ########## 47 | !assets/js/vendor/ 48 | wpcs/ 49 | /vendor/ 50 | 51 | # Bower # 52 | ########## 53 | assets/bower_components/* 54 | 55 | # Codekit # 56 | ########## 57 | /codekit-config.json 58 | *.codekit 59 | **.codekit-cache/* 60 | 61 | # Compiled Files and Build Dirs # 62 | ########## 63 | /README.html 64 | 65 | # PhpStrom Project Files # 66 | .idea/ 67 | library/vendors/composer 68 | assets/img/.DS_Store 69 | 70 | # VSCode related files # 71 | # .vscode 72 | # Gatsby related 73 | public 74 | .cache 75 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD010": false, 3 | "MD013": false, 4 | "MD033": false 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/spellright.dict: -------------------------------------------------------------------------------- 1 | posts 2 | ags 3 | ategories 4 | osts 5 | wordpress 6 | gatsby 7 | lodash 8 | dom 9 | npm 10 | js 11 | jsx 12 | graphql 13 | destructuring 14 | -------------------------------------------------------------------------------- /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 |

2 | 3 |
Gatsby & WordPress Integration 4 |

5 | 6 |
7 | 8 | Building static sites with `React.js` using **Gatsby** provides an **easy to deploy setup**, **blazing fast speed**, and **smooth developer experience**. JAMstack (JavaScript APIs Markup) is awesome and I am going to show you why it has become such a popular tool by demonstrating how you can leverage Gatsby to supercharge your next WordPress site. 9 | 10 | First we are going to configure a basic Gatsby project setup. And then we'll use it to fetch data from our WordPress site. 11 | 12 | ## Integrating Gatsby.js with WordPress 13 | 14 |
15 | Step #0: Don't have a Gatsby site setup? Read this. (CLICK TO EXPAND!) 16 | 17 | If this is your first time with Gatsby.js, all you need to do is follow these steps mentioned below. These will help you set up a basic Gatsby project. 18 | 19 | - Install the Gatsby CLI by typing the following command in your terminal 20 | 21 | ```sh 22 | npm install -g gatsby-cli 23 | ``` 24 | 25 | - Next, create a new Gatsby.js site through the following. 26 | 27 | ```sh 28 | gatsby new site-name 29 | ``` 30 | 31 | - To access your site folder contents type the following. 32 | 33 | ```sh 34 | cd site-name 35 | ``` 36 | 37 | - Finally, start the development server to begin building your Gatsby.js site. 38 | 39 | ```sh 40 | gatsby develop 41 | ``` 42 | 43 |
44 | 45 | ### #1: Install `gatsby-source-wordpress` Plugin 46 | 47 | If you have a WordPress site and you want to have its front-end built with Gatsby.js all you need to do is pull the existing data into your static Gatsby site. You can do that with the `gatsby-source-wordpress` plugin. 48 | 49 | Inside your terminal type the following to install this plugin. 50 | 51 | ```sh 52 | npm install gatsby-source-wordpress 53 | ``` 54 | 55 | ### #2: Configuring the plugin 56 | 57 | Inside your `gatsby-config.js` file, add the configuration options which includes your WordPress site’s `baseUrl`, `protocol`, whether it’s hosted on WordPress.com or self-hosted i.e., `hostingWPCOM`, and whether it uses the Advanced Custom Fields (ACF) plugin or not `useACF` Also, we are going to mention all the `includedRoutes` which tells what data do we exactly want to fetch. 58 | 59 | Inside your `gatsby-config.js` file, the configuration options looks like this: 60 | 61 | ```js 62 | module.exports = { 63 | // ... 64 | plugins: [ 65 | // ... 66 | { 67 | resolve: `gatsby-source-wordpress`, 68 | options: { 69 | // Your WordPress source. 70 | baseUrl: `demo.wp-api.org`, 71 | protocol: `https`, 72 | // Only fetches posts, tags and categories from the baseUrl. 73 | includedRoutes: ['**/posts', '**/tags', '**/categories'], 74 | // Not using ACF so putting it off. 75 | useACF: false 76 | } 77 | }, 78 | ], 79 | } 80 | ``` 81 | 82 | ### #3: Using the Fetched WordPress Data 83 | 84 | Once your Gatsby site is fetching data from your WordPress source URL, next you'll create your site pages. This is done by implementing the `createPages` API in the `gatsby-node.js`. 85 | 86 | This makes your fetched data available to be queried with GraphQL. At `build` time, the `gatsby-source-wordpress` plugin fetches your data, and use it to ”automatically infer a GraphQL schema” which you can query against. 87 | 88 | Here's the code of the `gatsby-node.js` file which iterates the WordPress post data. 89 | 90 | ```js 91 | /** 92 | * Implement Gatsby's Node APIs in this file. 93 | * 94 | * See: https://www.gatsbyjs.org/docs/node-apis/ 95 | */ 96 | 97 | const path = require(`path`); 98 | const slash = require(`slash`); 99 | 100 | /** 101 | * Implement the Gatsby API “createPages”. This is 102 | * called after the Gatsby bootstrap is finished so you have 103 | * access to any information necessary to programmatically 104 | * create pages. 105 | * Will create pages for WordPress pages (route : /{slug}) 106 | * Will create pages for WordPress posts (route : /post/{slug}) 107 | */ 108 | exports.createPages = async ({ graphql, actions }) => { 109 | const { createPage } = actions; 110 | 111 | /* 112 | * The “graphql” function allows us to run arbitrary 113 | * queries against the local Gatsby GraphQL schema. Think of 114 | * it like the site has a built-in database constructed 115 | * from the fetched data that you can run queries against. 116 | */ 117 | const result = await graphql(` 118 | { 119 | allWordpressPost { 120 | edges { 121 | node { 122 | id 123 | slug 124 | status 125 | template 126 | format 127 | } 128 | } 129 | } 130 | } 131 | `); 132 | 133 | // Check for any errors. 134 | if (result.errors) { 135 | throw new Error(result.errors); 136 | } 137 | 138 | // Access query results via object destructuring. 139 | const { allWordpressPost } = result.data; 140 | const postTemplate = path.resolve(`./src/templates/post.js`); 141 | 142 | /* 143 | * We want to create a detailed page for each 144 | * post node. We'll just use the WordPress Slug for the slug. 145 | * The Post ID is prefixed with 'POST_' 146 | */ 147 | allWordpressPost.edges.forEach(edge => { 148 | createPage({ 149 | path: `/${edge.node.slug}/`, 150 | component: slash(postTemplate), 151 | context: { 152 | id: edge.node.id 153 | } 154 | }); 155 | }); 156 | }; 157 | ``` 158 | 159 | ### #4: Create a `post.js` Template 160 | 161 | Then, create a folder for templates and add files for posts, pages, layouts, etc. For now, I am creating a `post.js` file since I am fetching the posts from my WordPress site. 162 | 163 | Here's the code: 164 | 165 | ``` js 166 | import { graphql } from 'gatsby'; 167 | import PropTypes from 'prop-types'; 168 | import React, { Component } from 'react'; 169 | import Layout from '../layouts'; 170 | 171 | class PostTemplate extends Component { 172 | render() { 173 | const post = this.props.data.wordpressPost; 174 | 175 | return ( 176 | 177 |

178 |
179 | 180 | ); 181 | } 182 | } 183 | 184 | PostTemplate.propTypes = { 185 | data: PropTypes.object.isRequired, 186 | edges: PropTypes.array 187 | }; 188 | 189 | export default PostTemplate; 190 | 191 | export const pageQuery = graphql` 192 | query($id: String!) { 193 | wordpressPost(id: { eq: $id }) { 194 | title 195 | content 196 | } 197 | } 198 | `; 199 | 200 | ``` 201 | 202 | ### #5: Final Result 203 | 204 | To start the development server to view the final result type the following command. 205 | 206 | ```sh 207 | npm start 208 | ``` 209 | 210 | You get the link from where you can access the site locally along with other details like no. of posts, categories and tags that are being fetched. 211 | 212 | > 👋 **[Follow @MaedahBatool on Twitter](https://twitter.com/MaedahBatool/) →** 213 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `Gatsby Default Starter`, 4 | description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`, 5 | author: `@MaedahBatool` 6 | }, 7 | plugins: [ 8 | `gatsby-plugin-react-helmet`, 9 | { 10 | resolve: `gatsby-source-filesystem`, 11 | options: { 12 | name: `images`, 13 | path: `${__dirname}/src/images` 14 | } 15 | }, 16 | `gatsby-transformer-sharp`, 17 | `gatsby-plugin-sharp`, 18 | { 19 | resolve: `gatsby-plugin-manifest`, 20 | options: { 21 | name: `gatsby-starter-default`, 22 | short_name: `starter`, 23 | start_url: `/`, 24 | background_color: `#663399`, 25 | theme_color: `#663399`, 26 | display: `minimal-ui`, 27 | icon: `src/images/gatsby-icon.png` // This path is relative to the root of the site. 28 | } 29 | }, 30 | // @TODO: STEP #1: Configure WordPress Backend as a source. 31 | { 32 | resolve: `gatsby-source-wordpress`, 33 | options: { 34 | // Your WordPress source. 35 | baseUrl: `demo.wp-api.org`, 36 | protocol: `https`, 37 | // Only fetches posts, tags and categories from the baseUrl. 38 | includedRoutes: ['**/posts', '**/tags', '**/categories'], 39 | // Not using ACF so putting it off. 40 | useACF: false 41 | } 42 | }, 43 | `gatsby-plugin-glamor`, 44 | `gatsby-plugin-offline` 45 | ] 46 | }; 47 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Node APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/node-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | 9 | const path = require(`path`); 10 | const slash = require(`slash`); 11 | 12 | /** Implement the Gatsby API “createPages”. This is 13 | * called after the Gatsby bootstrap is finished so you have 14 | * access to any information necessary to programmatically 15 | * create pages. 16 | * Will create pages for WordPress pages (route : /{slug}) 17 | * Will create pages for WordPress posts (route : /post/{slug}) 18 | */ 19 | exports.createPages = async ({ graphql, actions }) => { 20 | const { createPage } = actions; 21 | 22 | // @TODO: STEP #2: Query all WordPress Posts Data. 23 | /** The “graphql” function allows us to run arbitrary 24 | * queries against the local Gatsby GraphQL schema. Think of 25 | * it like the site has a built-in database constructed 26 | * from the fetched data that you can run queries against. 27 | */ 28 | const result = await graphql(` 29 | { 30 | allWordpressPost { 31 | edges { 32 | node { 33 | id 34 | slug 35 | status 36 | template 37 | format 38 | } 39 | } 40 | } 41 | } 42 | `); 43 | 44 | // Check for any errors 45 | if (result.errors) { 46 | throw new Error(result.errors); 47 | } 48 | 49 | // Access query results via object destructuring. 50 | const { allWordpressPost } = result.data; 51 | 52 | const postTemplate = path.resolve(`./src/templates/post.js`); 53 | 54 | // @TODO: STEP #3: Create pages in Gatsby with WordPress Posts Data. 55 | /** 56 | * We want to create a detailed page for each 57 | * post node. We'll just use the WordPress Slug for the slug. 58 | * The Post ID is prefixed with 'POST_' 59 | */ 60 | allWordpressPost.edges.forEach(edge => { 61 | createPage({ 62 | path: `/${edge.node.slug}/`, 63 | component: slash(postTemplate), 64 | context: { 65 | id: edge.node.id 66 | } 67 | }); 68 | }); 69 | }; 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-with-wordpress", 3 | "private": true, 4 | "description": "A simple integration to quickly convert your WordPress site to Gatsby.", 5 | "version": "0.1.0", 6 | "author": "Maedah Batool", 7 | "dependencies": { 8 | "gatsby": "^2.5.0", 9 | "gatsby-image": "^2.1.0", 10 | "gatsby-plugin-glamor": "^2.0.9", 11 | "gatsby-plugin-manifest": "^2.1.1", 12 | "gatsby-plugin-offline": "^2.1.0", 13 | "gatsby-plugin-react-helmet": "^3.0.12", 14 | "gatsby-plugin-sharp": "^2.0.37", 15 | "gatsby-source-filesystem": "^2.0.36", 16 | "gatsby-source-wordpress": "^3.0.61", 17 | "gatsby-transformer-sharp": "^2.1.19", 18 | "glamor": "^2.20.40", 19 | "lodash": "^4.17.11", 20 | "prop-types": "^15.7.2", 21 | "react": "^16.8.6", 22 | "react-dom": "^16.8.6", 23 | "react-helmet": "^5.2.1", 24 | "react-typography": "^0.16.19", 25 | "slash": "^3.0.0", 26 | "typography": "^0.16.19", 27 | "typography-theme-wordpress-2013": "^0.16.19" 28 | }, 29 | "devDependencies": { 30 | "prettier": "^1.17.1" 31 | }, 32 | "keywords": [ 33 | "gatsby" 34 | ], 35 | "license": "MIT", 36 | "scripts": { 37 | "build": "gatsby build", 38 | "develop": "gatsby develop", 39 | "format": "prettier --write src/**/*.{js,jsx}", 40 | "start": "npm run develop", 41 | "serve": "gatsby serve", 42 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" 43 | }, 44 | "repository": { 45 | "type": "git", 46 | "url": "https://github.com/gatsbyjs/gatsby-starter-default" 47 | }, 48 | "bugs": { 49 | "url": "https://github.com/gatsbyjs/gatsby/issues" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/components/header.js: -------------------------------------------------------------------------------- 1 | import { Link } from "gatsby" 2 | import PropTypes from "prop-types" 3 | import React from "react" 4 | 5 | const Header = ({ siteTitle }) => ( 6 |
12 |
19 |

20 | 27 | {siteTitle} 28 | 29 |

30 |
31 |
32 | ) 33 | 34 | Header.propTypes = { 35 | siteTitle: PropTypes.string, 36 | } 37 | 38 | Header.defaultProps = { 39 | siteTitle: ``, 40 | } 41 | 42 | export default Header 43 | -------------------------------------------------------------------------------- /src/components/image.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { StaticQuery, graphql } from "gatsby" 3 | import Img from "gatsby-image" 4 | 5 | /* 6 | * This component is built using `gatsby-image` to automatically serve optimized 7 | * images with lazy loading and reduced file sizes. The image is loaded using a 8 | * `StaticQuery`, which allows us to load the image from directly within this 9 | * component, rather than having to pass the image data down from pages. 10 | * 11 | * For more information, see the docs: 12 | * - `gatsby-image`: https://gatsby.dev/gatsby-image 13 | * - `StaticQuery`: https://gatsby.dev/staticquery 14 | */ 15 | 16 | const Image = () => ( 17 | } 30 | /> 31 | ) 32 | export default Image 33 | -------------------------------------------------------------------------------- /src/components/layout.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: sans-serif; 3 | -ms-text-size-adjust: 100%; 4 | -webkit-text-size-adjust: 100%; 5 | } 6 | body { 7 | margin: 0; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | main, 19 | menu, 20 | nav, 21 | section, 22 | summary { 23 | display: block; 24 | } 25 | audio, 26 | canvas, 27 | progress, 28 | video { 29 | display: inline-block; 30 | } 31 | audio:not([controls]) { 32 | display: none; 33 | height: 0; 34 | } 35 | progress { 36 | vertical-align: baseline; 37 | } 38 | [hidden], 39 | template { 40 | display: none; 41 | } 42 | a { 43 | background-color: transparent; 44 | -webkit-text-decoration-skip: objects; 45 | } 46 | a:active, 47 | a:hover { 48 | outline-width: 0; 49 | } 50 | abbr[title] { 51 | border-bottom: none; 52 | text-decoration: underline; 53 | text-decoration: underline dotted; 54 | } 55 | b, 56 | strong { 57 | font-weight: inherit; 58 | font-weight: bolder; 59 | } 60 | dfn { 61 | font-style: italic; 62 | } 63 | h1 { 64 | font-size: 2em; 65 | margin: 0.67em 0; 66 | } 67 | mark { 68 | background-color: #ff0; 69 | color: #000; 70 | } 71 | small { 72 | font-size: 80%; 73 | } 74 | sub, 75 | sup { 76 | font-size: 75%; 77 | line-height: 0; 78 | position: relative; 79 | vertical-align: baseline; 80 | } 81 | sub { 82 | bottom: -0.25em; 83 | } 84 | sup { 85 | top: -0.5em; 86 | } 87 | img { 88 | border-style: none; 89 | } 90 | svg:not(:root) { 91 | overflow: hidden; 92 | } 93 | code, 94 | kbd, 95 | pre, 96 | samp { 97 | font-family: monospace, monospace; 98 | font-size: 1em; 99 | } 100 | figure { 101 | margin: 1em 40px; 102 | } 103 | hr { 104 | box-sizing: content-box; 105 | height: 0; 106 | overflow: visible; 107 | } 108 | button, 109 | input, 110 | optgroup, 111 | select, 112 | textarea { 113 | font: inherit; 114 | margin: 0; 115 | } 116 | optgroup { 117 | font-weight: 700; 118 | } 119 | button, 120 | input { 121 | overflow: visible; 122 | } 123 | button, 124 | select { 125 | text-transform: none; 126 | } 127 | [type="reset"], 128 | [type="submit"], 129 | button, 130 | html [type="button"] { 131 | -webkit-appearance: button; 132 | } 133 | [type="button"]::-moz-focus-inner, 134 | [type="reset"]::-moz-focus-inner, 135 | [type="submit"]::-moz-focus-inner, 136 | button::-moz-focus-inner { 137 | border-style: none; 138 | padding: 0; 139 | } 140 | [type="button"]:-moz-focusring, 141 | [type="reset"]:-moz-focusring, 142 | [type="submit"]:-moz-focusring, 143 | button:-moz-focusring { 144 | outline: 1px dotted ButtonText; 145 | } 146 | fieldset { 147 | border: 1px solid silver; 148 | margin: 0 2px; 149 | padding: 0.35em 0.625em 0.75em; 150 | } 151 | legend { 152 | box-sizing: border-box; 153 | color: inherit; 154 | display: table; 155 | max-width: 100%; 156 | padding: 0; 157 | white-space: normal; 158 | } 159 | textarea { 160 | overflow: auto; 161 | } 162 | [type="checkbox"], 163 | [type="radio"] { 164 | box-sizing: border-box; 165 | padding: 0; 166 | } 167 | [type="number"]::-webkit-inner-spin-button, 168 | [type="number"]::-webkit-outer-spin-button { 169 | height: auto; 170 | } 171 | [type="search"] { 172 | -webkit-appearance: textfield; 173 | outline-offset: -2px; 174 | } 175 | [type="search"]::-webkit-search-cancel-button, 176 | [type="search"]::-webkit-search-decoration { 177 | -webkit-appearance: none; 178 | } 179 | ::-webkit-input-placeholder { 180 | color: inherit; 181 | opacity: 0.54; 182 | } 183 | ::-webkit-file-upload-button { 184 | -webkit-appearance: button; 185 | font: inherit; 186 | } 187 | html { 188 | font: 112.5%/1.45em georgia, serif; 189 | box-sizing: border-box; 190 | overflow-y: scroll; 191 | } 192 | * { 193 | box-sizing: inherit; 194 | } 195 | *:before { 196 | box-sizing: inherit; 197 | } 198 | *:after { 199 | box-sizing: inherit; 200 | } 201 | body { 202 | color: hsla(0, 0%, 0%, 0.8); 203 | font-family: georgia, serif; 204 | font-weight: normal; 205 | word-wrap: break-word; 206 | font-kerning: normal; 207 | -moz-font-feature-settings: "kern", "liga", "clig", "calt"; 208 | -ms-font-feature-settings: "kern", "liga", "clig", "calt"; 209 | -webkit-font-feature-settings: "kern", "liga", "clig", "calt"; 210 | font-feature-settings: "kern", "liga", "clig", "calt"; 211 | } 212 | img { 213 | max-width: 100%; 214 | margin-left: 0; 215 | margin-right: 0; 216 | margin-top: 0; 217 | padding-bottom: 0; 218 | padding-left: 0; 219 | padding-right: 0; 220 | padding-top: 0; 221 | margin-bottom: 1.45rem; 222 | } 223 | h1 { 224 | margin-left: 0; 225 | margin-right: 0; 226 | margin-top: 0; 227 | padding-bottom: 0; 228 | padding-left: 0; 229 | padding-right: 0; 230 | padding-top: 0; 231 | margin-bottom: 1.45rem; 232 | color: inherit; 233 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 234 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 235 | font-weight: bold; 236 | text-rendering: optimizeLegibility; 237 | font-size: 2.25rem; 238 | line-height: 1.1; 239 | } 240 | h2 { 241 | margin-left: 0; 242 | margin-right: 0; 243 | margin-top: 0; 244 | padding-bottom: 0; 245 | padding-left: 0; 246 | padding-right: 0; 247 | padding-top: 0; 248 | margin-bottom: 1.45rem; 249 | color: inherit; 250 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 251 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 252 | font-weight: bold; 253 | text-rendering: optimizeLegibility; 254 | font-size: 1.62671rem; 255 | line-height: 1.1; 256 | } 257 | h3 { 258 | margin-left: 0; 259 | margin-right: 0; 260 | margin-top: 0; 261 | padding-bottom: 0; 262 | padding-left: 0; 263 | padding-right: 0; 264 | padding-top: 0; 265 | margin-bottom: 1.45rem; 266 | color: inherit; 267 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 268 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 269 | font-weight: bold; 270 | text-rendering: optimizeLegibility; 271 | font-size: 1.38316rem; 272 | line-height: 1.1; 273 | } 274 | h4 { 275 | margin-left: 0; 276 | margin-right: 0; 277 | margin-top: 0; 278 | padding-bottom: 0; 279 | padding-left: 0; 280 | padding-right: 0; 281 | padding-top: 0; 282 | margin-bottom: 1.45rem; 283 | color: inherit; 284 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 285 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 286 | font-weight: bold; 287 | text-rendering: optimizeLegibility; 288 | font-size: 1rem; 289 | line-height: 1.1; 290 | } 291 | h5 { 292 | margin-left: 0; 293 | margin-right: 0; 294 | margin-top: 0; 295 | padding-bottom: 0; 296 | padding-left: 0; 297 | padding-right: 0; 298 | padding-top: 0; 299 | margin-bottom: 1.45rem; 300 | color: inherit; 301 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 302 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 303 | font-weight: bold; 304 | text-rendering: optimizeLegibility; 305 | font-size: 0.85028rem; 306 | line-height: 1.1; 307 | } 308 | h6 { 309 | margin-left: 0; 310 | margin-right: 0; 311 | margin-top: 0; 312 | padding-bottom: 0; 313 | padding-left: 0; 314 | padding-right: 0; 315 | padding-top: 0; 316 | margin-bottom: 1.45rem; 317 | color: inherit; 318 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 319 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 320 | font-weight: bold; 321 | text-rendering: optimizeLegibility; 322 | font-size: 0.78405rem; 323 | line-height: 1.1; 324 | } 325 | hgroup { 326 | margin-left: 0; 327 | margin-right: 0; 328 | margin-top: 0; 329 | padding-bottom: 0; 330 | padding-left: 0; 331 | padding-right: 0; 332 | padding-top: 0; 333 | margin-bottom: 1.45rem; 334 | } 335 | ul { 336 | margin-left: 1.45rem; 337 | margin-right: 0; 338 | margin-top: 0; 339 | padding-bottom: 0; 340 | padding-left: 0; 341 | padding-right: 0; 342 | padding-top: 0; 343 | margin-bottom: 1.45rem; 344 | list-style-position: outside; 345 | list-style-image: none; 346 | } 347 | ol { 348 | margin-left: 1.45rem; 349 | margin-right: 0; 350 | margin-top: 0; 351 | padding-bottom: 0; 352 | padding-left: 0; 353 | padding-right: 0; 354 | padding-top: 0; 355 | margin-bottom: 1.45rem; 356 | list-style-position: outside; 357 | list-style-image: none; 358 | } 359 | dl { 360 | margin-left: 0; 361 | margin-right: 0; 362 | margin-top: 0; 363 | padding-bottom: 0; 364 | padding-left: 0; 365 | padding-right: 0; 366 | padding-top: 0; 367 | margin-bottom: 1.45rem; 368 | } 369 | dd { 370 | margin-left: 0; 371 | margin-right: 0; 372 | margin-top: 0; 373 | padding-bottom: 0; 374 | padding-left: 0; 375 | padding-right: 0; 376 | padding-top: 0; 377 | margin-bottom: 1.45rem; 378 | } 379 | p { 380 | margin-left: 0; 381 | margin-right: 0; 382 | margin-top: 0; 383 | padding-bottom: 0; 384 | padding-left: 0; 385 | padding-right: 0; 386 | padding-top: 0; 387 | margin-bottom: 1.45rem; 388 | } 389 | figure { 390 | margin-left: 0; 391 | margin-right: 0; 392 | margin-top: 0; 393 | padding-bottom: 0; 394 | padding-left: 0; 395 | padding-right: 0; 396 | padding-top: 0; 397 | margin-bottom: 1.45rem; 398 | } 399 | pre { 400 | margin-left: 0; 401 | margin-right: 0; 402 | margin-top: 0; 403 | margin-bottom: 1.45rem; 404 | font-size: 0.85rem; 405 | line-height: 1.42; 406 | background: hsla(0, 0%, 0%, 0.04); 407 | border-radius: 3px; 408 | overflow: auto; 409 | word-wrap: normal; 410 | padding: 1.45rem; 411 | } 412 | table { 413 | margin-left: 0; 414 | margin-right: 0; 415 | margin-top: 0; 416 | padding-bottom: 0; 417 | padding-left: 0; 418 | padding-right: 0; 419 | padding-top: 0; 420 | margin-bottom: 1.45rem; 421 | font-size: 1rem; 422 | line-height: 1.45rem; 423 | border-collapse: collapse; 424 | width: 100%; 425 | } 426 | fieldset { 427 | margin-left: 0; 428 | margin-right: 0; 429 | margin-top: 0; 430 | padding-bottom: 0; 431 | padding-left: 0; 432 | padding-right: 0; 433 | padding-top: 0; 434 | margin-bottom: 1.45rem; 435 | } 436 | blockquote { 437 | margin-left: 1.45rem; 438 | margin-right: 1.45rem; 439 | margin-top: 0; 440 | padding-bottom: 0; 441 | padding-left: 0; 442 | padding-right: 0; 443 | padding-top: 0; 444 | margin-bottom: 1.45rem; 445 | } 446 | form { 447 | margin-left: 0; 448 | margin-right: 0; 449 | margin-top: 0; 450 | padding-bottom: 0; 451 | padding-left: 0; 452 | padding-right: 0; 453 | padding-top: 0; 454 | margin-bottom: 1.45rem; 455 | } 456 | noscript { 457 | margin-left: 0; 458 | margin-right: 0; 459 | margin-top: 0; 460 | padding-bottom: 0; 461 | padding-left: 0; 462 | padding-right: 0; 463 | padding-top: 0; 464 | margin-bottom: 1.45rem; 465 | } 466 | iframe { 467 | margin-left: 0; 468 | margin-right: 0; 469 | margin-top: 0; 470 | padding-bottom: 0; 471 | padding-left: 0; 472 | padding-right: 0; 473 | padding-top: 0; 474 | margin-bottom: 1.45rem; 475 | } 476 | hr { 477 | margin-left: 0; 478 | margin-right: 0; 479 | margin-top: 0; 480 | padding-bottom: 0; 481 | padding-left: 0; 482 | padding-right: 0; 483 | padding-top: 0; 484 | margin-bottom: calc(1.45rem - 1px); 485 | background: hsla(0, 0%, 0%, 0.2); 486 | border: none; 487 | height: 1px; 488 | } 489 | address { 490 | margin-left: 0; 491 | margin-right: 0; 492 | margin-top: 0; 493 | padding-bottom: 0; 494 | padding-left: 0; 495 | padding-right: 0; 496 | padding-top: 0; 497 | margin-bottom: 1.45rem; 498 | } 499 | b { 500 | font-weight: bold; 501 | } 502 | strong { 503 | font-weight: bold; 504 | } 505 | dt { 506 | font-weight: bold; 507 | } 508 | th { 509 | font-weight: bold; 510 | } 511 | li { 512 | margin-bottom: calc(1.45rem / 2); 513 | } 514 | ol li { 515 | padding-left: 0; 516 | } 517 | ul li { 518 | padding-left: 0; 519 | } 520 | li > ol { 521 | margin-left: 1.45rem; 522 | margin-bottom: calc(1.45rem / 2); 523 | margin-top: calc(1.45rem / 2); 524 | } 525 | li > ul { 526 | margin-left: 1.45rem; 527 | margin-bottom: calc(1.45rem / 2); 528 | margin-top: calc(1.45rem / 2); 529 | } 530 | blockquote *:last-child { 531 | margin-bottom: 0; 532 | } 533 | li *:last-child { 534 | margin-bottom: 0; 535 | } 536 | p *:last-child { 537 | margin-bottom: 0; 538 | } 539 | li > p { 540 | margin-bottom: calc(1.45rem / 2); 541 | } 542 | code { 543 | font-size: 0.85rem; 544 | line-height: 1.45rem; 545 | } 546 | kbd { 547 | font-size: 0.85rem; 548 | line-height: 1.45rem; 549 | } 550 | samp { 551 | font-size: 0.85rem; 552 | line-height: 1.45rem; 553 | } 554 | abbr { 555 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 556 | cursor: help; 557 | } 558 | acronym { 559 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 560 | cursor: help; 561 | } 562 | abbr[title] { 563 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 564 | cursor: help; 565 | text-decoration: none; 566 | } 567 | thead { 568 | text-align: left; 569 | } 570 | td, 571 | th { 572 | text-align: left; 573 | border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); 574 | font-feature-settings: "tnum"; 575 | -moz-font-feature-settings: "tnum"; 576 | -ms-font-feature-settings: "tnum"; 577 | -webkit-font-feature-settings: "tnum"; 578 | padding-left: 0.96667rem; 579 | padding-right: 0.96667rem; 580 | padding-top: 0.725rem; 581 | padding-bottom: calc(0.725rem - 1px); 582 | } 583 | th:first-child, 584 | td:first-child { 585 | padding-left: 0; 586 | } 587 | th:last-child, 588 | td:last-child { 589 | padding-right: 0; 590 | } 591 | tt, 592 | code { 593 | background-color: hsla(0, 0%, 0%, 0.04); 594 | border-radius: 3px; 595 | font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono", 596 | "Liberation Mono", Menlo, Courier, monospace; 597 | padding: 0; 598 | padding-top: 0.2em; 599 | padding-bottom: 0.2em; 600 | } 601 | pre code { 602 | background: none; 603 | line-height: 1.42; 604 | } 605 | code:before, 606 | code:after, 607 | tt:before, 608 | tt:after { 609 | letter-spacing: -0.2em; 610 | content: " "; 611 | } 612 | pre code:before, 613 | pre code:after, 614 | pre tt:before, 615 | pre tt:after { 616 | content: ""; 617 | } 618 | @media only screen and (max-width: 480px) { 619 | html { 620 | font-size: 100%; 621 | } 622 | } 623 | -------------------------------------------------------------------------------- /src/components/layout.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Layout component that queries for data 3 | * with Gatsby's StaticQuery component 4 | * 5 | * See: https://www.gatsbyjs.org/docs/static-query/ 6 | */ 7 | 8 | import React from "react" 9 | import PropTypes from "prop-types" 10 | import { StaticQuery, graphql } from "gatsby" 11 | 12 | import Header from "./header" 13 | import "./layout.css" 14 | 15 | const Layout = ({ children }) => ( 16 | ( 27 | <> 28 |
29 |
37 |
{children}
38 |
39 | © {new Date().getFullYear()}, Built with 40 | {` `} 41 | Gatsby 42 |
43 |
44 | 45 | )} 46 | /> 47 | ) 48 | 49 | Layout.propTypes = { 50 | children: PropTypes.node.isRequired, 51 | } 52 | 53 | export default Layout 54 | -------------------------------------------------------------------------------- /src/components/seo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SEO component that queries for data with 3 | * Gatsby's useStaticQuery React hook 4 | * 5 | * See: https://www.gatsbyjs.org/docs/use-static-query/ 6 | */ 7 | 8 | import React from "react" 9 | import PropTypes from "prop-types" 10 | import Helmet from "react-helmet" 11 | import { useStaticQuery, graphql } from "gatsby" 12 | 13 | function SEO({ description, lang, meta, keywords, title }) { 14 | const { site } = useStaticQuery( 15 | graphql` 16 | query { 17 | site { 18 | siteMetadata { 19 | title 20 | description 21 | author 22 | } 23 | } 24 | } 25 | ` 26 | ) 27 | 28 | const metaDescription = description || site.siteMetadata.description 29 | 30 | return ( 31 | 0 73 | ? { 74 | name: `keywords`, 75 | content: keywords.join(`, `), 76 | } 77 | : [] 78 | ) 79 | .concat(meta)} 80 | /> 81 | ) 82 | } 83 | 84 | SEO.defaultProps = { 85 | lang: `en`, 86 | meta: [], 87 | keywords: [], 88 | description: ``, 89 | } 90 | 91 | SEO.propTypes = { 92 | description: PropTypes.string, 93 | lang: PropTypes.string, 94 | meta: PropTypes.arrayOf(PropTypes.object), 95 | keywords: PropTypes.arrayOf(PropTypes.string), 96 | title: PropTypes.string.isRequired, 97 | } 98 | 99 | export default SEO 100 | -------------------------------------------------------------------------------- /src/images/gatsby-astronaut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaedahBatool/gatsby-with-wordpress/f41c547205a2ea1eb99415d06c64f36b01d9d882/src/images/gatsby-astronaut.png -------------------------------------------------------------------------------- /src/images/gatsby-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaedahBatool/gatsby-with-wordpress/f41c547205a2ea1eb99415d06c64f36b01d9d882/src/images/gatsby-icon.png -------------------------------------------------------------------------------- /src/layouts/index.js: -------------------------------------------------------------------------------- 1 | import { Link } from 'gatsby'; 2 | import PropTypes from 'prop-types'; 3 | import React, { Component } from 'react'; 4 | import { rhythm, scale } from '../utils/typography'; 5 | 6 | const containerStyle = { 7 | maxWidth: 700, 8 | margin: `0 auto`, 9 | padding: rhythm(3 / 4) 10 | }; 11 | 12 | class DefaultLayout extends Component { 13 | render() { 14 | return ( 15 |
16 |
26 |
27 |

38 | 48 | Gatsby.js + WordPress 49 | 50 |

51 |
52 |
53 |
{this.props.children}
54 |
55 | ); 56 | } 57 | } 58 | 59 | DefaultLayout.propTypes = { 60 | children: PropTypes.object.isRequired 61 | }; 62 | 63 | export default DefaultLayout; 64 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import Layout from "../components/layout" 4 | import SEO from "../components/seo" 5 | 6 | const NotFoundPage = () => ( 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/pages/index.js: -------------------------------------------------------------------------------- 1 | import { graphql, Link } from 'gatsby'; 2 | import React, { Component } from 'react'; 3 | import Layout from '../layouts'; 4 | import { rhythm } from '../utils/typography'; 5 | 6 | class Home extends Component { 7 | render() { 8 | const data = this.props.data; 9 | 10 | return ( 11 | 12 | {data.allWordpressPost.edges.map(({ node }) => ( 13 |
14 | 15 |

{node.title}

16 | 17 |
18 |
19 | ))} 20 | 21 | ); 22 | } 23 | } 24 | 25 | export default Home; 26 | 27 | // Set here the ID of the home page. 28 | export const pageQuery = graphql` 29 | query { 30 | allWordpressPost { 31 | edges { 32 | node { 33 | title 34 | excerpt 35 | slug 36 | } 37 | } 38 | } 39 | } 40 | `; 41 | -------------------------------------------------------------------------------- /src/templates/post.js: -------------------------------------------------------------------------------- 1 | import { graphql } from 'gatsby'; 2 | import PropTypes from 'prop-types'; 3 | import React, { Component } from 'react'; 4 | import Layout from '../layouts'; 5 | 6 | class PostTemplate extends Component { 7 | render() { 8 | const post = this.props.data.wordpressPost; 9 | 10 | // @TODO: STEP #5: Use title and content in Gatsby. 11 | return ( 12 | 13 |

14 |
15 | 16 | ); 17 | } 18 | } 19 | 20 | PostTemplate.propTypes = { 21 | data: PropTypes.object.isRequired, 22 | edges: PropTypes.array 23 | }; 24 | 25 | export default PostTemplate; 26 | 27 | // @TODO: STEP #4: Get current WP Post data via ID. 28 | export const pageQuery = graphql` 29 | query($id: String!) { 30 | wordpressPost(id: { eq: $id }) { 31 | title 32 | content 33 | } 34 | } 35 | `; 36 | -------------------------------------------------------------------------------- /src/utils/typography.js: -------------------------------------------------------------------------------- 1 | import Typography from 'typography'; 2 | import wordpress2013 from 'typography-theme-wordpress-2013'; 3 | 4 | wordpress2013.headerLineHeight = 1.1; 5 | wordpress2013.overrideThemeStyles = () => { 6 | return { 7 | a: { 8 | color: `rgb(60,99,243)` 9 | }, 10 | h1: { 11 | fontSize: 1, 12 | lineHeight: 1 13 | } 14 | }; 15 | }; 16 | 17 | const typography = new Typography(wordpress2013); 18 | 19 | export const { rhythm, scale } = typography; 20 | export default typography; 21 | --------------------------------------------------------------------------------