├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── sites ├── honkify │ ├── .gitignore │ ├── docs │ │ ├── installation.mdx │ │ └── react │ │ │ ├── custom-hook.mdx │ │ │ └── other.mdx │ ├── gatsby-config.js │ ├── package.json │ ├── src │ │ ├── components │ │ │ ├── button.js │ │ │ ├── honker.js │ │ │ └── layout.js │ │ ├── gatsby-plugin-theme-ui │ │ │ └── index.js │ │ ├── images │ │ │ └── honk.svg │ │ └── pages │ │ │ └── index.mdx │ └── yarn.lock ├── lookup │ ├── .env.EXAMPLE │ └── package.json ├── negronis │ ├── .env.EXAMPLE │ ├── content │ │ ├── events │ │ │ └── data.yml │ │ └── recipes │ │ │ ├── boulevardier.mdx │ │ │ ├── classic.mdx │ │ │ ├── index.mdx │ │ │ └── sbagliato.mdx │ ├── gatsby-config.js │ ├── package.json │ └── src │ │ ├── images │ │ ├── negroni-nuff.jpg │ │ └── negroni.jpg │ │ └── pages │ │ ├── history.js │ │ └── index.js └── yarn.lock └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | .env.* 71 | !.env.EXAMPLE 72 | .netlify 73 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": true, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "all" 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Jason Lengstorf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Intermediate/Advanced Gatsby 2 | 3 | A Frontend Masters workshop. 4 | 5 | ## Setup 6 | 7 | Clone this repo locally: 8 | 9 | ``` 10 | git clone git@github.com:jlengstorf/gatsby-intermediate.git 11 | ``` 12 | 13 | Make sure you’re on the `start` branch: 14 | 15 | ``` 16 | git checkout start 17 | ``` 18 | 19 | ## Part I: Create a Docs Theme 20 | 21 | - Set up Yarn workspaces 22 | - Create a site for theme dev 23 | - Create the `packages/gatsby-theme-docs` folder 24 | - `yarn init` 25 | - Create `index.js` (`// boop`) 26 | - Install the docs theme 27 | - `yarn workspace negronis add "gatsby-theme-docs@*"` (quotes for Windows) 28 | - Add default config to `gatsby-config.js` 29 | - Make sure the content directory exists (`onPreBootstrap`) 30 | - `yarn add mkdirp` 31 | - Validate that this works by starting the `theme-dev` site in `develop` mode 32 | - Define the docs data type (`createSchemaCustomization`) 33 | - Show this data type in GraphiQL 34 | - Run a query to show it returning an empty array 35 | - Create docs nodes from MDX files (`onCreateNode`) 36 | - Only get the docs, not all MDX files 37 | - Define a custom resolver to get the MDX `body` content (`createResolvers`) 38 | - Write a passthrough resolver (hat tip to @christopherbiscardi for the original work to figure out how these work) 39 | - Create the required React components to display a docs page 40 | - Create a `Layout` component (`src/components/layout.js`) 41 | - Create a `DocsPage` component (`src/components/docs-page.js`) 42 | - Set up `MDXRenderer` 43 | - Create a `DocsPageTemplate` component (`src/templates/docs-page-template.js`) 44 | - Write the GraphQL query in GraphiQL first 45 | - Use the Code Exporter to get started 46 | - Create pages from the docs nodes (`createPages`) 47 | - Write a GraphQL query in GraphiQL first 48 | - Add Theme UI 49 | - `yarn workspace gatsby-theme-docs add theme-ui gatsby-plugin-theme-ui @emotion/core @mdx-js/react` 50 | - Update `gatsby-config.js` 51 | - Add a theme file (`src/gatsby-plugin-theme-ui/index.js`) 52 | - Update `Layout` to use Theme UI 53 | - Update `DocsPage` to use Theme UI 54 | - Create a `TableOfContents` component (`src/components/table-of-contents.js`) 55 | - Write a `useDocs` hook (`src/hooks/use-docs.js`) 56 | - Add support for syntax highlighted code 57 | - `yarn workspace gatsby-theme-docs add mdx-utils prism-react-renderer` 58 | - Create a `Code` component (`src/components/code.js`) 59 | - Shadow the MDX components in Theme UI to use `Code` (`src/gatsby-plugin-theme-ui/components.js`) 60 | - Insert a fenced code block (use `src/components/docs-page.js`) into `docs/index.mdx` 61 | - Add support for live editing code blocks 62 | - `yarn workspace gatsby-theme-docs add react-live` 63 | - Add a scope file for easy shadowing 64 | - Update `Code` to use `react-live` 65 | 66 | ## Part II: Honkify 67 | 68 | - Install the docs theme 69 | - `yarn workspace negronis add "gatsby-theme-docs@*"` (quotes for Windows) 70 | - Update `gatsby-config.js` with custom basePath and disable theme MDX 71 | - The existing theme from the Honkify site will automatically override the docs Theme UI config 72 | - Shadow the `Layout` component 73 | - Create a `Button` component (`src/components/button.js`) 74 | - Shadow the `scope.js` file to add `Button` 75 | - Add the `Button` component in a live-editable code block in the docs 76 | - Show it interacting with Honkify 77 | 78 | ## Part III: Build a Negroni Fan Site 79 | 80 | - Add Theme UI 81 | - `yarn workspace negronis add theme-ui gatsby-plugin-theme-ui @emotion/core @mdx-js/react` 82 | - Add a preset (`yarn workspace negronis add @theme-ui/presets`) 83 | - Create a theme file (`src/gatsby-plugin-theme-ui/index.js`) 84 | - Create a `Layout` component (`src/components/layout.js`) 85 | - Update `src/pages/index.js` to use the `Layout` 86 | - Update `src/pages/history.js` to use the `Layout` 87 | - Add styles for a hollow button 88 | - Add image support 89 | - `yarn workspace negronis add gatsby-source-filesystem gatsby-transformer-cloudinary gatsby-image` 90 | - Get credentials from Cloudinary 91 | - Add env vars to `.env.development` 92 | - Load env vars in `gatsby-config.js` 93 | - Add plugin config to `gatsby-config.js` 94 | - Query for images 95 | - Show this in GraphiQL first 96 | - Update `src/pages/index.js` to display an image 97 | - Quick aside to show transformations with Cloudinary because they’re dope 98 | - Update `src/pages/history.js` to display an image 99 | - Install the docs theme 100 | - Recipes are a kind of documentation! :) 101 | - `yarn workspace negronis add "gatsby-theme-docs@*"` (quotes for Windows) 102 | - Add modified config to `gatsby-config.js` 103 | - `basePath: '/recipes'` 104 | - `contentPath: 'content/recipes'` 105 | - Update `src/pages/index.js` to link to `/recipes` 106 | - Add styles for a primary button 107 | - Shadow the `Layout` component in the docs theme 108 | - Shadow the `TableOfContents` component in the docs theme 109 | - Install the events theme 110 | - `yarn workspace negronis add @jlengstorf/gatsby-theme-events` 111 | - This was built as part of this free course on authoring Gatsby themes: https://egghead.io/courses/gatsby-theme-authoring 112 | - Update `gatsby-config.js` with a custom basePath and contentPath 113 | - Shadow the `Layout` component in the events theme 114 | 115 | ## Part IV: Rick & Morty Lookup App 116 | 117 | - Add support for client-side GraphQL queries 118 | - `yarn workspace lookup add gatsby-plugin-apollo @apollo/react-common @apollo/react-hooks graphql-tag` 119 | - Update `gatsby-config.js` to use `gatsby-plugin-apollo` 120 | - Point Apollo at the Rick & Morty API (https://rickandmortyapi.com/graphql/) 121 | - Create pages 122 | - `src/pages/index.js` 123 | - `src/pages/search.js` 124 | - Add support for client-only routes 125 | - `gatsby-node.js` (`onCreatePage`/`matchPath`) 126 | - Add a redirect `netlify.toml` 127 | - Test using `netlify dev` 128 | - Create a search form 129 | - React hooks 130 | - Programmatic navigation 131 | - Add a submit handler 132 | - Create a results component 133 | - Query based on the current search string 134 | - Figure out the search string from state or URL 135 | - `location` 136 | 137 | -------------------------------------------------------------------------------- /sites/honkify/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | .env.* 71 | !.env.EXAMPLE 72 | .netlify 73 | -------------------------------------------------------------------------------- /sites/honkify/docs/installation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | --- 4 | 5 | HONK! 6 | -------------------------------------------------------------------------------- /sites/honkify/docs/react/custom-hook.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom React Hook 3 | --- 4 | 5 | HONK 6 | -------------------------------------------------------------------------------- /sites/honkify/docs/react/other.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Other React Stuff 3 | --- 4 | 5 | HONK 6 | -------------------------------------------------------------------------------- /sites/honkify/gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'gatsby-plugin-react-helmet', 4 | { 5 | resolve: 'gatsby-plugin-mdx', 6 | options: { 7 | defaultLayouts: { 8 | default: require.resolve('./src/components/layout.js'), 9 | }, 10 | }, 11 | }, 12 | 'gatsby-plugin-theme-ui', 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /sites/honkify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "honkify", 4 | "version": "0.0.1", 5 | "author": "Jason Lengstorf (https://lengstorf.com)", 6 | "scripts": { 7 | "build": "gatsby build", 8 | "develop": "gatsby develop" 9 | }, 10 | "dependencies": { 11 | "@emotion/core": "*", 12 | "@mdx-js/mdx": "^1.5.0", 13 | "@mdx-js/react": "^1.5.0", 14 | "@theme-ui/prism": "^0.2.40", 15 | "gatsby": "^2.15.28", 16 | "gatsby-plugin-mdx": "^1.0.46", 17 | "gatsby-plugin-react-helmet": "^3.1.10", 18 | "gatsby-plugin-theme-ui": "^0.2.43", 19 | "honkify": "^0.2.0", 20 | "react": "^16.10.1", 21 | "react-dom": "^16.10.1", 22 | "react-helmet": "^5.2.1", 23 | "theme-ui": "^0.2.43" 24 | }, 25 | "main": "gatsby-config.js", 26 | "license": "MIT" 27 | } 28 | -------------------------------------------------------------------------------- /sites/honkify/src/components/button.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { jsx } from 'theme-ui'; 3 | 4 | const Button = ({ text = 'Submit', type = 'submit', ...props }) => ( 5 | 8 | ); 9 | 10 | export default Button; 11 | -------------------------------------------------------------------------------- /sites/honkify/src/components/honker.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { useState } from 'react'; 3 | import { jsx } from 'theme-ui'; 4 | import honkify from 'honkify'; 5 | 6 | const Honker = () => { 7 | const initialState = { active: false, unregister: () => {} }; 8 | const [honk, setHonk] = useState(initialState); 9 | const toggleHonk = () => { 10 | if (!honk.active) { 11 | const unregister = honkify(); 12 | setHonk({ active: true, unregister }); 13 | } 14 | 15 | if (honk.active) { 16 | honk.unregister(); 17 | setHonk(initialState); 18 | } 19 | }; 20 | 21 | return ( 22 | 29 | ); 30 | }; 31 | 32 | export default Honker; 33 | -------------------------------------------------------------------------------- /sites/honkify/src/components/layout.js: -------------------------------------------------------------------------------- 1 | /** @jsx jsx */ 2 | import { Fragment } from 'react'; 3 | import { jsx } from 'theme-ui'; 4 | import { Link } from 'gatsby'; 5 | import { Global } from '@emotion/core'; 6 | import Helmet from 'react-helmet'; 7 | import Honk from '../images/honk.svg'; 8 | import Honker from './honker'; 9 | 10 | const seo = { 11 | title: 'Honkify.js — the goose is loose!', 12 | description: 13 | 'Does your website need more HONK? Add Honkify.js to add more geese being jerks to your website.', 14 | image: 15 | 'https://res.cloudinary.com/jlengstorf/image/upload/q_auto,f_auto/v1569994857/honkify.jpg', 16 | url: 'https://honkify.netlify.com/', 17 | }; 18 | 19 | const Layout = ({ children }) => ( 20 | 21 | 22 | 23 | 24 | {seo.title} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | Honk. 40 | 41 | Honkify.js 42 | 43 |
44 |
{children}
45 | 49 |
50 | ); 51 | 52 | export default Layout; 53 | -------------------------------------------------------------------------------- /sites/honkify/src/gatsby-plugin-theme-ui/index.js: -------------------------------------------------------------------------------- 1 | import nightOwl from '@theme-ui/prism/presets/night-owl'; 2 | 3 | export default { 4 | colors: { 5 | primary: '#276ebd', 6 | secondary: '#619fe4', 7 | muted: '#888', 8 | text: '#222', 9 | background: '#fff', 10 | }, 11 | fonts: { 12 | body: 13 | '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', 14 | heading: 15 | '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', 16 | monospace: 'menlo, monospace', 17 | }, 18 | styles: { 19 | pre: { 20 | ...nightOwl, 21 | overflowX: 'scroll', 22 | p: 3, 23 | }, 24 | }, 25 | header: { 26 | alignItems: 'baseline', 27 | bg: 'primary', 28 | color: 'background', 29 | display: 'flex', 30 | flexWrap: 'wrap', 31 | fontFamily: 'heading', 32 | justifyContent: 'center', 33 | paddingBottom: 4, 34 | paddingTop: 3, 35 | px: `5vw`, 36 | textAlign: 'center', 37 | '@media (min-width: 700px)': { 38 | px: `calc((100vw - 580px) / 2)`, 39 | }, 40 | img: { 41 | maxWidth: 60, 42 | }, 43 | a: { 44 | color: 'background', 45 | fontSize: 6, 46 | fontWeight: 'bold', 47 | mx: 2, 48 | textDecoration: 'none', 49 | ':first-of-type': { 50 | ml: 0, 51 | }, 52 | ':last-of-type': { 53 | mr: 0, 54 | }, 55 | ':focus': { 56 | outline: t => `3px solid ${t.colors.background}`, 57 | outlineOffset: 3, 58 | }, 59 | }, 60 | }, 61 | content: { 62 | backgroundColor: 'background', 63 | color: 'text', 64 | fontFamily: 'body', 65 | fontSize: 18, 66 | mx: 'auto', 67 | my: 5, 68 | maxWidth: '90vw', 69 | width: 580, 70 | }, 71 | footer: { 72 | bg: 'secondary', 73 | color: 'text', 74 | fontFamily: 'body', 75 | fontSize: 14, 76 | px: '5vw', 77 | py: 2, 78 | textAlign: 'center', 79 | '@media (min-width: 700px)': { 80 | px: `calc((100vw - 580px) / 2)`, 81 | }, 82 | a: { 83 | color: 'white', 84 | }, 85 | }, 86 | button: { 87 | primary: { 88 | bg: 'primary', 89 | border: t => `2px solid ${t.colors.primary}`, 90 | borderRadius: 6, 91 | color: 'background', 92 | cursor: 'pointer', 93 | fontSize: 17, 94 | fontWeight: 300, 95 | letterSpacing: '0.2em', 96 | textTransform: 'uppercase', 97 | transition: '250ms all linear', 98 | ':focus,:hover': { 99 | borderColor: 'text', 100 | }, 101 | }, 102 | hollow: { 103 | alignSelf: 'flex-start', 104 | bg: 'transparent', 105 | border: t => `2px solid ${t.colors.background}`, 106 | borderRadius: 6, 107 | color: 'background', 108 | cursor: 'pointer', 109 | fontSize: 17, 110 | fontWeight: 300, 111 | letterSpacing: '0.2em', 112 | ml: 10, 113 | mt: 29, 114 | textTransform: 'uppercase', 115 | '@media (min-width: 450px)': { 116 | ml: 'auto', 117 | }, 118 | ':focus,:hover': { 119 | bg: 'background', 120 | color: 'primary', 121 | }, 122 | }, 123 | }, 124 | 'react-live': { 125 | border: t => `1px solid ${t.colors.muted}`, 126 | p: 4, 127 | }, 128 | 'prism-highlight': { 129 | p: 2, 130 | }, 131 | }; 132 | -------------------------------------------------------------------------------- /sites/honkify/src/images/honk.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sites/honkify/src/pages/index.mdx: -------------------------------------------------------------------------------- 1 | # Honkify.js 2 | 3 | Need a little more chaos in your life? Inspired by [_Untitled Goose Game_](https://goose.game), you can now set a goose loose on your site to act like a jerk. 4 | 5 | When activated, all links on the site will stop working, instead triggering a “honk!” sound effect. 6 | 7 | Honk. Honk honk honk. 8 | 9 | - [See the source code](https://github.com/jlengstorf/honkify) 10 | 11 | ## Praise for Honkify.js 12 | 13 | > Nobody asked for this. – [Jessica Tremblay](https://twitter.com/poofichu/status/1179146980569878528) 14 | 15 | > This is the worst thing you have ever done. – [E.J. Mason](https://twitter.com/codeability/status/1179136560110768128) 16 | 17 | ## Installation and Quick Start 18 | 19 | ``` 20 | yarn add honkify 21 | ``` 22 | 23 | In your code: 24 | 25 | ```js 26 | import honkify from 'honkify'; 27 | 28 | // The goose is loose! 29 | const unregister = honkify(); 30 | 31 | // Disable so links work again 32 | unregister(); 33 | ``` 34 | 35 | ## How to use this on a React site 36 | 37 | ```jsx 38 | import React, { useState } from 'react'; 39 | import honkify from 'honkify'; 40 | 41 | const Honker = () => { 42 | const initialState = { active: false, unregister: () => {} }; 43 | const [honk, setHonk] = useState(initialState); 44 | const toggleHonk = () => { 45 | if (!honk.active) { 46 | const unregister = honkify(); 47 | setHonk({ active: true, unregister }); 48 | } 49 | 50 | if (honk.active) { 51 | honk.unregister(); 52 | setHonk(initialState); 53 | } 54 | }; 55 | 56 | return ( 57 | 58 | ); 59 | }; 60 | 61 | export default Honker; 62 | ``` 63 | 64 | ## Disclaimer: please don’t use this 65 | 66 | Or, if you do, make sure it’s easy to toggle off. Geese may be jerks, but developers shouldn’t be. 67 | -------------------------------------------------------------------------------- /sites/lookup/.env.EXAMPLE: -------------------------------------------------------------------------------- 1 | # Get this at https://github.com/settings/tokens 2 | GITHUB_PERSONAL_ACCESS_TOKEN= 3 | -------------------------------------------------------------------------------- /sites/lookup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "lookup", 4 | "version": "0.0.1", 5 | "main": "gatsby-config.js", 6 | "author": "Jason Lengstorf (https://lengstorf.com)", 7 | "license": "MIT", 8 | "scripts": { 9 | "build": "gatsby build", 10 | "develop": "gatsby develop" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /sites/negronis/.env.EXAMPLE: -------------------------------------------------------------------------------- 1 | # Find this at https://cloudinary.com/console/settings/account 2 | CLOUDINARY_CLOUD_NAME= 3 | 4 | # Generate an API key pair at https://cloudinary.com/console/settings/security 5 | CLOUDINARY_API_KEY= 6 | CLOUDINARY_API_SECRET= 7 | -------------------------------------------------------------------------------- /sites/negronis/content/events/data.yml: -------------------------------------------------------------------------------- 1 | - name: Cocktail Making Class 2 | location: Rum Club, Portland OR 3 | start_date: 2019-10-30 4 | end_date: 2019-10-30 5 | url: http://rumclubpdx.com/ 6 | 7 | - name: Happy Hour 8 | location: Hey Love, Portland OR 9 | start_date: 2019-11-14 10 | end_date: 2019-11-14 11 | url: https://www.heylovepdx.com/ 12 | 13 | - name: Try Something New 14 | location: Angel Face, Portland OR 15 | start_date: 2019-11-22 16 | end_date: 2019-11-22 17 | url: https://www.angelfaceportland.com/ 18 | -------------------------------------------------------------------------------- /sites/negronis/content/recipes/boulevardier.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Boulevardier 3 | --- 4 | 5 | For an American twist on the Negroni, swap out the gin for bourbon. 6 | 7 | - 1oz bourbon 8 | - 1oz Campari 9 | - 1oz sweet vermouth 10 | - lemon twist 11 | 12 | Add bourbon, Campari, and vermouth into a mixing glass. Fill glass with ice and stir. Serve up with a twist of lemon. 13 | -------------------------------------------------------------------------------- /sites/negronis/content/recipes/classic.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Classic Negroni 3 | --- 4 | 5 | The classic Negroni is easy to make and it’s stood the test of time for a reason! 6 | 7 | - 1oz gin 8 | - 1oz Campari 9 | - 1oz sweet vermouth 10 | - lemon twist 11 | 12 | Add gin, Campari, and vermouth into a mixing glass. Fill glass with ice and stir. Serve up with a twist of lemon. 13 | -------------------------------------------------------------------------------- /sites/negronis/content/recipes/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Negroni Recipes and Variations 3 | --- 4 | 5 | Check out these delicious drinks! 6 | -------------------------------------------------------------------------------- /sites/negronis/content/recipes/sbagliato.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Sbagliato (Broken Negroni) 3 | --- 4 | 5 | For a lower-proof (but still delicious) twist, try a Negroni Sbagliato, which roughly translates to “Broken Negroni”, by substituting sparkling wine for gin. 6 | 7 | - 1oz prosecco 8 | - 1oz Campari 9 | - 1oz sweet vermouth 10 | - lemon twist 11 | 12 | Add prosecco, Campari, and vermouth into a mixing glass. Fill glass with ice and stir. Serve up with a twist of lemon. 13 | -------------------------------------------------------------------------------- /sites/negronis/gatsby-config.js: -------------------------------------------------------------------------------- 1 | // Gatsby Config commented out for the start branch 2 | // Jason adds this later in the course 3 | // 4 | // require('dotenv').config({ 5 | // path: `.env.${process.env.NODE_ENV}`, 6 | // }); 7 | 8 | // module.exports = { 9 | // plugins: [ 10 | // 'gatsby-plugin-theme-ui', 11 | // { 12 | // resolve: 'gatsby-source-filesystem', 13 | // options: { 14 | // name: 'images', 15 | // path: 'src/images', 16 | // }, 17 | // }, 18 | // { 19 | // resolve: 'gatsby-transformer-cloudinary', 20 | // options: { 21 | // cloudName: process.env.CLOUDINARY_CLOUD_NAME, 22 | // apiKey: process.env.CLOUDINARY_API_KEY, 23 | // apiSecret: process.env.CLOUDINARY_API_SECRET, 24 | // uploadFolder: 'fem-workshop', 25 | // }, 26 | // }, 27 | // { 28 | // resolve: 'gatsby-theme-docs', 29 | // options: { 30 | // basePath: '/recipes', 31 | // contentPath: 'content/recipes', 32 | // }, 33 | // }, 34 | // { 35 | // resolve: '@jlengstorf/gatsby-theme-events', 36 | // options: { 37 | // basePath: '/events', 38 | // contentPath: 'content/events', 39 | // }, 40 | // }, 41 | // ], 42 | // }; 43 | -------------------------------------------------------------------------------- /sites/negronis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "negronis", 4 | "version": "0.0.1", 5 | "author": "Jason Lengstorf (https://lengstorf.com)", 6 | "scripts": { 7 | "build": "gatsby build", 8 | "develop": "gatsby develop" 9 | }, 10 | "dependencies": { 11 | "gatsby": "^2.15.28", 12 | "react": "^16.10.1", 13 | "react-dom": "^16.10.1" 14 | }, 15 | "main": "gatsby-config.js", 16 | "license": "MIT" 17 | } 18 | -------------------------------------------------------------------------------- /sites/negronis/src/images/negroni-nuff.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlengstorf/gatsby-intermediate/61f9b0dfb02abb69c5f59098dfea170c5dddae2e/sites/negronis/src/images/negroni-nuff.jpg -------------------------------------------------------------------------------- /sites/negronis/src/images/negroni.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlengstorf/gatsby-intermediate/61f9b0dfb02abb69c5f59098dfea170c5dddae2e/sites/negronis/src/images/negroni.jpg -------------------------------------------------------------------------------- /sites/negronis/src/pages/history.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const History = () => ( 4 | <> 5 |

The History of the Negroni

6 |

7 | The Negroni is a variation on a classic cocktail called an Americano, 8 | which is a mix of Campari, sweet vermouth, and club soda. 9 |

10 |

11 | According to legend, in 1919 in Florence, Italy, Count Negroni was on the 12 | hunt for a drink a little stiffer than the average Italian caffé had to 13 | offer. 14 |

15 |

16 | At the count’s request, a Florence bartender swapped out the club soda in 17 | the Americano for gin, and the result has lived on with the count’s name 18 | since. 19 |

20 |

The recent rise in popularity for Negronis

21 |

22 | Recently, the Negroni has grown in popularity due to a resurgence in the 23 | popularity of craft cocktails, a revival of interest in gin, and some 24 | clever marketing from Campari, who acquired the Wild Turkey distillery in 25 | 2009 and declared 2011 “The Year of the Negroni” to expand its US 26 | marketing efforts. 27 |

28 |
29 |

30 | 31 | Photo by Nuff on Unsplash 32 | 33 |

34 | 35 | ); 36 | 37 | export default History; 38 | -------------------------------------------------------------------------------- /sites/negronis/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'gatsby'; 3 | 4 | const Index = () => ( 5 | <> 6 |

Negronis: A Love Story

7 |

8 | A Negroni, while simple, is a beautifully complex cocktail with endless 9 | opportunities to experiment with flavors. 10 |

11 | Learn the History 12 | 13 | ); 14 | 15 | export default Index; 16 | -------------------------------------------------------------------------------- /sites/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | --------------------------------------------------------------------------------