├── .prettierignore
├── src
├── images
│ ├── gatsby-icon.png
│ └── gatsby-astronaut.png
├── markdown-pages
│ └── 1.md
├── pages
│ ├── 404.js
│ ├── page-2.js
│ └── index.js
├── components
│ ├── header.js
│ ├── image.js
│ ├── layout.js
│ ├── seo.js
│ └── layout.css
└── templates
│ └── blogTemplate.js
├── .prettierrc
├── gatsby-browser.js
├── gatsby-ssr.js
├── LICENSE
├── .gitignore
├── gatsby-node.js
├── package.json
├── gatsby-config.js
└── README.md
/.prettierignore:
--------------------------------------------------------------------------------
1 | .cache
2 | package.json
3 | package-lock.json
4 | public
5 |
--------------------------------------------------------------------------------
/src/images/gatsby-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaedahBatool/Optimizing-Gatsby-Site-For-Production/HEAD/src/images/gatsby-icon.png
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "endOfLine": "lf",
3 | "semi": false,
4 | "singleQuote": false,
5 | "tabWidth": 2,
6 | "trailingComma": "es5"
7 | }
8 |
--------------------------------------------------------------------------------
/src/images/gatsby-astronaut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaedahBatool/Optimizing-Gatsby-Site-For-Production/HEAD/src/images/gatsby-astronaut.png
--------------------------------------------------------------------------------
/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-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 |
--------------------------------------------------------------------------------
/src/markdown-pages/1.md:
--------------------------------------------------------------------------------
1 | ---
2 | path: "/blog/my-first-post"
3 | date: "2019-09-25"
4 | title: "My blog post for WordSesh September 2019 edition."
5 | ---
6 |
7 | ## Hello, John Doe!
8 |
9 | `youtube: https://www.youtube.com/watch?v=2Xc9gXyf2G4`
10 |
--------------------------------------------------------------------------------
/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/page-2.js:
--------------------------------------------------------------------------------
1 | import { Link } from "gatsby"
2 | import React from "react"
3 | import Layout from "../components/layout"
4 | import SEO from "../components/seo"
5 |
6 | const SecondPage = () => (
7 |
8 |
9 | Hi from the second page
10 | Go back to the homepage
11 |
12 | )
13 |
14 | export default SecondPage
15 |
--------------------------------------------------------------------------------
/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import { Link } from "gatsby"
2 | import React from "react"
3 | import Image from "../components/image"
4 | import Layout from "../components/layout"
5 | import SEO from "../components/seo"
6 |
7 | const IndexPage = () => (
8 |
9 |
10 | Hi people
11 | Welcome to your new Gatsby site.
12 | Now go build something great.
13 | `youtube: 2Xc9gXyf2G4`
14 |
15 |
16 |
17 | Go to page 2
18 |
19 | )
20 |
21 | export default IndexPage
22 |
--------------------------------------------------------------------------------
/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 |
32 | )
33 |
34 | Header.propTypes = {
35 | siteTitle: PropTypes.string,
36 | }
37 |
38 | Header.defaultProps = {
39 | siteTitle: ``,
40 | }
41 |
42 | export default Header
43 |
--------------------------------------------------------------------------------
/src/templates/blogTemplate.js:
--------------------------------------------------------------------------------
1 | // Step #4: Create a page template for the Markdown files
2 | import { graphql } from "gatsby"
3 | import React from "react"
4 |
5 | export default function Template({
6 | data, // this prop will be injected by the GraphQL query below.
7 | }) {
8 | const { markdownRemark } = data // data.markdownRemark holds our post data
9 | const { frontmatter, html } = markdownRemark
10 | return (
11 |
12 |
13 |
{frontmatter.title}
14 |
{frontmatter.date}
15 |
19 |
20 |
21 | )
22 | }
23 |
24 | export const pageQuery = graphql`
25 | query($path: String!) {
26 | markdownRemark(frontmatter: { path: { eq: $path } }) {
27 | html
28 | frontmatter {
29 | date(formatString: "MMMM DD, YYYY")
30 | path
31 | title
32 | }
33 | }
34 | }
35 | `
36 |
--------------------------------------------------------------------------------
/src/components/image.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { useStaticQuery, 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 | * `useStaticQuery`, 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 | * - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
14 | */
15 |
16 | const Image = () => {
17 | const data = useStaticQuery(graphql`
18 | query {
19 | placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
20 | childImageSharp {
21 | fluid(maxWidth: 300) {
22 | ...GatsbyImageSharpFluid
23 | }
24 | }
25 | }
26 | }
27 | `)
28 |
29 | return
30 | }
31 |
32 | export default Image
33 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
64 | # Yarn
65 | yarn-error.log
66 | .pnp/
67 | .pnp.js
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
--------------------------------------------------------------------------------
/src/components/layout.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Layout component that queries for data
3 | * with Gatsby's useStaticQuery component
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 { useStaticQuery, graphql } from "gatsby"
11 |
12 | import Header from "./header"
13 | import "./layout.css"
14 |
15 | const Layout = ({ children }) => {
16 | const data = useStaticQuery(graphql`
17 | query SiteTitleQuery {
18 | site {
19 | siteMetadata {
20 | title
21 | }
22 | }
23 | }
24 | `)
25 |
26 | return (
27 | <>
28 |
29 |
37 |
{children}
38 |
43 |
44 | >
45 | )
46 | }
47 |
48 | Layout.propTypes = {
49 | children: PropTypes.node.isRequired,
50 | }
51 |
52 | export default Layout
53 |
--------------------------------------------------------------------------------
/gatsby-node.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Implement Gatsby's Node APIs in this file.
3 | *
4 | */
5 |
6 | // Step #5: Create static pages using createPage API
7 | const path = require(`path`)
8 |
9 | exports.createPages = async ({ actions, graphql, reporter }) => {
10 | const { createPage } = actions
11 |
12 | const blogPostTemplate = path.resolve(`src/templates/blogTemplate.js`)
13 |
14 | const result = await graphql(`
15 | {
16 | allMarkdownRemark(
17 | sort: { order: DESC, fields: [frontmatter___date] }
18 | limit: 1000
19 | ) {
20 | edges {
21 | node {
22 | frontmatter {
23 | path
24 | }
25 | }
26 | }
27 | }
28 | }
29 | `)
30 |
31 | // Handle errors
32 | if (result.errors) {
33 | reporter.panicOnBuild(`Error while running GraphQL query.`)
34 | return
35 | }
36 |
37 | result.data.allMarkdownRemark.edges.forEach(({ node }) => {
38 | createPage({
39 | path: node.frontmatter.path,
40 | component: blogPostTemplate,
41 | context: {}, // additional data can be passed via context
42 | })
43 | })
44 | }
45 |
46 | const { createFilePath } = require(`gatsby-source-filesystem`)
47 |
48 | exports.onCreateNode = ({ node, actions, getNode }) => {
49 | const { createNodeField } = actions
50 | if (node.internal.type === `MarkdownRemark`) {
51 | const value = createFilePath({ node, getNode })
52 | createNodeField({
53 | name: `slug`,
54 | node,
55 | value,
56 | })
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/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 | "gatsby": "^2.15.11",
9 | "gatsby-image": "^2.2.17",
10 | "gatsby-plugin-feed": "^2.3.13",
11 | "gatsby-plugin-manifest": "^2.2.15",
12 | "gatsby-plugin-offline": "^2.2.10",
13 | "gatsby-plugin-react-helmet": "^3.1.6",
14 | "gatsby-plugin-sharp": "^2.2.20",
15 | "gatsby-plugin-sitemap": "^2.2.11",
16 | "gatsby-remark-embed-video": "^1.7.1",
17 | "gatsby-remark-images": "^3.1.20",
18 | "gatsby-remark-responsive-iframe": "^2.2.14",
19 | "gatsby-source-filesystem": "^2.1.21",
20 | "gatsby-transformer-remark": "^2.6.21",
21 | "gatsby-transformer-sharp": "^2.2.13",
22 | "prop-types": "^15.7.2",
23 | "react": "^16.9.0",
24 | "react-dom": "^16.9.0",
25 | "react-helmet": "^5.2.1"
26 | },
27 | "devDependencies": {
28 | "prettier": "^1.18.2"
29 | },
30 | "keywords": [
31 | "gatsby"
32 | ],
33 | "license": "MIT",
34 | "scripts": {
35 | "build": "gatsby build",
36 | "develop": "gatsby develop",
37 | "format": "prettier --write \"**/*.{js,jsx,json,md}\"",
38 | "start": "npm run develop",
39 | "serve": "gatsby serve",
40 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing \""
41 | },
42 | "repository": {
43 | "type": "git",
44 | "url": "https://github.com/gatsbyjs/gatsby-starter-default"
45 | },
46 | "bugs": {
47 | "url": "https://github.com/gatsbyjs/gatsby/issues"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/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, 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 |
72 | )
73 | }
74 |
75 | SEO.defaultProps = {
76 | lang: `en`,
77 | meta: [],
78 | description: ``,
79 | }
80 |
81 | SEO.propTypes = {
82 | description: PropTypes.string,
83 | lang: PropTypes.string,
84 | meta: PropTypes.arrayOf(PropTypes.object),
85 | title: PropTypes.string.isRequired,
86 | }
87 |
88 | export default SEO
89 |
--------------------------------------------------------------------------------
/gatsby-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | siteMetadata: {
3 | title: `WordSesh September 2019`,
4 | description: `Kick off with your next, Gatsby website by optimizing it for sitemaps, handling markdown pages, embedding videos and rss feed.`,
5 | author: `@MaedahBatool`,
6 | siteUrl: `https://maedahbatool.com`,
7 | siteUrlNoSlash: `https://maedahbatool.com`,
8 | },
9 | plugins: [
10 | // Adding RSS Feed to Your Gatsby Blog
11 |
12 | {
13 | resolve: `gatsby-plugin-feed`,
14 | options: {
15 | query: `
16 | {
17 | site {
18 | siteMetadata {
19 | title
20 | description
21 | siteUrl
22 | site_url: siteUrl
23 | }
24 | }
25 | }
26 | `,
27 | feeds: [
28 | {
29 | serialize: ({ query: { site, allMarkdownRemark } }) => {
30 | return allMarkdownRemark.edges.map(edge => {
31 | return Object.assign({}, edge.node.frontmatter, {
32 | description: edge.node.excerpt,
33 | date: edge.node.frontmatter.date,
34 | url: site.siteMetadata.siteUrl + edge.node.fields.slug,
35 | guid: site.siteMetadata.siteUrl + edge.node.fields.slug,
36 | custom_elements: [{ "content:encoded": edge.node.html }],
37 | })
38 | })
39 | },
40 | query: `
41 | {
42 | allMarkdownRemark(
43 | sort: { order: DESC, fields: [frontmatter___date] },
44 | ) {
45 | edges {
46 | node {
47 | excerpt
48 | html
49 | fields { slug }
50 | frontmatter {
51 | title
52 | date
53 | }
54 | }
55 | }
56 | }
57 | }
58 | `,
59 | output: "/rss.xml",
60 | title: "My Demo Site's RSS Feed",
61 | // optional configuration to insert feed reference in pages:
62 | // if `string` is used, it will be used to create RegExp and then test if pathname of
63 | // current page satisfied this regular expression;
64 | // if not provided or `undefined`, all pages will have feed reference inserted
65 | match: "^/blog/",
66 | },
67 | ],
68 | },
69 | },
70 | // Adding Sitemap to Your Gatsby Blog
71 | {
72 | resolve: `gatsby-plugin-sitemap`,
73 | options: {
74 | query: `
75 | {
76 | site {
77 | siteMetadata {
78 | siteUrl
79 | }
80 | }
81 |
82 | allSitePage {
83 | edges {
84 | node {
85 | path
86 | }
87 | }
88 | }
89 | }`,
90 | serialize: ({ site, allSitePage }) =>
91 | allSitePage.edges.map(edge => {
92 | return {
93 | url: site.siteMetadata.siteUrl + edge.node.path,
94 | changefreq: `daily`,
95 | priority: 0.7,
96 | }
97 | }),
98 | },
99 | },
100 | {
101 | resolve: `gatsby-source-filesystem`,
102 | options: {
103 | name: `images`,
104 | path: `${__dirname}/src/images`,
105 | },
106 | },
107 | `gatsby-transformer-sharp`,
108 | `gatsby-plugin-sharp`,
109 | {
110 | resolve: `gatsby-source-filesystem`,
111 | options: {
112 | name: `markdown-pages`,
113 | path: `${__dirname}/src/markdown-pages`,
114 | },
115 | },
116 | // Remark.
117 | {
118 | resolve: `gatsby-transformer-remark`,
119 | options: {
120 | plugins: [
121 | {
122 | // Using gatsby-remark-embed-video before gatsby-remark-images & gatsby-remark-responsive-iframe plugins.
123 | resolve: `gatsby-remark-embed-video`,
124 | options: {
125 | maxWidth: 800,
126 | ratio: 1.77,
127 | height: 400,
128 | related: false,
129 | noIframerder: true,
130 | },
131 | },
132 | {
133 | resolve: `gatsby-remark-images`,
134 | options: {
135 | maxWidth: 590,
136 | },
137 | },
138 | {
139 | resolve: `gatsby-remark-responsive-iframe`,
140 | options: {
141 | wrapperStyle: `margin-bottom: 1.0725rem`,
142 | },
143 | },
144 | ],
145 | },
146 | },
147 | ],
148 | }
149 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Optimizing Your Gatsby.js Website for Production
5 |
6 |
7 |
8 |
9 | Building static sites with `React.js` using **Gatsby** provides an **easy to deploy setup**, **blazing fast speed**, and **smooth developer experience**. We are all aware of the three fundamentals of website development i.e.,
10 |
11 | - Development
12 | - Staging
13 | - Production
14 |
15 | **JAMstack (JavaScript APIs Markup)** is awesome and being the recent trend I am going to explain some of the best ways through which you can optimize your `Gatsby.js` website before production.
16 |
17 | Before we start make sure you have configured a basic Gatsby project setup.
18 |
19 | ## Optimizing Gatsby.js Site
20 |
21 |
22 | Step #0: Don't have a Gatsby site setup? Read this. (CLICK TO EXPAND!)
23 |
24 | In case you are an absolute beginner and 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.
25 |
26 | - Install the Gatsby CLI by typing the following command in your terminal
27 |
28 | ```sh
29 | npm install -g gatsby-cli
30 | ```
31 |
32 | - Next, create a new Gatsby.js site through the following.
33 |
34 | ```sh
35 | gatsby new site-name
36 | ```
37 |
38 | - To access your site folder contents type the following.
39 |
40 | ```sh
41 | cd site-name
42 | ```
43 |
44 | - Finally, start the development server to begin building your Gatsby.js site.
45 |
46 | ```sh
47 | gatsby develop
48 | ```
49 |
50 |
51 |
52 | To optimize a Gatsby site make sure you have the following functionalities set up and running:
53 |
54 | - Sitemaps
55 | - Markdown Pages
56 | - Embed Videos
57 | - RSS Feed
58 |
59 | ### 🔘Adding Custom Sitemaps
60 |
61 | Sitemaps maintains a list of all pages to tell search engines like Google about the organization of your site content. These prompts information about an unindexed
62 | page to get it appropriately indexed. They are equally important for new and old sites. But a new website needs sitemap since it is difficult for search engines to find posts and pages of a new site.
63 |
64 | You can add custom sitemaps in Gatsby through the `[gatsby-plugin-sitemap]` plugin.
65 |
66 | Inside your terminal type the following to install this plugin.
67 |
68 | ```sh
69 | npm install -- save gatsby-plugin-sitemap
70 | ```
71 |
72 | ### 🔘 Adding Markdown Pages
73 |
74 | Gatsby plugins can read folders/files with markdown and create pages from them. Is important since writing in markdown is always easy of eyes, user friendly with less errors. So, the process of adding and rendering markdown in Gatsby is that the plugins read files from filesystem. Then it transforms markdown to html and frontmatter to data. Finally, using the create page API you build page components.
75 |
76 | All this is done via using the `gatsby-source-filesystem` plugin.
77 |
78 | Inside your terminal type the following to install this plugin.
79 |
80 | ```sh
81 | npm install -- save gatsby-file-sourcesystem
82 | ```
83 |
84 | But to make this plugin work you need a pre-requisite plugin i.e., `gatsby-transformer-remark` which is installed via the following:
85 |
86 | ```sh
87 | npm install -- save gatsby-transformer-remark
88 | ```
89 |
90 | ### 🔘 Embedding Videos in Gatsby.js
91 |
92 | Different web applications render media files especially videos and GIFs differently. With Gatsby, plugins helps you source videos from a variety of video hosts like YouTube, Vimeo, Dailymotion, etc.
93 |
94 | The `gatsby-remark-embed-video` plugin is a great piece of software for this purpose.
95 |
96 | In your terminal type the following for plugin installation:
97 |
98 | ```sh
99 | npm i gatsby-remark-embed-video
100 | ```
101 |
102 | Also, this plugin require some other plugins to be installed first. These are:
103 |
104 | - `gatsby-remark-responsive-iframe`
105 | - `gatsby-transformer-remark`
106 | - `gatsby-remark-images`
107 |
108 | Note that if you’re using the `gatsby-remark-responsive-iframe` plugin, you have to ensure that the `gatsby-remark-embed-video` plugin is defined first.
109 |
110 | ### 🔘 Adding RSS Feed
111 |
112 | When developing a Gatsby.js, website it is important to optimize for RSS Feed since it makes your site content easy to subscribe through feed reader apps.
113 |
114 | The `gatsby-plugin-feed` serves the purpose really well.
115 |
116 | Install it via the following command:
117 |
118 | ```sh
119 | npm install -- save gatsby-plugin-feed
120 | ```
121 |
122 | It needs the following two plugins as a pre-reqs:
123 |
124 | - `gatsby-transformer-remark`
125 | - `gatsby-source-filesystem`
126 |
127 | ### 🔘 Final Build & Deploy
128 |
129 | After you have optimized your Gatsby website for the aforementioned functionalities you can run the final build command and then deploy it to some live environment. I am a huge fan of **Netlify** and host all my JAMstack sites through it.
130 |
131 | That's about it! I hope you find this learning material helpful. You can share your feedback by 🌟this repo. For any queries and suggestions PRs are welcomed.
132 |
133 | 🔘 **SLIDES**: https://Maedah.dev/WDSlidesSep19
134 |
135 | > 👋 **[Follow @MaedahBatool on Twitter](https://twitter.com/MaedahBatool/) →**
136 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------