├── .nvmrc ├── renovate.json ├── .huskyrc.js ├── lint-staged.config.js ├── content └── blog │ ├── 2017-07-10-about-me │ ├── ui-and-code.png │ └── index.md │ ├── 2023-08-18-the-ai-gap │ ├── images │ │ ├── ai.png │ │ └── ai-prompting.png │ └── index.md │ ├── on-excellence │ ├── images │ │ └── excellence.png │ └── index.md │ ├── 2017-07-13-hello-world │ ├── ui-and-code.png │ ├── media │ │ └── introduction.mp4 │ └── index.md │ ├── 2019-01-04-seo-and-gatsby │ ├── images │ │ ├── seo.jpg │ │ ├── slack.png │ │ ├── facebook.png │ │ ├── google.png │ │ └── twitter.png │ └── index.md │ ├── 2017-07-17-getting-started-with-gatsby │ ├── preview.png │ ├── images │ │ ├── blog-listing.png │ │ ├── dream-bigger.jpeg │ │ ├── my-first-blog-post.jpeg │ │ └── my-first-blog-post.png │ └── index.md │ ├── 2018-06-15-graphql-most-of-the-parts │ ├── images │ │ ├── 01-0.png │ │ ├── 02-1.png │ │ ├── 03-2.png │ │ ├── 04-3.png │ │ ├── 05-4.png │ │ ├── 06-5.png │ │ ├── 07-6.png │ │ ├── 08-7.png │ │ ├── 09-8.png │ │ ├── 10-9.png │ │ ├── 11-10.png │ │ ├── 12-11.png │ │ ├── 13-12.png │ │ ├── 14-13.png │ │ ├── 15-14.png │ │ ├── 16-15.png │ │ ├── 17-16.png │ │ ├── 18-17.png │ │ ├── 19-18.png │ │ ├── 20-19.png │ │ ├── 21-20.png │ │ ├── 22-21.png │ │ ├── 23-22.png │ │ ├── 24-23.png │ │ ├── 25-24.png │ │ ├── 27-26.png │ │ ├── 28-27.png │ │ ├── 29-28.png │ │ ├── 30-29.png │ │ ├── 31-30.png │ │ ├── 32-31.png │ │ ├── 33-32.png │ │ ├── 34-33.png │ │ ├── 35-34.png │ │ ├── 36-35.png │ │ ├── 37-36.png │ │ ├── 38-37.png │ │ ├── 39-38.png │ │ ├── 40-39.png │ │ ├── 41-40.png │ │ ├── 42-41.png │ │ ├── 43-42.png │ │ ├── 44-43.png │ │ ├── 45-44.png │ │ ├── 46-45.png │ │ ├── 47-46.png │ │ ├── 48-47.png │ │ ├── 49-48.png │ │ ├── 50-49.png │ │ ├── 51-50.png │ │ ├── 52-51.png │ │ ├── 54-53.png │ │ ├── 55-54.png │ │ ├── 56-55.png │ │ ├── 57-56.png │ │ ├── 58-57.png │ │ ├── 59-58.png │ │ ├── 60-59.png │ │ ├── 61-60.png │ │ ├── 26-resolvers-in-depth.png │ │ └── 53-apollo-boost-example.png │ └── index.md │ ├── 2017-07-21-writing-an-open-source-library │ ├── preview.png │ ├── images │ │ └── troll-face.jpeg │ └── index.md │ ├── 2018-09-04-my-next-chapter │ ├── images │ │ └── my-next-chapter.jpg │ └── index.md │ ├── 2017-10-27-css-in-js-benefits-drawbacks-and-tooling │ ├── preview.png │ ├── images │ │ └── screenshots │ │ │ ├── 01-0.png │ │ │ ├── 35-is.png │ │ │ ├── 16-bem.png │ │ │ ├── 17-run.png │ │ │ ├── 07-to-here.png │ │ │ ├── 33-is-not.png │ │ │ ├── 47-caveat.png │ │ │ ├── 52-emotion.png │ │ │ ├── 62-usage.png │ │ │ ├── 70-nesting.png │ │ │ ├── 83-happy.png │ │ │ ├── 87-links.png │ │ │ ├── 02-about-me.png │ │ │ ├── 05-sponsors.png │ │ │ ├── 06-from-here.png │ │ │ ├── 15-but-wait.png │ │ │ ├── 38-powerful.png │ │ │ ├── 50-glamorous.png │ │ │ ├── 54-polished.png │ │ │ ├── 61-companies.png │ │ │ ├── 65-real-css.png │ │ │ ├── 66-animation.png │ │ │ ├── 08-the-problems.png │ │ │ ├── 09-first-button.png │ │ │ ├── 11-third-button.png │ │ │ ├── 13-the-globals.png │ │ │ ├── 19-hard-stuff.png │ │ │ ├── 20-alternatives.png │ │ │ ├── 28-not-broken.png │ │ │ ├── 30-lesh-tweet.png │ │ │ ├── 36-abstractions.png │ │ │ ├── 39-real-styles.png │ │ │ ├── 63-using-props.png │ │ │ ├── 64-inheritance.png │ │ │ ├── 82-instructions.png │ │ │ ├── 86-attributions.png │ │ │ ├── 10-second-button.png │ │ │ ├── 12-fourth-button.png │ │ │ ├── 27-benefits-intro.png │ │ │ ├── 34-inline-styles.png │ │ │ ├── 37-scoped-styles.png │ │ │ ├── 71-theming-intro.png │ │ │ ├── 72-theme-provider.png │ │ │ ├── 75-not-scrapeable.png │ │ │ ├── 76-editor-tooling.png │ │ │ ├── 81-wrap-up-intro.png │ │ │ ├── 03-nebraska-actual.png │ │ │ ├── 04-object-partners.png │ │ │ ├── 14-global-problems.png │ │ │ ├── 22-it-does-not-scale.png │ │ │ ├── 24-sharing-constants.png │ │ │ ├── 26-facebook-problems.png │ │ │ ├── 29-but-maybe-it-is.png │ │ │ ├── 41-component-styling.png │ │ │ ├── 43-semantic-elements.png │ │ │ ├── 46-libraries-intro.png │ │ │ ├── 48-styled-components.png │ │ │ ├── 51-glamorous-example.png │ │ │ ├── 53-emotion-example.png │ │ │ ├── 55-polished-example.png │ │ │ ├── 56-polished-methods.png │ │ │ ├── 57-other-libraries.png │ │ │ ├── 67-using-class-name.png │ │ │ ├── 69-injecting-globals.png │ │ │ ├── 73-drawbacks-intro.png │ │ │ ├── 85-people-to-follow.png │ │ │ ├── 21-shadow-dom-support.png │ │ │ ├── 40-real-styles-example.png │ │ │ ├── 42-java-script-styling.png │ │ │ ├── 44-semantic-comparison.png │ │ │ ├── 59-github-stars-count.png │ │ │ ├── 60-payload-size-chart.png │ │ │ ├── 68-external-libraries.png │ │ │ ├── 23-dead-code-elimination.png │ │ │ ├── 31-seperation-of-concerns.png │ │ │ ├── 45-style-cognitive-load.png │ │ │ ├── 58-library-download-count.png │ │ │ ├── 74-java-script-disabled.png │ │ │ ├── 77-editor-tooling-plugin.png │ │ │ ├── 78-sanitization-concerns.png │ │ │ ├── 79-performance-concerns.png │ │ │ ├── 84-css-in-js-playground.png │ │ │ ├── 18-safety-through-automation.png │ │ │ ├── 25-sharing-constants-example.png │ │ │ ├── 49-styled-components-example.png │ │ │ ├── 80-performance-chart-example.png │ │ │ ├── 88-fin-the-end-thats-all-folks.png │ │ │ └── 32-seperation-of-concerns-image.png │ └── index.md │ └── 2018-08-14-css-in-js-with-styled-components-and-react │ ├── images │ └── featured.jpg │ └── index.md ├── netlify.toml ├── gatsby-config.js ├── .gitignore ├── package.json ├── .travis.yml ├── README.md ├── LICENSE ├── .circleci └── config.yml └── src └── @dschau └── gatsby-theme-blog └── components └── about.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 8 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.huskyrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | "pre-commit": "lint-staged" 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /lint-staged.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "*.{js,css,md,json,yml,yaml}": ["prettier --write", "git add"] 3 | }; 4 | -------------------------------------------------------------------------------- /content/blog/2017-07-10-about-me/ui-and-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-10-about-me/ui-and-code.png -------------------------------------------------------------------------------- /content/blog/2023-08-18-the-ai-gap/images/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2023-08-18-the-ai-gap/images/ai.png -------------------------------------------------------------------------------- /content/blog/on-excellence/images/excellence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/on-excellence/images/excellence.png -------------------------------------------------------------------------------- /content/blog/2017-07-13-hello-world/ui-and-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-13-hello-world/ui-and-code.png -------------------------------------------------------------------------------- /content/blog/2019-01-04-seo-and-gatsby/images/seo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2019-01-04-seo-and-gatsby/images/seo.jpg -------------------------------------------------------------------------------- /content/blog/2019-01-04-seo-and-gatsby/images/slack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2019-01-04-seo-and-gatsby/images/slack.png -------------------------------------------------------------------------------- /content/blog/2017-07-13-hello-world/media/introduction.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-13-hello-world/media/introduction.mp4 -------------------------------------------------------------------------------- /content/blog/2019-01-04-seo-and-gatsby/images/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2019-01-04-seo-and-gatsby/images/facebook.png -------------------------------------------------------------------------------- /content/blog/2019-01-04-seo-and-gatsby/images/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2019-01-04-seo-and-gatsby/images/google.png -------------------------------------------------------------------------------- /content/blog/2019-01-04-seo-and-gatsby/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2019-01-04-seo-and-gatsby/images/twitter.png -------------------------------------------------------------------------------- /content/blog/2023-08-18-the-ai-gap/images/ai-prompting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2023-08-18-the-ai-gap/images/ai-prompting.png -------------------------------------------------------------------------------- /content/blog/2017-07-17-getting-started-with-gatsby/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-17-getting-started-with-gatsby/preview.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/01-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/01-0.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/02-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/02-1.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/03-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/03-2.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/04-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/04-3.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/05-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/05-4.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/06-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/06-5.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/07-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/07-6.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/08-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/08-7.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/09-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/09-8.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/10-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/10-9.png -------------------------------------------------------------------------------- /content/blog/2017-07-21-writing-an-open-source-library/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-21-writing-an-open-source-library/preview.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/11-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/11-10.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/12-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/12-11.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/13-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/13-12.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/14-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/14-13.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/15-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/15-14.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/16-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/16-15.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/17-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/17-16.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/18-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/18-17.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/19-18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/19-18.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/20-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/20-19.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/21-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/21-20.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/22-21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/22-21.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/23-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/23-22.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/24-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/24-23.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/25-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/25-24.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/27-26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/27-26.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/28-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/28-27.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/29-28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/29-28.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/30-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/30-29.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/31-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/31-30.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/32-31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/32-31.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/33-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/33-32.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/34-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/34-33.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/35-34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/35-34.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/36-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/36-35.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/37-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/37-36.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/38-37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/38-37.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/39-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/39-38.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/40-39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/40-39.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/41-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/41-40.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/42-41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/42-41.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/43-42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/43-42.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/44-43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/44-43.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/45-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/45-44.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/46-45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/46-45.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/47-46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/47-46.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/48-47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/48-47.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/49-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/49-48.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/50-49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/50-49.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/51-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/51-50.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/52-51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/52-51.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/54-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/54-53.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/55-54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/55-54.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/56-55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/56-55.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/57-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/57-56.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/58-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/58-57.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/59-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/59-58.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/60-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/60-59.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/61-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/61-60.png -------------------------------------------------------------------------------- /content/blog/2018-09-04-my-next-chapter/images/my-next-chapter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-09-04-my-next-chapter/images/my-next-chapter.jpg -------------------------------------------------------------------------------- /content/blog/2017-07-17-getting-started-with-gatsby/images/blog-listing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-17-getting-started-with-gatsby/images/blog-listing.png -------------------------------------------------------------------------------- /content/blog/2017-07-17-getting-started-with-gatsby/images/dream-bigger.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-17-getting-started-with-gatsby/images/dream-bigger.jpeg -------------------------------------------------------------------------------- /content/blog/2017-07-21-writing-an-open-source-library/images/troll-face.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-21-writing-an-open-source-library/images/troll-face.jpeg -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/preview.png -------------------------------------------------------------------------------- /content/blog/2017-07-17-getting-started-with-gatsby/images/my-first-blog-post.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-17-getting-started-with-gatsby/images/my-first-blog-post.jpeg -------------------------------------------------------------------------------- /content/blog/2017-07-17-getting-started-with-gatsby/images/my-first-blog-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-07-17-getting-started-with-gatsby/images/my-first-blog-post.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/26-resolvers-in-depth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/26-resolvers-in-depth.png -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/images/53-apollo-boost-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-06-15-graphql-most-of-the-parts/images/53-apollo-boost-example.png -------------------------------------------------------------------------------- /content/blog/2018-08-14-css-in-js-with-styled-components-and-react/images/featured.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2018-08-14-css-in-js-with-styled-components-and-react/images/featured.jpg -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/01-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/01-0.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/35-is.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/35-is.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/16-bem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/16-bem.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/17-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/17-run.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/07-to-here.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/07-to-here.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/33-is-not.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/33-is-not.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/47-caveat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/47-caveat.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/52-emotion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/52-emotion.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/62-usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/62-usage.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/70-nesting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/70-nesting.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/83-happy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/83-happy.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/87-links.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/87-links.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/02-about-me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/02-about-me.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/05-sponsors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/05-sponsors.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/06-from-here.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/06-from-here.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/15-but-wait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/15-but-wait.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/38-powerful.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/38-powerful.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/50-glamorous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/50-glamorous.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/54-polished.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/54-polished.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/61-companies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/61-companies.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/65-real-css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/65-real-css.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/66-animation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/66-animation.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/08-the-problems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/08-the-problems.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/09-first-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/09-first-button.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/11-third-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/11-third-button.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/13-the-globals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/13-the-globals.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/19-hard-stuff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/19-hard-stuff.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/20-alternatives.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/20-alternatives.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/28-not-broken.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/28-not-broken.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/30-lesh-tweet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/30-lesh-tweet.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/36-abstractions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/36-abstractions.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/39-real-styles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/39-real-styles.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/63-using-props.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/63-using-props.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/64-inheritance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/64-inheritance.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/82-instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/82-instructions.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/86-attributions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/86-attributions.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/10-second-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/10-second-button.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/12-fourth-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/12-fourth-button.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/27-benefits-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/27-benefits-intro.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/34-inline-styles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/34-inline-styles.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/37-scoped-styles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/37-scoped-styles.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/71-theming-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/71-theming-intro.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/72-theme-provider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/72-theme-provider.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/75-not-scrapeable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/75-not-scrapeable.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/76-editor-tooling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/76-editor-tooling.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/81-wrap-up-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/81-wrap-up-intro.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/03-nebraska-actual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/03-nebraska-actual.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/04-object-partners.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/04-object-partners.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/14-global-problems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/14-global-problems.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/22-it-does-not-scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/22-it-does-not-scale.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/24-sharing-constants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/24-sharing-constants.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/26-facebook-problems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/26-facebook-problems.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/29-but-maybe-it-is.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/29-but-maybe-it-is.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/41-component-styling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/41-component-styling.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/43-semantic-elements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/43-semantic-elements.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/46-libraries-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/46-libraries-intro.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/48-styled-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/48-styled-components.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/51-glamorous-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/51-glamorous-example.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/53-emotion-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/53-emotion-example.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/55-polished-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/55-polished-example.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/56-polished-methods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/56-polished-methods.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/57-other-libraries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/57-other-libraries.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/67-using-class-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/67-using-class-name.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/69-injecting-globals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/69-injecting-globals.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/73-drawbacks-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/73-drawbacks-intro.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/85-people-to-follow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/85-people-to-follow.png -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [[redirects]] 2 | from = "/*" 3 | to = "https://dustinschau.com/posts/:splat" 4 | status = 301 5 | force = true 6 | 7 | [[redirects]] 8 | from = "/" 9 | to = "https://dustinschau.com/posts" 10 | status = 301 11 | force = true -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/21-shadow-dom-support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/21-shadow-dom-support.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/40-real-styles-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/40-real-styles-example.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/42-java-script-styling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/42-java-script-styling.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/44-semantic-comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/44-semantic-comparison.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/59-github-stars-count.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/59-github-stars-count.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/60-payload-size-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/60-payload-size-chart.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/68-external-libraries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/68-external-libraries.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/23-dead-code-elimination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/23-dead-code-elimination.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/31-seperation-of-concerns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/31-seperation-of-concerns.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/45-style-cognitive-load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/45-style-cognitive-load.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/58-library-download-count.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/58-library-download-count.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/74-java-script-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/74-java-script-disabled.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/77-editor-tooling-plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/77-editor-tooling-plugin.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/78-sanitization-concerns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/78-sanitization-concerns.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/79-performance-concerns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/79-performance-concerns.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/84-css-in-js-playground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/84-css-in-js-playground.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/18-safety-through-automation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/18-safety-through-automation.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/25-sharing-constants-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/25-sharing-constants-example.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/49-styled-components-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/49-styled-components-example.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/80-performance-chart-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/80-performance-chart-example.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/88-fin-the-end-thats-all-folks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/88-fin-the-end-thats-all-folks.png -------------------------------------------------------------------------------- /content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/32-seperation-of-concerns-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DSchau/blog/HEAD/content/blog/2017-10-27-css-in-js-benefits-drawbacks-and-tooling/images/screenshots/32-seperation-of-concerns-image.png -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | process.noDeprecation = true; // https://github.com/webpack/webpack/issues/6568 2 | 3 | const siteUrl = 4 | process.env.URL || process.env.DEPLOY_URL || "https://blog.dustinschau.com"; 5 | 6 | module.exports = { 7 | siteMetadata: { 8 | author: "Dustin Schau", 9 | description: 10 | "The blog of the Omaha, Nebraska based software engineer, Dustin Schau", 11 | siteUrl, 12 | social: { 13 | twitter: "schaudustin" 14 | } 15 | }, 16 | __experimentalThemes: [ 17 | { 18 | resolve: "@dschau/gatsby-theme-blog", 19 | options: { 20 | root: __dirname 21 | } 22 | } 23 | ] 24 | }; 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | .gatsby-context.js 29 | .sass-cache/ 30 | public/ 31 | .cache/ 32 | 33 | # misc 34 | 35 | .DS_Store 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dschau/blog", 3 | "description": "Dustin Schau's personal blog powered by Gatsby", 4 | "version": "1.0.0", 5 | "private": true, 6 | "author": "Dustin Schau (https://blog.dustinschau.com)", 7 | "dependencies": { 8 | "@dschau/gatsby-theme-blog": "^0.2.3", 9 | "gatsby": "^2.1.4", 10 | "react": "^16.8.2", 11 | "react-dom": "^16.8.2" 12 | }, 13 | "devDependencies": { 14 | "husky": "1.3.1", 15 | "lint-staged": "8.1.3", 16 | "prettier": "1.15.3" 17 | }, 18 | "keywords": [ 19 | "gatsby", 20 | "blog", 21 | "react" 22 | ], 23 | "license": "MIT", 24 | "main": "n/a", 25 | "scripts": { 26 | "build": "gatsby build", 27 | "develop": "gatsby develop", 28 | "serve": "gatsby serve", 29 | "test": "exit 0", 30 | "start": "npm run develop" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | cache: 5 | yarn: true 6 | 7 | before_install: 8 | - export PATH=$PATH:`yarn global bin` 9 | - yarn global add travis-ci-cloudfront-invalidation 10 | - yarn global add greenkeeper-lockfile@1 11 | install: yarn 12 | 13 | before_script: greenkeeper-lockfile-update 14 | script: yarn test 15 | after_script: greenkeeper-lockfile-upload 16 | 17 | before_deploy: yarn build 18 | deploy: 19 | provider: s3 20 | access_key_id: $AWS_ACCESS_KEY_ID 21 | secret_access_key: $AWS_SECRET_ACCESS_KEY 22 | bucket: "blog.dustinschau.com" 23 | skip_cleanup: true 24 | local-dir: public 25 | acl: public_read 26 | on: 27 | branch: master 28 | after_deploy: 29 | - travis-ci-cloudfront-invalidation -a $AWS_ACCESS_KEY_ID -s $AWS_SECRET_ACCESS_KEY -c $AWS_CLOUDFRONT_ID -i '/*' -b $TRAVIS_BRANCH -p $TRAVIS_PULL_REQUEST 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blog 2 | 3 | [![CircleCI](https://circleci.com/gh/DSchau/blog.svg?style=svg)](https://circleci.com/gh/DSchau/blog) 4 | 5 | The source code for the [Gatsby][gatsby] driven statically generated blog. See [dschau/gatsby-theme-blog][blog-theme] for the theme that powers the functionality. 6 | 7 | ![blog](https://screenshot-v2.now.sh/blog.dustinschau.com?type=png) 8 | 9 | ## Tech stack 10 | 11 | - [gatsby v2][gatsby] 12 | - An awesome React powered app compiler 13 | - CSS in JS with [emotion][emotion] 14 | - "The Next Generation of CSS-in-JS," used as a styling solution 15 | - [particles.js][particles.js] 16 | - A nifty particle effect seen in the header 17 | - [markdown][markdown] 18 | - Each and every post is authored in Markdown parsed by [remark][remark] 19 | 20 | [blog-theme]: https://github.com/dschau/gatsby-theme-blog 21 | [gatsby]: https://github.com/gatsbyjs/gatsby 22 | [emotion]: https://emotion.sh/ 23 | [particles.js]: https://github.com/VincentGarreau/particles.js/ 24 | [markdown]: https://en.wikipedia.org/wiki/Markdown 25 | [remark]: http://remark.js.org/ 26 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | executors: 3 | node: 4 | parameters: 5 | image: 6 | type: string 7 | default: "11" 8 | docker: 9 | - image: circleci/node:<< parameters.image >> 10 | 11 | aliases: 12 | restore_cache: &restore_cache 13 | restore_cache: 14 | name: Restore node_modules cache 15 | keys: 16 | - yarn-cypress-cache-{{ checksum "yarn.lock" }} 17 | 18 | install_node_modules: &install_node_modules 19 | run: 20 | name: Install node modules 21 | command: yarn --frozen-lockfile 22 | 23 | persist_cache: &persist_cache 24 | save_cache: 25 | name: Save node modules cache 26 | key: yarn-cypress-cache-{{ checksum "yarn.lock" }} 27 | paths: 28 | - ~/.cache 29 | 30 | jobs: 31 | build: 32 | executor: node 33 | steps: 34 | - checkout 35 | - <<: *restore_cache 36 | - <<: *install_node_modules 37 | - <<: *persist_cache 38 | - run: yarn build 39 | - persist_to_workspace: 40 | root: public 41 | paths: 42 | - "*" 43 | deploy: 44 | docker: 45 | - image: circleci/python:2.7-jessie 46 | steps: 47 | - attach_workspace: 48 | at: public 49 | - run: sudo pip install awscli 50 | - run: > 51 | aws s3 sync public s3://blog.dustinschau.com --acl public-read --delete 52 | - run: > 53 | aws cloudfront create-invalidation --distribution-id $AWS_CLOUDFRONT_ID --paths /* 54 | 55 | workflows: 56 | version: 2 57 | build-and-deploy: 58 | jobs: 59 | - build 60 | - deploy: 61 | requires: 62 | - build 63 | filters: 64 | branches: 65 | only: 66 | - master 67 | -------------------------------------------------------------------------------- /content/blog/2018-09-04-my-next-chapter/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2018-09-04T20:50:21.302Z 3 | title: "My Next Chapter" 4 | excerpt: "I am happy to announce that I've accepted a role as Software Engineer for Gatsby Inc, a startup working on making a more performant web through smart defaults and optimizations." 5 | featured: images/my-next-chapter.jpg 6 | tags: 7 | - career 8 | - gatsby 9 | - gatsby inc 10 | - object partners 11 | --- 12 | 13 | ![My next chapter](./images/my-next-chapter.jpg) 14 | 15 | _(Pretend that's me and not Kevin Durant)_ 16 | 17 | I'm incredibly excited to announce that I've accepted a role with Gatsby Inc. working on an awesome static-site generator for React--although anyone who follows me on Twitter knows I think it's so much more 😅. 18 | 19 | For those who may not be aware of what Gatsby is, go check out [the documentation](https://gatsbyjs.org) and read up on the [company itself](https://gatsbyjs.com) if it tickles your fancy--oh, and this blog you're reading right now? Created with and powered by Gatsby! Gatsby powers an increasing number of incredibly successful and performant websites, including [the ReactJS.org docs](https://reactjs.org), [CSS Grid by Mozilla](https://mozilladevelopers.github.io/playground/), and [far, far more][site-showcase]. 20 | 21 | The role with Gatsby will be far different than anything I've done as of yet in my career, but I look very much forward to this next journey working on something that I believe to be transformative, powerful, and capable of shaping the modern web experience. 22 | 23 | ## Thank you 24 | 25 | I want to thank each and every one of my co-workers (and friends!) not only at Object Partners, but also Union Pacific. Both were transformative places in my career, and I can't recommend them both highly enough. Talented folks working on fun projects, what more could you want!? 26 | 27 | [site-showcase]: https://next.gatsbyjs.org/showcase/ 28 | -------------------------------------------------------------------------------- /src/@dschau/gatsby-theme-blog/components/about.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | import GatsbyImage from "gatsby-image"; 4 | 5 | import { rhythm } from "@dschau/gatsby-theme-blog/src/utils/typography"; 6 | import SocialIcons from "@dschau/gatsby-theme-blog/src/components/social-icons"; 7 | 8 | const Container = styled.div` 9 | display: flex; 10 | margin: ${rhythm(1)} auto; 11 | margin-bottom: 0; 12 | justify-content: space-between; 13 | align-items: center; 14 | position: relative; 15 | @media only screen and (min-width: 768px) { 16 | max-width: 75%; 17 | } 18 | `; 19 | 20 | const Image = styled(GatsbyImage)` 21 | border-radius: 100%; 22 | `; 23 | 24 | const Details = styled.div` 25 | display: flex; 26 | flex-direction: column; 27 | justify-content: flex-start; 28 | margin: 0 ${rhythm(1 / 2)}; 29 | @media only screen and (min-width: 768px) { 30 | margin: 0 ${rhythm(1)}; 31 | } 32 | `; 33 | 34 | const Name = styled.h1` 35 | margin: 0; 36 | padding: 0; 37 | padding-bottom: ${rhythm(1 / 4)}; 38 | font-size: ${rhythm(1)}; 39 | color: #002635; 40 | text-transform: uppercase; 41 | line-height: ${rhythm(1)}; 42 | `; 43 | 44 | const Last = styled.span` 45 | font-weight: 400; 46 | `; 47 | 48 | const Description = styled.p` 49 | margin-bottom: 0; 50 | color: #444; 51 | `; 52 | 53 | export default function About({ image }) { 54 | return ( 55 | 56 | {image && ( 57 |
58 | 59 |
60 | )} 61 |
62 | 63 | Dustin Schau 64 | 65 | 66 | Product-focused Engineering leader who likes building great, 67 | collaborative teams that ship (and yes, still codes). 68 | 69 |
70 | 71 |
72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /content/blog/on-excellence/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2023-08-14 3 | title: "Excellence" 4 | author: Dustin Schau 5 | draft: true 6 | featured: images/excellence.jpg 7 | excerpt: "Excellence is something that a lot of people talk about, but as we all know, showing and not just telling is better. Thus, this is a deep dive on what makes excellence and some updated and concrete examples of excellence on display." 8 | tags: 9 | - excellence 10 | --- 11 | 12 | _Note: this post is a work-in-progress. If you're reading this, kudos! I have a super fan. I'll update it with more examples on a rolling basis as I find them. Excellence is hard!_ 13 | 14 | Excellence is a concept that is often talked about, frequently claimed, and rare. Some examples of products, ideas, and concrete examples of excellence on display and what makes them excellent: 15 | 16 | - [**rsync, command-line utility for syncing files**](https://linux.die.net/man/1/rsync). `rsync` is a prototypical example of a utility that _just works_ every time, consistently, without fail. It does its core job completely: syncing files from a source to a destination consistently. 17 | - [**Uni-ball Kuru Toga, Mechanical Pencil**](https://uniballco.com/products/kuru-toga-mechanical-pencils). The best pencil I've ever used. The lead rotates subtly and slightly as you write, which keeps the lead sharp and your lines crisp and clean. 18 | - _Note: I'm kind of a pen/pencil nerd, check out [Jet Pens](https://www.jetpens.com/blog/Uni-Kuru-Toga-A-Comprehensive-Guide/pt/706) for some even nicer iterations of the Kuru Toga pencil_ 19 | - [**Nonstick pan, Made-in**](https://madeincookware.com/products/non-stick-frying-pan/10-inch-graphite). I've used countless iterations of "non-stick" pans and they all suffer from a singular fatal flaw: notably, that they _all_ begin to stick after a period of 3-6 months. After 1-year plus, still highly non-stick. 20 | 21 | For a similar post that served as inspiration for this post, please check out [Patrick Collison's Fast](https://patrickcollison.com/fast) which is a rolling list of projects that demonstrate some of humanity's best achievements, done **fast**. 22 | -------------------------------------------------------------------------------- /content/blog/2017-07-13-hello-world/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2017-07-13T05:00:00.000Z 3 | title: "Hello World" 4 | tags: 5 | - intro 6 | - about 7 | featured: ui-and-code.png 8 | excerpt: Who I am, what I do, and why you should care! This post goes into some detail about my general philosophy around blogging, what I hope to accomplish with this blog, and various other details… 9 | --- 10 | 11 |
12 | 16 |
17 | 18 | Hello! My name is Dustin Schau, and I'm a web developer working in Omaha, Nebraska. 19 | 20 | I've long wanted to get into blogging, but never found a CMS or system that I quite liked enough, nor that felt natural enough to continually use, so hopefully I've stumbled upon a system that I like and that will last. 21 | 22 | I hope to post a variety articles on a variety of topics and not pigeon-hole myself into _just_ technical articles. That said, the vast majority of stuff I'll post will be technical programming articles, so if that's not your thing, this blog _may_ not be for you. 23 | 24 | ## About me 25 | 26 | I'm a 20s something developer living in Omaha, Nebraska. I graduated from Creighton University (also in Omaha) with a degree in Computer Science that I've translated into my current career as a front-end developer. My current employer is [Object Partners, Inc.][opi]--an incredible IT consulting company headquartered in Minneapolis with smaller offices in Omaha, Milwaukee, and Chicago. I previously worked at [Union Pacific][union-pacific], where I worked on a team who development encapsulated components with AngularJS and Foundation. 27 | 28 | ### Technical interests 29 | 30 | I tend to skew quite heavily towards the front-end spectrum of development, and so I enjoy discussing/writing about JavaScript with a particular emphasis on frameworks and new technologies for development. You can regularly find me messing around with some new framework, implementing some new technology, or in general just tinkering and learning. 31 | 32 | ### Non-technical interests 33 | 34 | In my spare time, I enjoy golfing--although I am decidedly not that great with something like a 20+ handicap, going to movies, traveling and exploring the world, and mentoring, among many, many other interests! 35 | 36 | Now that we have that out of the way, I hope you enjoy your time here! Please always feel free to drop me a line at dustinschau [at] gmail [dot] com, or check out my [website][website] for more contact information and detail. 37 | 38 | [opi]: https://objectpartners.com/ 39 | [union-pacific]: https://up.com 40 | [website]: https://www.dustinschau.com 41 | -------------------------------------------------------------------------------- /content/blog/2018-08-14-css-in-js-with-styled-components-and-react/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | featured: images/featured.jpg 3 | date: 2018-08-15T00:00:00.756Z 4 | title: "CSS in JS with styled-components and React (Manning)" 5 | tags: 6 | - css in js 7 | - styled-components 8 | - react 9 | excerpt: "I'm incredibly excited to announce that I've been working on a Manning liveVideo course for the last several months with the intent to share all that makes CSS in JS great with the library styled-components" 10 | --- 11 | 12 | I am _incredibly_ excited to announce that for the last several months I've been working on a [Manning][manning] liveVideo course. The topic, as you may have imagined, is CSS in JS, specifically with a styled-components and React focus. 13 | 14 |

New @ManningBooks early access video: "CSS in JavaScript: With styled-components and React" by Dustin Schau @schaudustin #ReactJS #css #WebDev #JavaScript https://t.co/TKZVC882kC pic.twitter.com/S2cUqiEFm7

— John Dhabolt (@Dhabolt) August 8, 2018
15 | 16 | _Hot damn, it's happening!_ 17 | 18 | ## Approach 19 | 20 | However, a React focus can be somewhat limiting, so the last several lessons in the course focus on instrumenting CSS in JS _outside_ of React, e.g. with tools and techniques like CSS Modules, scoped selectors, and even a brief segue into web component land with the Shadow DOM. 21 | 22 | The intent is for the course to be super approachable to beginners. However, making something approachable to beginners doesn't necessarily mean that a variety of skillsets can't get value out of the course, and I'd like to think there's something here for not only beginners, but skillsets of a wide variety. 23 | 24 | ## Deal of the Day 25 | 26 | If that's not enough, the course has been selected as the "Deal of the Day" on **August 15th**! If this course sounds like it could be up your alley--and I truly believe it will be!--consider using the following code for 50% off if purchased on **August 15th** or **August 16th**. 27 | 28 |

dotd081518au

29 | 30 | Visit the [Deal of the Day Page][dod] to learn more! 31 | 32 | [manning]: https://www.manning.com/ 33 | [dod]: http://bit.ly/2nxt6sK 34 | -------------------------------------------------------------------------------- /content/blog/2017-07-10-about-me/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2017-07-10T23:36:56.503Z 3 | title: About 4 | tags: 5 | - tech stack 6 | - colophon 7 | - about 8 | featured: ui-and-code.png 9 | excerpt: Welcome to the second version of my blog, powered by Gatsby, an incredible site generator. Learn more about the tech stack and things I built to power this blog. 10 | --- 11 | 12 | Welcome to the second version of my blog, powered by [Gatsby][gatsby], an incredible static site generator. 13 | 14 | Inspired by [Daring Fireball][df], some detail will be provided for the technologies, applications, and techniques that power this site. 15 | 16 | ## Mac apps 17 | 18 | - [VSCode][vscode] 19 | - [Hyper][hyper] 20 | 21 | ## Backend software 22 | 23 | The site is hosted on [MediaTemple][media-temple]. 24 | 25 | Articles are written using Markdown, and are translated to HTML using [remark][remark]. 26 | 27 | The content is partially server-side rendered via [gatsby][gatsby], which uses react-dom to scaffold out the basis content, and then React running client side takes over for the now-hydrated web application. Theoretically, this will provide for great SEO as well as some dynamism via React/JavaScript run client side once the page is hydrated. 28 | 29 | The following gatsby plugins are each used as the backbone for much of the functionality present in this blog: 30 | 31 | - [gatsby-plugin-styled-components][gatsby-plugin-styled-components] 32 | - [gatsby-source-filesystem][gatsby-source-filesystem] 33 | - [gatsby-transformer-remark][gatsby-transformer-remark] 34 | - [gatsby-remark-copy-linked-files][gatsby-remark-copy-linked-files] 35 | - [gatsby-remark-smartypants][gatsby-remark-smartypants] 36 | - [gatsby-plugin-react-helmet][gatsby-plugin-react-helmet] 37 | 38 | ## Web technologies 39 | 40 | As much as possible, this site attempts to abide by current web standards with a baseline threshold targeting around or about IE 10. That means that my heavy usage of Flexbox (CSS) will not _quite_ be rendered perfectly in every circumstance, but in general, the goal is to be progressively enhanced so that the site is still readable and usable in a browser that doesn't have great support for Flexbox. 41 | 42 | ### [styled-components][styled-components] 43 | 44 | The incredible CSS library `styled-components` is used for the majority of the components rendered by the blog, particularly those not parsed via Markdown. 45 | 46 | ### Progressive enhancement 47 | 48 | Whenever possible, I attempt to only use JavaScript to _enhance_ the site, rather than serve as the only mechanism for functionality. For instance, the [Google fonts][google-fonts] Montserrat and Bitter are used, but they are loaded asyncronously with [`webfontloader`][webfontloader] and then persisted in sessionStorage with the following JavaScript snippet. This means that in an environment without JavaScript, the fallback fonts `Georgia, serif` will be used _until_ the webfonts have been loaded. 49 | 50 | ```javascript 51 | /* 52 | * https://css-tricks.com/loading-web-fonts-with-the-web-font-loader/ 53 | */ 54 | export default function loadWebFonts() { 55 | const families = ["Montserrat:400,700", "Bitter:400,700"]; 56 | if (sessionStorage.fonts === families.join(" ")) { 57 | document.documentElement.classList.add("wf-active"); 58 | } 59 | 60 | require.ensure("webfontloader", () => { 61 | const WebFonts = require("webfontloader"); 62 | 63 | WebFonts.load({ 64 | active() { 65 | sessionStorage.fonts = families.join(" "); 66 | }, 67 | google: { 68 | families 69 | }, 70 | timeout: 2000 71 | }); 72 | }); 73 | } 74 | ``` 75 | 76 | [gatsby]: https://github.com/gatsbyjs/gatsby 77 | [df]: https://daringfireball.net/colophon/ 78 | [vscode]: https://code.visualstudio.com/ 79 | [hyper]: https://hyper.is/ 80 | [media-temple]: https://mediatemple.net 81 | [remark]: https://www.npmjs.com/package/remark 82 | [gatsby-plugin-catch-links]: https://www.npmjs.com/package/gatsby-plugin-catch-links 83 | [gatsby-plugin-styled-components]: https://www.npmjs.com/package/gatsby-plugin-styled-components 84 | [gatsby-source-filesystem]: https://www.npmjs.com/package/gatsby-source-filesystem 85 | [gatsby-transformer-remark]: https://www.npmjs.com/package/gatsby-transformer-remark 86 | [gatsby-remark-copy-linked-files]: https://www.npmjs.com/package/gatsby-remark-copy-linked-files 87 | [gatsby-remark-prismjs]: https://www.npmjs.com/package/gatsby-remark-prismjs 88 | [gatsby-remark-smartypants]: https://www.npmjs.com/package/gatsby-remark-smartypants 89 | [gatsby-plugin-react-helmet]: https://www.npmjs.com/package/gatsby-plugin-react-helmet 90 | [gatsby-plugin-offline]: https://www.npmjs.com/package/gatsby-plugin-offline 91 | [styled-components]: https://www.styled-components.com/ 92 | [google-fonts]: https://fonts.google.com/ 93 | [webfontloader]: https://github.com/typekit/webfontloader 94 | -------------------------------------------------------------------------------- /content/blog/2023-08-18-the-ai-gap/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2023-08-18 3 | title: "The AI Gap" 4 | author: Dustin Schau 5 | draft: true 6 | featured: images/ai.png 7 | excerpt: "The rise of AI has revealed a gap. It's so close to fully replacing (read: augmenting) entire fields and professions, but there is friction, challenges, issues. Will those gaps exist forever?" 8 | tags: 9 | - ai 10 | --- 11 | 12 | There's a thelogical perspective called "God of the gaps," (see: [Wikipedia][wikipedia-god-of-the-gaps]) in which God is a placeholder for gaps in explanation, awareness, or lack of scientific knowledge. As scientific knowledge grows and more previously unexplainable phenomonon are explained, the _gap_ of the shrinking power of God narrows. As an example, in ancient times weather was not understood. Thus, ancient civilizations believed that clearly, God must control the weather, and so we must pray to him/them/etc. 13 | 14 | The field collectively known as Artificial Intelligence (hereafter I'll use AI, even though the whole term is really a misnomer, but I digress) reminds me of this concept. Whole industries may _shrink_ with the advent of AI, but it's unclear how much this gap will narrow, whether it will someday narrow to zero, or whether like the God of the Gaps, if there is still a sufficient gap in the middle for the human experience and entire industries to exist _alongside_ AI. 15 | 16 | As I quite like using concrete examples as demonstrations, I'll use my recent experience in writing a children's novel for my son, Noah, to weave through where this gap exists in various industries and the current friction that exists in AI. 17 | 18 | ## The project 19 | 20 | After seeing the below tweet from [Chase Lean](https://twitter.com/chaseleantj) (follow him, he's excellent and educational!) 21 | 22 |

How to make pictures for children's coloring books with Midjourney

Use this prompt:

kid's coloring book, [OBJECT], cartoon, thick lines, black and white, white background

You can even control the maturity level of the drawing, from simple to complex.

Steps below ↓ pic.twitter.com/XTTYzJvY98

— Chase Lean (@chaseleantj) August 2, 2023
23 | 24 | ## The gap, today 25 | 26 | So, let's break down this gap. This gap: human industries, but I'll focus on industries that I know best, specifically Product, Engineering, and Design. I'll start with an oft-repeated phrase that I _generally_ believe to be true at this point: 27 | 28 | > AI won't replace your job, but someone _using_ AI will. 29 | 30 | Loosely phrased, the gap is whether an industry still _needs_ to exist at all. Currently: yes, very much so! While the usage of AI has begun to shape and transform industries, whole professions have seemingly not disappaered overnight, however professionals in these industries have begun to use these tools to become more efficient and effective in their day-to-day. I'll give a few examples. 31 | 32 | ### Engineering 33 | 34 | Tools like GitHub Copilot and ChatGPT have exploded in usage as engineers have recognized that a lot of what they do day-to-day are somewhat mundane tasks that can be learned and automated. Of course, knowing _how_ to prompt an AI has created a whole field of engineering called "Prompt Engineering," in which engineers prompt the AI to craft a solution with deepening understanding of the problem. 35 | 36 | ![ChatGPT, Prompting for GitHub's API](./images/ai-prompting.png) 37 | 38 | Right now, the field of Engineering's gap is that the AI needs prompting. Human understanding of higher-order concepts, of how systems of knowledge and processes work together, and so forth still needs to exist with the current states of AI. There's friction, and a lack of ability of the current tooling to gain sufficient domain knowledge and understanding to replace the field of Engineering. 39 | 40 | Will that be true forever? Are there areas of engineering that perhaps are less "safe" than others? 41 | 42 | ### Product 43 | 44 | I'll use Product here loosely to mean: idea generation, strategy, and writing. If Engineering is a bit more science than art, Product is a bit more art than science and so AI is a tool used to augment and inspire creativity to help this industry be more effective and efficient. To use a metaphor from a friend, if we think of software is a canvas, Product oftentimes fills in the blanks and anything that remains uncovered. This could be: talking to customers to develop conviction in the problem(s), analyzing data to understand friction or themes to explore further, or simply writing documents to help everyone align around what we're doing and why we're doing it. 45 | 46 | I believe the most transformative tool that we've seen for AI augmenting Product is ChatGPT. If we use Product even more loosely, then other tools like logo generation, specific tools for copywriting or ideating on strategy, and so forth have also begun to emerge but ChatGPT seems to be the most generally useful AI tool today that has the ability to narrow the gap for Product. 47 | 48 | ### Design 49 | 50 | ## Where we could be going 51 | 52 | ## What's next? 53 | 54 | [wikipedia-god-of-the-gaps]: https://en.wikipedia.org/wiki/God_of_the_gaps 55 | -------------------------------------------------------------------------------- /content/blog/2017-07-21-writing-an-open-source-library/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2017-07-21T20:44:35.199Z 3 | title: Writing an Open Source JavaScript Library 4 | tags: 5 | - open source 6 | - javascript 7 | - ci 8 | - travis 9 | - jest 10 | - unit testing 11 | featured: preview.png 12 | draft: true 13 | --- 14 | 15 | It can be incredibly difficult to keep up with the seemingly nebulous and always changing JavaScript ecosystem. This struggle, and oftentimes misunderstanding of the value/purpose of tools, has led to what many self-diagnose as "JavaScript fatigue." _However_, I **strongly** disagree with this assertion. Incredible tooling, incredible utilities, and incredible libraries coalesce to form what I believe to be the strongest foundation JavaScript has had in years. In this post, I plan to outline the origin story and creation of an open source (NodeJS) utility, and in doing so, touch on a plethora of these incredible tools, utilities, and libraries that collectively make up the foundation of what some have called the **JavaScript Renaissance.** 16 | 17 | > JavaScript fatigue is what happens when people use tools they don't need to solve problems they don't have. 18 | > 19 | > -- Lucas F. Costa 20 | 21 | ## The 💡 Moment 22 | 23 | While working on a Gatsby PR (see [this blog post][getting-started-with-gatsby] for more about Gatsby), I gained some exposure to the [Remark library][remark] library, which has the ability to transform a Markdown document into an abstract syntax tree--hereafter referred to as an AST. The general approach is given a Markdown file, we can parse it into an AST of nodes (e.g. code nodes, image nodes, text nodes, etc.), modify these nodes, and then write back to the original Markdown file. Pretty cool! I tend to think looking at code is helpful, so let's consider the following snippet: 24 | 25 | ```javascript 26 | const Remark = require("remark"); 27 | 28 | const ast = remark().parse(` 29 | # hello world 30 | 31 | - I'm a list 32 | - Me too 33 | 34 | 1. Numbered 35 | 1. Numbered Two 36 | `); 37 | ``` 38 | 39 | I then realized that [prettier][prettier], a code formatter based on the width of a line, can prettify JavaScript code as a string. Prettier's approach is actually fairly similar to Remark's approach. It parses your JavaScript code as an AST and then re-prints this AST with line-width and other stylistic concerns in mind. 40 | 41 | With Remark, we can get _each_ and _every_ code block as a string. With Prettier, take code blocks (as string), and enforce a consistent, formatted style. Sounds like there's some overlap and we can use these tools together? Possibly make this utility sharable, and usable via either a **C**omand **L**ine **I**nterface (hereafter CLI) _and/or_ possibly usable dynamic (e.g. in another Node module). Sounds like a JavaScript library, right? 42 | 43 | ## 🔧 Project Setup 44 | 45 | This can often be a point of contention, or cause of stress, for many developers. The plethora of choices, tools, and utilities that can be used can sometimes lead to an overwhelming feeling that one is making the wrong choice, or perhaps not the _most_ correct choice. Do I use Webpack? Do I use Babel? Which preset do I use? Which testing framework? And so it goes… Each of these choices is important, but I'd like to stress the importance of ignoring some of this selection anxiety, and just get down to developing. Choose what **you** feel most comfortable with, not what is the "new hotness" or the tool that has a lot of hype behind it--in other words, **don't** be consumed by [hype driven development][hdd]. Choose what makes you feel most empowered to develop something usable, well-tested, and that keeps you productive. Note that I'm not saying you shouldn't learn some new tool, or investigate some new utility, but I am merely saying you don't _have_ to do so and if you are feeling selection anxiety, then use what you are most comfortable using! 46 | 47 | An additional note here: I'd urge you to consider **not** using any type of boilerplate until you're comfortable with what the boilerplate provides. I've found that many developers tend to just pull down boilerplates not really understanding what's going on behind the scenes. In fact, I think it is this lack of understanding and confusion with boilerplates that leads to much of the foundation for what many cal JavaScript fatigue. This inevitably leads to confusion, particularly when something (oftentimes!) goes wrong and something must be fixed. This confusion causes a vehement dislike of the stack, and oftentimes a slamming of JavaScript in the process. The problem isn't JavaScript, it's the plethora of choices we have available to us. There's no guarantee that every utility provided in a boilerplate is useful for your use case, and oftentimes they provide too much! That said… if you like them, by all means continue to utilize them! 48 | 49 | With all of this in mind… here's my preferred stack and you should use the same. 50 | 51 | ![Troll face](images/troll-face.jpeg) 52 | 53 | Entirely kidding! However, I do think there is implicit value in discussing how _someone_ (e.g. me) builds something. This is particularly true if it may encourage discussion or improve your existing stack in some meaningful way. There's no guarantee that you, the reader, may find my particular stack encouraging at _this_ time, but learning about it now could pay dividends in the future. With that said, let's get down to it! 54 | 55 | ### TypeScript 56 | 57 | I'm a big fan of TypeScript, as are other companies like [slack][typescript-slack], [reddit][typescript-reddit], and of course, [Microsoft][typescript-microsoft], among many others! The static typing analysis makes me feel confident that my code is as bug-free as possible, and I truly enjoy writing TypeScript code now that the ecosystem has seen some maturation, particularly with the scoped package `@types`, which contains many type declarations files for most of the packages I tend to use. Additionally, I think the `tsc` compiler is first-class, and I've found it particularly great for Node development. Let me explain why as I walk through some basic project setup for TypeScript. 58 | 59 | #### `tsconfig.json` 60 | 61 | The first step when starting with any TypeScript project is to create a TypeScript configuration file, similarly to `webpack.config.js`, `.babelrc`, etc. TypeScript uses a `json` file in the project root called `tsconfig.json`. 62 | 63 | ```json 64 | { 65 | "compilerOptions": { 66 | "module": "commonjs", 67 | "moduleResolution": "node", 68 | "target": "es2017", 69 | "rootDir": "src", 70 | "outDir": "dist" 71 | }, 72 | "exclude": ["__mocks__", "src/__tests__", "src/interfaces", "node_modules"] 73 | } 74 | ``` 75 | 76 | [getting-started-with-gatsby]: /blog/getting-started-with-gatsby 77 | [remark]: https://github.com/gnab/remark 78 | [prettier]: https://github.com/prettier/prettier 79 | [hdd]: https://blog.daftcode.pl/hype-driven-development-3469fc2e9b22 80 | [typescript-reddit]: https://redditblog.com/2017/06/30/why-we-chose-typescript/ 81 | [typescript-slack]: https://slack.engineering/typescript-at-slack-a81307fa288d 82 | [typescript-microsoft]: https://medium.com/@delveeng/why-we-love-typescript-bec2df88d6c2 83 | -------------------------------------------------------------------------------- /content/blog/2019-01-04-seo-and-gatsby/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2019-01-04 3 | title: "Search Engine Optimization with Gatsby" 4 | author: Dustin Schau 5 | featured: images/seo.jpg 6 | excerpt: "SEO and Gatsby: A Perfect Pairing. Learn how Gatsby implements SEO utilizing React Helmet and smart defaults and how you can use these tools to implement your own!" 7 | tags: 8 | - gatsby 9 | - javascript 10 | - react 11 | - seo 12 | --- 13 | 14 | Search Engine Optimization (hereafter SEO) is something that you should want. You've possibly even been approached by an SEO _expert_ who can maximize your revenue and page views just by following these **Three Simple Tricks**! However, relatively few make the concerted effort to implement SEO in their web app. In this post, I'll share some of the ins and outs of SEO and how you can implement common, simple SEO patterns in your Gatsby web app, today. By the end of this post you'll know how to do the following: 15 | 16 | - Implement SEO patterns with [react-helmet][react-helmet] 17 | - Create an optimized social sharing card for Twitter, Facebook, and Slack 18 | - Tweak the SEO component exposed in the default gatsby starter ([`gatsby-starter-default`][gatsby-starter-default]) 19 | 20 | ## Implementation 21 | 22 | The core technology powering SEO is the humble, ubiquitiuous `meta` tag. You've probably seen something like: 23 | 24 | ```html 25 | 29 | ``` 30 | 31 | or further still with more of an SEO spin something as simple as the `description` and/or `keywords` properties: 32 | 33 | ```html 34 | 38 | 42 | ``` 43 | 44 | These are the _bare minimum_ requirements that should be implemented for simple and basic SEO. However--we can go further, and we can go further with the powerful combo of content rendered at _build time_ powered by Gatsby and GraphQL. Let's dive in. 45 | 46 | ## Gatsby + GraphQL 47 | 48 | GraphQL is a crucial feature enabled via Gatsby (note: you don't [_have_ to use GraphQL with Gatsby][unstructured-data]). Leveraging GraphQL to query your indexable content--wherever it lives (at build time!)--is one of the most powerful and flexible techniques enabled via Gatsby. Let's briefly look at how we can implement an extensible and flexible SEO component. 49 | 50 | ### `StaticQuery` 51 | 52 | Gatsby distinguishes between page-level queries and component queries. The former can use page GraphQL queries while the latter can use a new in Gatsby v2 feature called [`StaticQuery`][gatsby-static-query]. A StaticQuery will be parsed, evaluated, and injected at _build time_ into the component that is requesting the data. This is a perfect scenario in which we can create an SEO component with sane defaults that can be easily extended. 53 | 54 | ### Creating the component 55 | 56 | Using the power and flexibility of React, we can create a React component to power this functionality. 57 | 58 | > Note: `react-helmet` is enabled, by default, in gatsby-starter-default and gatsby-starter-blog 59 | > 60 | > If you're not using those: [follow this guide for installation instructions][gatsby-plugin-react-helmet] 61 | 62 | ```jsx:title=src/components/seo.js 63 | import React from "react"; 64 | // highlight-start 65 | import Helmet from "react-helmet"; 66 | import { StaticQuery, graphql } from "gatsby"; 67 | // highlight-end 68 | 69 | function SEO() { 70 | return ( 71 | null} 86 | /> 87 | ); 88 | } 89 | 90 | export default SEO; 91 | ``` 92 | 93 | This component doesn't _do_ anything yet, but we're laying the foundation for a useful, extensible component. What we've done up to this point is leverage the `StaticQuery` functionality enabled via Gatsby to query our siteMetadata (e.g. details in `gatsby-config.js`) so that we can grab description and keywords. 94 | 95 | The `StaticQuery` component accepts a render prop, and at this point, we're simply returning `null` to render nothing. Let's _actually_ render something and build out our prototype for this SEO component. Let's iterate further. 96 | 97 | ```jsx:title=src/components/seo.js 98 | import React from "react"; 99 | import Helmet from "react-helmet"; 100 | import { StaticQuery, graphql } from "gatsby"; 101 | 102 | function SEO() { 103 | return ( 104 | ( 117 | 132 | )} 133 | /> 134 | ); 135 | } 136 | 137 | export default SEO; 138 | ``` 139 | 140 | whew, getting closer! This will now render the `meta` `description` tag, and will do so using content injected at build-time with the `StaticQuery` component. Additionally, it will add the `lang="en"` attribute to our root-level `html` tag to silence that pesky Lighthouse warning 😉 141 | 142 | If you remember earlier, I claimed this was the bare bones, rudimentary approach to SEO, and that still holds true. Let's enhance this functionality this and get some useful functionality for sharing a page via social networks like Facebook, Twitter, and Slack. 143 | 144 | ### Implementing social SEO 145 | 146 | In addition to SEO for actual _search_ engines we also want those pretty cards that social networks like Twitter and Slack enable. Specifically, we'd like to implement the following: 147 | 148 | - Description for embedded results 149 | - Title for embedded results 150 | - (Optionally) display an image and a card if an image is passed in to the component 151 | 152 | Let's implement it 👌 153 | 154 | ```jsx:title=src/components/seo.js 155 | import React from "react"; 156 | import Helmet from "react-helmet"; 157 | import PropTypes from "prop-types"; // highlight-line 158 | import { StaticQuery, graphql } from "gatsby"; 159 | 160 | // highlight-next-line 161 | function SEO({ description, meta, image: metaImage, title }) { 162 | return ( 163 | { 177 | // highlight-start 178 | const metaDescription = 179 | description || data.site.siteMetadata.description; 180 | const image = 181 | metaImage && metaImage.src 182 | ? `${data.site.siteMetadata.siteUrl}${metaImage.src}` 183 | : null; 184 | // highlight-end 185 | return ( 186 | 254 | ); 255 | }} 256 | /> 257 | ); 258 | } 259 | 260 | // highlight-start 261 | SEO.defaultProps = { 262 | meta: [] 263 | }; 264 | // highlight-end 265 | 266 | // highlight-start 267 | SEO.propTypes = { 268 | description: PropTypes.string, 269 | image: PropTypes.shape({ 270 | src: PropTypes.string.isRequired(), 271 | height: PropTypes.string.isRequired(), 272 | width: PropTypes.string.isRequired() 273 | }), 274 | meta: PropTypes.array, 275 | title: PropTypes.string.isRequired 276 | }; 277 | // highlight-end 278 | 279 | export default SEO; 280 | ``` 281 | 282 | Woo hoo! What we've done up to this point is enabled not only SEO for search engines like Google, Bing (people use Bing, right?) but we've also laid the groundwork for enhanced sharing capabilities on social networks. That's a win-win if I've ever seen one 😍 283 | 284 | To bring it all home, let's consider actually _using_ this extensible SEO component. 285 | 286 | ## Using the SEO component 287 | 288 | We now have our extensible SEO component. It takes a `title` prop, and then (optionally) `description`, `meta`, and `image` props. Let's wire it all up! 289 | 290 | ### In a page component 291 | 292 | ```jsx:title=src/pages/index.js 293 | import React from "react"; 294 | 295 | import Layout from "../components/layout"; 296 | import SEO from "../components/seo"; // highlight-line 297 | 298 | function Index() { 299 | return ( 300 | 301 | {/* highlight-line */} 302 |

lol - pretend this is meaningful content

303 |
304 | ); 305 | } 306 | 307 | export default Index; 308 | ``` 309 | 310 | ### In a template 311 | 312 | Let's pretend we have a Markdown powered blog (see: [this tutorial][gatsby-markdown-blog] for more info). We--of course--want some nice SEO as well as a nifty image for sharing on Twitter, Facebook, and Slack. We're going to do this with a few steps, specifically: 313 | 314 | - Create a Markdown post 315 | - Add an image, and add it to the Markdown posts frontmatter 316 | - Query this image with GraphQL 317 | 318 | #### Creating the post 319 | 320 | ```shell 321 | mkdir -p content/blog/2019-01-04-hello-world-seo 322 | touch content/blog/2019-01-04-hello-world-seo/index.md 323 | ``` 324 | 325 | ```md:title=content/blog/2019-01-04-hello-world-seo/index.md 326 | --- 327 | date: 2019-01-04 328 | featured: images/featured.jpg 329 | --- 330 | 331 | Hello World! 332 | ``` 333 | 334 | #### Adding the image 335 | 336 | Feel free to add whatever, or perhaps use this _very pertinent_ image: 337 | 338 | ![Sample Image](./images/seo.jpg) 339 | 340 | the image will need to be located at `content/blog/2019-01-04-hello-world-seo/images/featured.jpg` 341 | 342 | #### Querying with GraphQL 343 | 344 | ```jsx:title=src/templates/blog-post.js 345 | import React from 'react' 346 | import { graphql } from 'gatsby' 347 | 348 | import Layout from '../components/layout' 349 | import SEO from '../components/seo' // highlight-line 350 | 351 | // highlight-start 352 | function BlogPost({ data }) { 353 | const { markdown: { excerpt, html, frontmatter } } = data 354 | const image = frontmatter.image ? frontmatter.image.childImageSharp.resize : null 355 | // highlight-end 356 | return ( 357 | 358 | {/* highlight-next-line */} 359 | 360 |

{frontmatter.title}

361 |
362 | 363 | ) 364 | } 365 | 366 | export const blogPostQuery = graphql` 367 | # highlight-start 368 | query BlogPostBySlug($slug: String!) { 369 | markdown: markdownRemark(fields: { $slug: { eq: $slug }}) { 370 | html 371 | excerpt(pruneLength: 200) 372 | frontmatter { 373 | image: featured { 374 | childImageSharp { 375 | resize(width: 1200) { 376 | src 377 | height 378 | width 379 | } 380 | } 381 | } 382 | title 383 | } 384 | } 385 | # highlight-end 386 | } 387 | ` 388 | 389 | export default BlogPost 390 | ``` 391 | 392 | ## The Payoff 393 | 394 | Utilizing the techniques outlined in this post, we've made our Gatsby application SEO-friendly as well as sharable on common social networks. Don't just take _my_ word for it, though--check out the following examples of a sample blog post. 395 | 396 | ### Google 397 | 398 | ![Google](./images/google.png) 399 | 400 | ### Facebook 401 | 402 | ![Facebook](./images/facebook.png) 403 | 404 | ### Twitter 405 | 406 | ![Twitter](./images/twitter.png) 407 | 408 | ### Slack 409 | 410 | ![Slack](./images/slack.png) 411 | 412 | These SEO resources outlined in this post aren't _only_ a best practice, they're also a best practice enabled, by default. Available **today** in `gatsby-starter-default`, simply use: 413 | 414 | ```shell 415 | npx gatsby new my-new-gatsby-app 416 | ``` 417 | 418 | and you'll have the `SEO` component available to maximize your SEO and social sharing capabilities. Check it out! 419 | 420 | ## Further Learning 421 | 422 | This article is merely a shallow dive into the depths of SEO optimization--consider it a primer for further learning. To learn more, check out the following resources: 423 | 424 | - Facebook uses the [Open Graph][og] tag format 425 | - Twitter uses `twitter:` keywords. See [Twitter Cards][twitter-cards] for more info 426 | - Slack reads tags in the following order ([source][slack-unfurl]) 427 | 1. oEmbed server 428 | 1. Twitter cards tags / Facebook Open Graph tags 429 | 1. HTML meta tags 430 | 431 | Perhaps even more importantly, check out how to _validate_ SEO with the following tools from [Google][google-validation], [Twitter][twitter-validation], and [Facebook][facebook-validation]. 432 | 433 | Finally, check out the [`gatsby-seo-example`][gatsby-seo-example] for a ready-to-use starter for powering your Markdown-based blog. 434 | 435 | Thanks for reading--I cannot wait to see what you build next. 💪 436 | 437 | [gatsby-starter-default]: https://github.com/gatsbyjs/gatsby-starter-default 438 | [gatsby-static-query]: https://www.gatsbyjs.org/docs/static-query/ 439 | [gatsby-markdown-blog]: https://www.gatsbyjs.org/docs/adding-markdown-pages/ 440 | [gatsby-plugin-react-helmet]: https://www.gatsbyjs.org/packages/gatsby-plugin-react-helmet/ 441 | [react-helmet]: https://github.com/nfl/react-helmet 442 | [unstructured-data]: https://www.gatsbyjs.org/docs/using-unstructured-data/ 443 | [og]: https://developers.facebook.com/docs/sharing/webmasters/#markup 444 | [twitter-cards]: https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards.html 445 | [slack-unfurl]: https://medium.com/slack-developer-blog/everything-you-ever-wanted-to-know-about-unfurling-but-were-afraid-to-ask-or-how-to-make-your-e64b4bb9254 446 | [google-validation]: https://support.google.com/webmasters/answer/6066468?hl=en 447 | [twitter-validation]: https://cards-dev.twitter.com/validator 448 | [facebook-validation]: https://developers.facebook.com/tools/debug/sharing 449 | [gatsby-seo-example]: https://github.com/DSchau/gatsby-seo-example 450 | -------------------------------------------------------------------------------- /content/blog/2018-06-15-graphql-most-of-the-parts/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2018-06-10T17:15:34.619Z 3 | title: "GraphQL: Most of the Parts" 4 | tags: 5 | - graphql 6 | - react 7 | - node 8 | excerpt: In this post, I'll do a deep dive on most of the parts of GraphQL. I'll start with the foundational concepts and then from this foundational basis I'll construct the value of GraphQL and illustrate how it could be a hugely transformative technology for server and client communication. 9 | --- 10 | 11 | Hello! My name is Dustin Schau and I hope to share some knowledge with you about... you guessed it, GraphQL! 12 | 13 | I intend for this to be a gentle introduction to foundational concepts of GraphQL. In illustrating these concepts, we gain a greater understanding of what makes GraphQL such a transformative technology, and a greater appreciation for the value it can provide for an application. I go into some detail of the problems that GraphQL is trying to solve and how it solves them. 14 | 15 | I'll end with a section on integration into an existing backend. This is primarily focused on an existing RESTful backend, but can be substituted to any data storage mechanism, e.g. MySQL, Mongo, etc. I'll have a number of code examples and repos at the end so you can dive further into some real code powered by both server and client-side GraphQL technologies. Let's do it! 16 | 17 | ![0](./images/01-0.png) 18 | 19 | I'm a frontend developer who likes to claim that I specialize in all things JavaScript. The last few months, the client work I've been doing has had a NodeJS focus, so that ties in particularly well for a deep dive into GraphQL. 20 | 21 | I work for an awesome company called Object Partners. We have offices in Minneapolis and Omaha, and about 100 senior developers between both offices. 22 | 23 | ![1](./images/02-1.png) 24 | 25 | Lately, I think there's been a tendency to follow what is essentially Facebook Driven Development. With React, GraphQL, Jest, and other Facebook open source initiatives eating the world, it sometimes feels that if you're _not_ using this new hotness you're falling behind. With this perception comes a perhaps deserved backlash and mistrust of some of these technologies. 26 | 27 | > _I_ don't need React; jQuery|Vue|Insert framework here works fine for me thank you very much 28 | 29 | > Jest? Nah, Mocha and Karma are all I'll ever need. 30 | 31 | I'd like you to resist succumbing to this mindset, and rather approach GraphQL with an eager and open mind. Whether React is in your wheel house or company's stack or not, I still strongly feel that GraphQL is a transformative technology for data querying and how we communicate between client and server, so try to resist those notions to reject GraphQL simply _just_ because it's new, hot, and from Facebook. 32 | 33 | ![2](./images/03-2.png) 34 | 35 | Many have called GraphQL a REST killer because the functionality it offers seems to be a game-changer for how we consider backend development and the relationship between client and server. What can we make of this? Is GraphQL actually a REST killer? 36 | 37 | ![3](./images/04-3.png) 38 | 39 | **No.** I do not personally believe GraphQL to be the REST killer as some have claimed. 40 | 41 | It seems slightly contradictory for a technology that some have purported to _kill_ REST to actually make REST better, and that is one of the key points I want you to take home. Implementing GraphQL today will make your REST backend more easily queryable, better documented, and can even improve performance client-side by reducing round-robin requests among many other benfits. 42 | 43 | ![4](./images/05-4.png) 44 | 45 | In effect, I am absolutely not claiming that GraphQL kills REST. It is, in fact, intended to be a gentle introduction to GraphQL and how to begin implementing GraphQL in your RESTful backend, today. I believe that implementing GraphQL will lead to a number of tangible benefits and overall will improve your backend service communication between client and server. 46 | 47 | ![5](./images/06-5.png) 48 | 49 | Before we begin the section on integration, it is, of course, helpful to first take a step back and describe GraphQL at a foundational level. I will construct the base, disparate pieces that make up GraphQL and how they contribute to the larger whole of the value and benefit of GraphQL. 50 | 51 | ![6](./images/07-6.png) 52 | 53 | GraphQL is perhaps at its most interesting and valuable, a query language. Using a JSON like structure--which we'll see in more detail in a bit--we can pluck only the fields we need for our UI. Doing so results in a more performant and cleaner interface between client and server, and it is this query language that is one of the largest benefits as I see it with GraphQL. 54 | 55 | ![7](./images/08-7.png) 56 | 57 | To begin describing this query language, first consider this `User` inteface. Pretend we have a RESTful backend that operates on this User resource, and this RESTful backend has a number of CRUD operations that operate on this resource. 58 | 59 | ![8](./images/09-8.png) 60 | 61 | With GraphQL we can request a _subset_ (or every field!) using this query language. This query language directly maps to our underlying data interface/contract, and so we can pull _only_ what we need and no more. If our requirements for our UI change at some point in the future, we can simply request either less or more data depending on our needs. 62 | 63 | ![9](./images/10-9.png) 64 | 65 | Let's say down the road we _only_ need to display a user's name, and we'd like to alias that property in our query to `username`. Incredibly simple with GraphQL, and we didn't have to make a single backend change to accomodate this functionality. 66 | 67 | ![10](./images/11-10.png) 68 | 69 | It's clear that one of the strongest benefits of GraphQL is, in fact, this query language. The structure of the data is described in the query itself, and the resulting data set matches this requested structure. 70 | 71 | However... you may be jumping ahead of me here. What we've described can be _easily_ implemented with REST, utilizing query parameters which will conditionally filter and return only what is requested. There are tools to make this easier, such as [Apache Solr][solr]. 72 | 73 | [solr]: http://lucene.apache.org/solr/ 74 | 75 | ![11](./images/12-11.png) 76 | 77 | I would agree with you that if this simple example encapsulated the depth of the value of GraphQL queries that the benefit may not be there for you. The REST example with query parameters is really _not that bad_ and I'd be comfortable adopting that in my client-side application. 78 | 79 | ![12](./images/13-12.png) 80 | 81 | But wait... as you may have guessed it, we've only scratched the surface of what is possible with GraphQL. Now let's consider a more complex example which is not as easily achieved with a traditional RESTful backend. 82 | 83 | ![13](./images/14-13.png) 84 | 85 | The beauty of GraphQL queries is that they accomodate deeply nested data just as simply as if we were plucking data from a top-level resource. If you only want _some_ properties of a deeply nested resource, it couldn't be simpler to pluck only what you need for the UI and no more, thereby sending less data from the server and rendering only what you need in the UI. 86 | 87 | ![14](./images/15-14.png) 88 | 89 | How would this be done in REST? I'm _sure_ there are solutions and libraries to achieve this--and please let me know if you know of any particularly good ones--but utilizing a tool that makes it simple and has a defined, easily understood query language makes this a strong selling point of adopting GraphQL. 90 | 91 | ![15](./images/16-15.png) 92 | 93 | Up to this point, the query language is the R in CRUD. How is the CUD handled with GraphQL? You better believe there's a solution for that too! 94 | 95 | ![16](./images/17-16.png) 96 | 97 | The GraphQL solution to the CUD is via a concept called mutations. Mutations allow you to update a resource (be it create, update, or delete) and optionally use that same query language to pluck queried data from the created/updated/deleted resource. 98 | 99 | ![17](./images/18-17.png) 100 | 101 | Here's a sample mutation that is creating a review. A review takes some input, which is an episode and then a review, each of which is typed at the GraphQL server level, and validation on this input will happen "for free" with the GraphQL type system. 102 | 103 | When run, this mutation will create a review and we will grab the stars and commentary so we can display it in the UI. Incredibly easy and intuitive! 104 | 105 | ![18](./images/19-18.png) 106 | 107 | That type system we just used for a mutation? It's also a foundational concept in GraphQL. By leveraging this strong type system, our backend enables excellent documentation, validation, and even autocomplete/intellisense quite easily. Let's dive in to this type system. 108 | 109 | ![19](./images/20-19.png) 110 | 111 | Remember that earlier interface for a user? Here's how that same user is represented with GraphQL's type system. Let me make note of a few concepts that may need clarification: 112 | 113 | 1. The `!` means that a field is non-nullable. In other words, a User will always contain a field of id and it will be type ID 114 | 2. The `ID` type is a special type in GraphQL, and using it enables some nice functionality like improved caching, unique resource recognition, etc. 115 | 116 | Note: I am using the library [graphql-tools][graphql-tools] from [Apollo](https://www.apollographql.com/) to leverage this string type system. You can also use the reference implementation [graphqljs][graphqljs], but it tends to be a bit more verbose. 117 | 118 | [graphql-tools]: https://github.com/apollographql/graphql-tools 119 | [graphqljs]: https://github.com/graphql/graphql-js 120 | 121 | ![20](./images/21-20.png) 122 | 123 | A schema essentially describes our entire data model. A schema is composed of queries and mutations which augment and/or return resources which are mapped to resource types (like the above user). 124 | 125 | As the schema is strongly typed, as mentioned we can get some great functionality very easily like excellent documentation, validation, etc. We'll go into more depth on this in a bit. 126 | 127 | ![21](./images/22-21.png) 128 | 129 | An incredibly simple schema is shown here. We have our familiar `User` type, and now we've introduced a Query. Our `users` query accepts a non-nullable limit argument and returns an Array of non-nullable User resources. 130 | 131 | In just several lines of code, we've created a strongly typed representation of our data model that can be queried against and used by a client. Once-more, this is utilizing the library [graphql-tools][graphql-tools] from [Apollo](https://www.apollographql.com/). 132 | 133 | [graphql-tools]: https://github.com/apollographql/graphql-tools 134 | 135 | ![22](./images/23-22.png) 136 | 137 | GraphQL's query language is powered by a core technique known as resolvers. _Every_ field you request can have custom resolvers, and even deeply nested requests can be easily and cleanly resolved with this technique. 138 | 139 | Resolvers are the foundational technique that enable the heart of GraphQL's functionality. Resolvers allow you to specify how query fields are resolved--as you'd expect! This means that whatever mechanism you use to store data (i.e. MySQL, RESTful backend, MongoDB, etc.) can be used to request resources from that data store and return it to the client, on demand. If a field isn't requested in a query, the field is never resolved and an additional request is not made! 140 | 141 | Additionally, resolvers can be defined for _any_ field, or even to add additional functionality to a resource (e.g. a computed property on User which adds fullName). 142 | 143 | ![23](./images/24-23.png) 144 | 145 | If we consider our sample RESTful backend again, we can now implement this data fetching cleanly and simply with resolvers. When we query for resources, we specify how to resolve these resources by hitting out RESTful backend and returning the necessary data. GraphQL will handle only sending the payload requested to the user as long as we return the subset of non-nullable fields and typed fields appropriately. Excellent! 146 | 147 | ![24](./images/25-24.png) 148 | 149 | Let's go into a bit more depth on resolvers. 150 | 151 | Each resolver is a function that can return sync or async a value corresponding to the non-nullable fields specified for that resource. 152 | 153 | Additionally, each resolver function is injected with three arguments: 154 | 155 | ## root 156 | 157 | The root is effectively the "parent" of the current resolved field. For instance, when we resolve a user's manager, root refers to the already resolved user. This makes it easy to use resolved fields (i.e. a user's id) to make a second request to get additional resolved data. 158 | 159 | ## args 160 | 161 | args is simply an object representing our passed arguments/options to the resource type. For instance, if we pass a limit to the users query, it will be expressed as: 162 | 163 | ```json 164 | { 165 | "limit": 10 166 | } 167 | ``` 168 | 169 | and can be easily accessed with this args argument. 170 | 171 | ## context 172 | 173 | Finally, context is how shared data, e.g. authentication, shared database connection, etc. can be made available to _any_ resolver cleanly. 174 | 175 | ![resolvers in depth](./images/26-resolvers-in-depth.png) 176 | 177 | Let's wire this all up and show how to create a schema, once again utilizing [graphql-tools][graphql-tools] 178 | 179 | [graphql-tools]: https://github.com/apollographql/graphql-tools 180 | 181 | ![26](./images/27-26.png) 182 | 183 | First, we import `makeExecutableSchema` which will wire up a schema given typeDefs (our schema and type definitions), and resolvers, which resolve data appropriately. 184 | 185 | This schema is then typically passed to whatever type of server you're working with. There exists a number of options, e.g. 186 | 187 | - [express-graphql][graphql-express-middleware] 188 | - [koa-graphql][koa-graphql] 189 | - [apollo-server][apollo-server] 190 | 191 | [graphql-express-middleware]: https://github.com/graphql/express-graphql 192 | [koa-graphql]: https://github.com/chentsulin/koa-graphql 193 | [apollo-server]: https://github.com/apollographql/apollo-server 194 | 195 | ![27](./images/28-27.png) 196 | 197 | How incredible is this? In approximately 100 or so lines of code, we've created a strongly-typed GraphQL layer to our existing RESTful backend and wired it all up. Could not have been easier! 198 | 199 | ![28](./images/29-28.png) 200 | 201 | GraphQL is backend agnostic. As a well-documented technology, it contains a number of reference implementations in effectively whatever your backend language/framework of choice is, although I will mention that NodeJS probably has the most active ecosystem currently. 202 | 203 | ![29](./images/30-29.png) 204 | 205 | If your team is a Groovy shop, a .Net shop, whatever, feel free to use what you know and love and there is probably a GraphQL reference implementation for your language of choice. 206 | 207 | Check out all the [implementations here](https://graphql.org/code/). 208 | 209 | ![30](./images/31-30.png) 210 | 211 | By going through the foundational concepts of GraphQL, some of the problems it is attempting to fix are made extremely apparent. That said, it never hurts to go into a bit more detail and be explicit about the high-level goals of GraphQL and how it attempts to solve some very real API problems many of us have run into over our careers. 212 | 213 | ![31](./images/32-31.png) 214 | 215 | [John Resig](https://twitter.com/jeresig?lang=en) mentions here a crucial benefit of GraphQL. If you've perhaps made a mistake, and your database layer may be fairly hard to query against or update resources, GraphQL can be used as a shim layer to abstract some of this complexity while introducing reasonable, understandable queries for your client/users. 216 | 217 | ![32](./images/33-32.png) 218 | 219 | That strong type system? It's leveraged to create excellent documentation. Queries expected arguments, argument types, return types, etc. can all be inspected utilizing the excellent tooling and ecosystem around GraphQL. 220 | 221 | ![33](./images/34-33.png) 222 | 223 | Of particular note is [GraphiQL](https://github.com/graphql/graphiql), which is distributed as a "middleware" and can be hosted along side your API to give a sort of IDE-like experience to your GraphQL API. 224 | 225 | Your entire schema can be inspected and drilled down into. You can even send real queries/mutations/etc. against the real database, and errors or any type mismatches will be displayed inline within the hosted GraphiQL application. 226 | 227 | Also worth mentioning is [GraphQLPlayground](https://github.com/prismagraphql/graphql-playground), which also offers similar functionality to GraphiQL. 228 | 229 | ![34](./images/35-34.png) 230 | 231 | Let's use a simple example: Twitter. I'm browsing Twitter the other day, scrolling through my feed, and I scroll, scroll, scroll some more, and then finally click on a provocative tweet. 232 | 233 | (For the purposes of this example, pretend Twitter's API works as I describe) 234 | 235 | ![35](./images/36-35.png) 236 | 237 | I click on a tweet, and clicking this tweet loads additional data and makes additional HTTP requests. 238 | 239 | ![36](./images/37-36.png) 240 | 241 | Scrolling down further makes additional HTTP requests. Likes, retweets, author avatar, etc. So in effect, we've introduced a number of REST calls where each interaction could potentially trigger one or more additional REST calls. 242 | 243 | ![37](./images/38-37.png) 244 | 245 | This simple interaction of scrolling through and clicking on a tweet could have theoretically created at least 3 API calls. One to request the timeline, one to request detail on a tweet in the timeline, and then finally the conversation for that tweet in the timeline. 246 | 247 | ![38](./images/39-38.png) 248 | 249 | We've effectively introduced waterfall requests in our UI. Structured cleanly, this complexity is maintainable, but it's certainly not an easy problem to solve. 250 | 251 | Why not use something we're now familiar with... resolvers, and hydrate our client with the minimal data payload they need, thereby reducing waterfall requests and requesting just the minimum subset of data we need for our client. 252 | 253 | ![39](./images/40-39.png) 254 | 255 | Let's abstract this a bit, and consider the same functionality but from a GraphQL context. 256 | 257 | We can use resolvers to request the first fifty tweets for a user's timeline. Additionally, we can reduce waterfall requests by hydrating each tweet in the timeline with the first couple of items in the conversation. 258 | 259 | We can do all of this while maintaining the ability to _easily_ augment what we need for particular views by requesting more or less data fields to build out _exactly_ what we need. The power of GraphQL in one slide. 260 | 261 | ![40](./images/41-40.png) 262 | 263 | Let's revisit the question I posited from the beginning. Is it a REST killer? 264 | 265 | ![41](./images/42-41.png) 266 | 267 | Again, I say no. It's a REST enhancer. Putting a GraphQL layer in front of your existing backend is one of the best things you can do to improve not only the client-side experience, but also the documentation and validation of your existing API with GraphQL's type system. 268 | 269 | However, I will mention that if you're experiencing some latency or otherwise slow connections, it may make sense at some point to rip out the REST layer and directly connect to the data store within GraphQL with resolvers, but I'd urge you here to not prematurely optimize. If you have a backend that works for you, I think introducing GraphQL into your stack is certainly an excellent choice that will have great benefits in the future. 270 | 271 | ![42](./images/43-42.png) 272 | 273 | If you were to integrate GraphQL into your stack today, I would have some simple recommendations. 274 | 275 | ![43](./images/44-43.png) 276 | 277 | Quite simply, start by introducing GraphQL as a layer in front of your existing API/backend. Keep your backend as is, but tie into the very tangible benefits of GraphQL using the resolvers approach I've shown earlier. 278 | 279 | ![44](./images/45-44.png) 280 | 281 | Additionally, by keeping your RESTful backend intact, you keep your business logic intact. No need to rip that out and re-write it within GraphQL resolvers! 282 | 283 | ![45](./images/46-45.png) 284 | 285 | Introducing GraphQL absolutely does not, and I'd argue _should not_, constitute an entire re-write of your backend application. It may make sense to do that in the future, but introducing GraphQL gradually--i.e. just one or two APIs here and there--can still have some nice benefits and begin to introduce the value of GraphQL to your users/clients. 286 | 287 | ![46](./images/47-46.png) 288 | 289 | Utilize the existing service offerings, be it open source or otherwise. There are some big hitters in this space that can certainly save you some work, and [Apollo](https://www.apollographql.com/) is certainly one of the most prominent players in this space. Investigate their service offerings yourself and see if it makes financial sense to tie into some of their excellent services that enhance GraphQL and make it easier to adopt! 290 | 291 | ![47](./images/48-47.png) 292 | 293 | [Graphcool](https://www.graph.cool/) is also an excellent service, and offers some of the same service offerings of [Apollo](https://www.apollographql.com/). I haven't used it as much, but I have heard excellent things, so be sure to do some due diligence to see if either meet your needs more effectively. 294 | 295 | ![48](./images/49-48.png) 296 | 297 | If introducing a GraphQL layer to an existing RESTful backend, consider hosting a separate/standalone endpoint to your backend exposed at `/graphql`. This makes it clear it's a separate construct to your base API, but also makes it very clear of the intended purpose. 298 | 299 | Additionally, consider hosting something like GraphiQL or GraphQLPlayground to make the interaction and documentation of this new layer as robust as possible! 300 | 301 | ![49](./images/50-49.png) 302 | 303 | Up to this point, I've primarily focused on backend technologies, but there are also a great number of niceties that have begun to spring up to make using a GraphQL API as clean as possible in your client side code. 304 | 305 | ![50](./images/51-50.png) 306 | 307 | First and foremost, [Apollo](https://www.apollographql.com/) has some excellent open-source client-side offerings. 308 | 309 | ![51](./images/52-51.png) 310 | 311 | In particular, I'd like to mention [apollo-boost][apollo-boost], which makes integrating GraphQL in your React application incredibly, incredibly easy. 312 | 313 | [apollo-boost]: https://github.com/apollographql/apollo-client/tree/master/packages/apollo-boost 314 | 315 | ![apollo boost example](./images/53-apollo-boost-example.png) 316 | 317 | [Graphcool](https://www.graph.cool/) also has a number of client-side libraries, but once again, I haven't investigated them as much. That said, it's still worth comparing side-by-side with [Apollo](https://www.apollographql.com/) to see what fits your needs better! 318 | 319 | ![53](./images/54-53.png) 320 | 321 | If you haven't noticed a trend yet, you may not have been paying close enough attention :) [Apollo](https://www.apollographql.com/) and [Graphcool](https://www.graph.cool/) are two of the big players in this space, and you can bet that if you're running into a problem there is likely a service or open-source offering from one of these two companies, if not from Facebook. 322 | 323 | ![54](./images/55-54.png) 324 | 325 | Would you consider yourself a minimalist? Is shipping that ultra-small 200KB gzipped JavaScript payload one of your priorities? 326 | 327 | If so, you may consider going "vanilla" and utilizing the Fetch API, which can also be used with GraphQL. You won't get some niceties (such as in apollo-boost) that are in my opinion very worth it, but you do ship a reduced payload to your users and that can be an inherently good thing. Just be aware that you may end up implementing more code than you think to deliver similar functionality. 328 | 329 | ![55](./images/56-55.png) 330 | 331 | Finally, [urql from FormidableLabs](https://github.com/FormidableLabs/urql) is a newer offering that shows some promise. It is circling much the same space as apollo-boost and intends to make getting started with GraphQL--from a client-side perspective--as simple as possible. 332 | 333 | It's a great time to be in the GraphQL ecosystem with all this excellent tooling. Exciting times! 334 | 335 | ![56](./images/57-56.png) 336 | 337 | I've created (and open sourced!) some demos and repositories to illustrate some of what I've been discussing today. 338 | 339 | ![57](./images/58-57.png) 340 | 341 | Check out some of the below demos/source code to learn more! 342 | 343 | ## [graphql-rest-implementation](https://github.com/DSchau/graphql-rest-implementation) 344 | 345 | A demonstration of graphql-tools and GraphQL as a layer in front of an existing RESTful backend. 346 | 347 | ## [graphql-rest-demo](https://github.com/DSchau/graphql-rest-demo) 348 | 349 | A simple RESTful backend that exposes a CRUD API for operating on a blog-like application, e.g. posts, commments, users, etc. 350 | 351 | ## [speaker-signup](https://github.com/dschau/speaker-signup) 352 | 353 | A client-side application demonstrating apollo-boost and static generation with Gatsby for reduced payload sizes. It uses Github's GraphQL API to display a number of issues, which can then be reacted upon (i.e. liked, disliked, etc.), and is intended to be used to support our local Omaha NebraskaJS meetup. 354 | 355 | All have been open sourced, so be sure to check out the code to learn more! 356 | 357 | ![58](./images/59-58.png) 358 | 359 | Check out some of these links to view the repos and/or live demonstration sites of the GraphQL functionality! 360 | 361 | - [REST backend](https://github.com/DSchau/graphql-rest-demo) 362 | - [GraphQL Layer](https://github.com/DSchau/graphql-rest-implementation) 363 | - [Speaker Signup Repo](https://github.com/DSchau/speaker-signup) 364 | - [Speaker Signup App](https://speaker-signup.netlify.com) 365 | 366 | ![59](./images/60-59.png) 367 | 368 | Thanks for reading, and I hope this leaves you feeling much more confident about the value of GraphQL and informed enough to make a decision as to whether it may make sense to adopt for your applications in the future! 369 | 370 | ![60](./images/61-60.png) 371 | -------------------------------------------------------------------------------- /content/blog/2017-07-17-getting-started-with-gatsby/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting Started with Gatsby 3 | date: 2017-07-17T17:12:33.962Z 4 | tags: 5 | - gatsby 6 | - react 7 | - javascript 8 | featured: preview.png 9 | excerpt: Gatsby is an incredible static site generator that lets you build a static site that still has all the benefits expected from a modern web application. In this tutorial, we'll create a static blog, and get an in-depth look at Gatsby and its feature-set. 10 | --- 11 | 12 | _This blog post was originally published at [Object Partners, Inc.](https://objectpartners.com/2017/07/19/creating-a-static-blog-with-gatsby/), and has since been cross-posted to the [official gatsby blog](https://www.gatsbyjs.org/blog/2017-07-19-creating-a-blog-with-gatsby/)_ 13 | 14 | Gatsby is an incredible static site generator that allows for React to be used as the underlying rendering engine to scaffold out a static site that truly has all the benefits expected in a modern web application. It does this by rendering dynamic React components into static HTML content via [server side rendering][react-dom-server] at build time. This means that your users get all the benefits of a static site such as the ability to work without JavaScript, search engine friendliness, speedy load times, etc. without losing the dynamism and interactivity that is expected of the modern web. Once rendered to static HTML, client-site React/JavaScript _can_ take over (if creating stateful components or logic in `componentDidMount`) and add dynamism to the statically generated content. 15 | 16 | Gatsby [recently released][gatsby-release] a v1.0.0 with a bunch of new features, including (but not limited to) the ability to create content queries with GraphQL, integration with various CMSs--including WordPress, Contentful, Drupal, etc., and route based code splitting to keep the end-user experience as snappy as possible. In this post, we'll take a deep dive into Gatsby and some of these new features by creating a static blog. Let's get on it! 17 | 18 | ## Getting started 19 | 20 | ### Installing the CLI 21 | 22 | `npm install -g gatsby` 23 | 24 | Gatsby ships with a great CLI (command line interface) that contains the functionality of scaffolding out a working site, as well as commands to help develop the site once created. 25 | 26 | `gatsby new personal-blog && cd $_` 27 | 28 | This command will create the folder `personal-blog` and then change into that directory. A working `gatsby` statically generated application can now be developed upon. The Gatsby CLI includes many common development features such as `gatsby build` (build a production, statically generated version of the project), `gatsby develop` (launch a hot-reload enabled web development server), etc. 29 | 30 | We can now begin the exciting task of _actually_ developing on the site, and creating a functional, modern blog. You'll generally want to use `gatsby develop` to launch the local development server to validate functionality as we progress through the steps. 31 | 32 | ## Adding necessary plugins 33 | 34 | Gatsby supports a [rich plugin interface][gatsby-plugins], and many incredibly useful plugins have been authored to make accomplishing common tasks a breeze. Plugins can be broken up into three main categories: **functional** plugins, **source** plugins, and **transformer** plugins. 35 | 36 | ### Functional plugins 37 | 38 | Functional plugins either implement some functionality (e.g. offline support, generating a sitemap, etc.) _or_ they extend Gatsby's webpack configuration adding support for typescript, sass, etc. 39 | 40 | For this particular blog post, we want a single page app-like feel (without page reloads), as well as the ability to dynamically change the `title` tag within the `head` tags. As noted, the Gatsby plugin ecosystem is rich, vibrant, and growing, so oftentimes a plugin already exists that solves the particular problem you're trying to solve. To address the functionality we want for _this_ blog, we'll use the following plugins: 41 | 42 | - [`gatsby-plugin-catch-links`][gatsby-plugin-catch-links] 43 | - implements the history `pushState` API, and does not require a page reload on navigating to a different page in the blog 44 | - [`gatsby-plugin-react-helmet`][gatsby-plugin-react-helmet] 45 | - [react-helmet][react-helmet] is a tool that allows for modification of the `head` tags; Gatsby statically renders any of these `head` tag changes 46 | 47 | with the following command: 48 | 49 | ```bash 50 | yarn add gatsby-plugin-catch-links gatsby-plugin-react-helmet 51 | ``` 52 | 53 | We're using [yarn][yarn], but npm can just as easily be used with `npm i --save [deps]`. 54 | 55 | After installing each of these functional plugins, we'll edit `gatsby-config.js`, which Gatsby loads at build-time to implement the exposed functionality of the specified plugins. 56 | 57 | ```javascript{6} 58 | module.exports = { 59 | siteMetadata: { 60 | title: `Your Name - Blog`, 61 | author: `Your Name` 62 | }, 63 | plugins: ["gatsby-plugin-catch-links", "gatsby-plugin-react-helmet"] 64 | }; 65 | ``` 66 | 67 | Without any additional work besides a `yarn install` and editing a config file, we now have the ability to edit our site's head tags, as well as implement a single page app feel without reloads. Now let's enhance the base functionality by implementing a source plugin which can load blog posts from our local file system. 68 | 69 | ### Source plugins 70 | 71 | Source plugins create _nodes_ which can then be transformed into a usable format (if not already usable) by a transformer plugin. For instance, a typical workflow often involves using [`gatsby-source-filesystem`][gatsby-source-filesystem], which loads files off of disk--e.g. Markdown files--and then specifying a Markdown transformer to transform the Markdown into HTML. 72 | 73 | Since the bulk of the blog's content, and each article, will be authored in Markdown, let's add that [`gatsby-source-filesystem`][gatsby-source-filesystem] plugin. Similarly to our previous step, we'll install the plugin and then inject into our `gatsby-config.js`, like so: 74 | 75 | ```bash 76 | yarn add gatsby-source-filesystem 77 | ``` 78 | 79 | ```javascript{6-12} 80 | module.exports = { 81 | // previous configuration 82 | plugins: [ 83 | "gatsby-plugin-catch-links", 84 | "gatsby-plugin-react-helmet", 85 | { 86 | resolve: `gatsby-source-filesystem`, 87 | options: { 88 | path: `${__dirname}/src/pages`, 89 | name: "pages" 90 | } 91 | } 92 | ] 93 | }; 94 | ``` 95 | 96 | Some explanation will be helpful here! An `options` object can be passed to a plugin, and we're passing the filesystem `path` (i.e. where our Markdown files will be located), and then a `name` for the source files. Now that Gatsby knows about our source files, we can begin applying some useful transformers to convert those files into usable data! 97 | 98 | ### Transformer plugins 99 | 100 | As mentioned, a transformer plugin takes some underlying data format that is not inherently usable in its current form (e.g. Markdown, json, yaml, etc.), and transforms it into a format that Gatsby can understand, and that we can query against with GraphQL. Jointly, the filesystem source plugin will load file nodes (as Markdown) off of our filesystem, and then the Markdown transformer will take over and convert to usable HTML. 101 | 102 | We'll only be using one transformer plugin (for Markdown), so let's get that installed. 103 | 104 | - [gatsby-transformer-remark][gatsby-transformer-remark] 105 | - Uses the [remark][remark] Markdown parser to transform .md files on disk into HTML; additionally this transformer can optionally take plugins to further extend functionality--e.g. add syntax highlighting with `gatsby-remark-prismjs`, `gatsby-remark-copy-linked-files` to copy relative files specified in markdown, `gatsby-remark-images` to compress images and add responsive images with `srcset`, etc. 106 | 107 | The process should be familiar by now, install and then add to config. 108 | 109 | ```bash 110 | yarn add gatsby-transformer-remark 111 | ``` 112 | 113 | and editing `gatsby-config.js` 114 | 115 | ```javascript{14-18} 116 | module.exports = { 117 | // previous setup 118 | plugins: [ 119 | "gatsby-plugin-catch-links", 120 | "gatsby-plugin-react-helmet", 121 | { 122 | resolve: `gatsby-source-filesystem`, 123 | options: { 124 | path: `${__dirname}/src/pages`, 125 | name: "pages" 126 | } 127 | }, 128 | { 129 | resolve: "gatsby-transformer-remark", 130 | options: { 131 | plugins: [] // just in case those previously mentioned remark plugins sound cool :) 132 | } 133 | } 134 | ] 135 | }; 136 | ``` 137 | 138 | Whew! Seems like a lot of set up, but collectively these plugins are going to super charge Gatsby, and give us an incredibly powerful (yet relatively simple!) development environment. We have one more set up step and it's an easy one. We're simply going to create a Markdown file that will contain the content of our first blog post. Let's get to it. 139 | 140 | ## Writing our first Markdown blog post 141 | 142 | The `gatsby-source-filesystem` plugin we configured earlier expects our content to be in `src/pages`, so that's exactly where we'll put it! 143 | 144 | Gatsby is not at all prescriptive in naming conventions, but a typical practice for blog posts is to name the folder something like `MM-DD-YYYY-title`, e.g. `07-12-2017-hello-world`. Let's do just that, and create the folder `src/pages/07-12-2017-hello-world`, and place an `index.md` inside! 145 | 146 | The content of this Markdown file will be our blog post, authored in Markdown (of course!). Here's what it'll look like: 147 | 148 | ```markdown 149 | --- 150 | path: "/hello-world" 151 | date: 2017-07-12T17:12:33.962Z 152 | title: "My First Gatsby Post" 153 | --- 154 | 155 | Oooooh-weeee, my first blog post! 156 | ``` 157 | 158 | _Fairly_ typical stuff, except for the block surrounded in dashes. What is that? That is what is referred to as [`frontmatter`][frontmatter], and the contents of the block can be used to inject React components with the specified data, e.g. path, date, title, etc. Any piece of data can be injected here (e.g. tags, sub-title,draft, etc.), so feel free to experiment and find what necessary pieces of frontmatter are required to achieve an ideal blogging system for your usage. One important note is that `path` will be used when we dynamically create our pages to specify the URL/path to render the file (in a later step!). In this instance, `http://localhost:8000/hello-world` will be the path to this file. 159 | 160 | Now that we have created a blog post with frontmatter and some content, we can begin actually writing some React components that will display this data! 161 | 162 | ## Creating the (React) template 163 | 164 | As Gatsby supports server side rendering (to string) of React components, we can write our template in... you guessed it, React! (Or [Preact][gatsby-plugin-preact], if that's more your style) 165 | 166 | We'll want to create the file `src/templates/blog-post.js` (please create the `src/templates` folder if it does not yet exist!). 167 | 168 | ```javascript 169 | import React from "react"; 170 | import Helmet from "react-helmet"; 171 | 172 | // import '../css/blog-post.css'; // make it pretty! 173 | 174 | export default function Template({ 175 | data // this prop will be injected by the GraphQL query we'll write in a bit 176 | }) { 177 | const { markdownRemark: post } = data; // data.markdownRemark holds our post data 178 | return ( 179 |
180 | 181 |
182 |

{post.frontmatter.title}

183 |
187 |
188 |
189 | ); 190 | } 191 | ``` 192 | 193 | Whoa, neat! This React component will be rendered to a static HTML string (for each route/blog post we define), which will serve as the basis of our routing/navigation for our blog. 194 | 195 | At this point, there is a reasonable level of confusion and "magic" occuring, particularly with the props injection. What is `markdownRemark`? Where is this `data` prop injected from? All good questions, so let's answer them by writing a GraphQL query to seed our `