diff --git a/.babelrc.js b/.babelrc.js index 4eb42997a778d..0a68c657a7b33 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -9,5 +9,11 @@ if (process.env.NODE_ENV !== `test`) { module.exports = { sourceMaps: true, presets: ["babel-preset-gatsby-package"], + overrides: [ + { + test: "**/*.ts", + plugins: [["@babel/plugin-transform-typescript", { isTSX: true }]], + }, + ], ignore, } diff --git a/.circleci/config.yml b/.circleci/config.yml index c9a5c64403f8d..b267144509cfc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,6 @@ orbs: win: circleci/windows@1.0.0 + slack: circleci/slack@3.4.1 executors: node: @@ -35,7 +36,7 @@ aliases: attach_to_bootstrap: &attach_to_bootstrap attach_workspace: - at: packages + at: ./ ignore_master: &ignore_master filters: @@ -52,12 +53,10 @@ aliases: test_template: &test_template steps: - - checkout - - run: ./scripts/assert-changed-files.sh "packages/*|.circleci/*" - - <<: *restore_cache - - <<: *install_node_modules - - <<: *persist_cache - <<: *attach_to_bootstrap + - <<: *install_node_modules + - run: yarn list react + - run: ./scripts/assert-changed-files.sh "packages/*|.circleci/*" - run: yarn jest -w 1 --ci - run: GATSBY_DB_NODES=loki yarn jest -w 1 --ci @@ -72,9 +71,70 @@ aliases: - lint - unit_tests_node8 + e2e_tests_production_runtime_alias: &e2e_tests_production_runtime_alias + <<: *e2e-executor + parameters: + nightly: + type: boolean + default: false + steps: + - e2e-test: + test_path: e2e-tests/production-runtime + test_command: CYPRESS_PROJECT_ID=is8aoq CYPRESS_RECORD_KEY=cb4708d2-1578-4665-9a07-c59f8db28d91 yarn test && CYPRESS_PROJECT_ID=htpvkv CYPRESS_RECORD_KEY=0d734841-c613-41d2-86e5-df0b5968f93f yarn test:offline + skip_file_change_test: << parameters.nightly >> + - notify-status: + condition: << parameters.nightly >> + + e2e_tests_development_runtime_alias: &e2e_tests_development_runtime_alias + <<: *e2e-executor + parameters: + nightly: + type: boolean + default: false + environment: + CYPRESS_PROJECT_ID: s3j3qj + CYPRESS_RECORD_KEY: 3904ca0c-bc98-47d9-8371-b68c5e81fb9b + steps: + - e2e-test: + test_path: e2e-tests/development-runtime + skip_file_change_test: << parameters.nightly >> + - notify-status: + condition: << parameters.nightly >> + + e2e_tests_gatsby-image_alias: &e2e_tests_gatsby-image_alias + <<: *e2e-executor + parameters: + nightly: + type: boolean + default: false + environment: + CYPRESS_PROJECT_ID: ave32k + CYPRESS_RECORD_KEY: fb3cb6e0-a0f9-48b2-aa9a-95e8ef150a85 + steps: + - e2e-test: + test_path: e2e-tests/gatsby-image + skip_file_change_test: << parameters.nightly >> + - notify-status: + condition: << parameters.nightly >> + commands: + notify-status: + parameters: + condition: + type: boolean + default: false + steps: + - when: + condition: << parameters.condition >> + steps: + - slack/status: + channel: eng-react-integration-status + e2e-test: parameters: + skip_file_change_test: + type: boolean + default: false trigger_pattern: type: string default: "packages/*|.circleci/*" @@ -84,12 +144,15 @@ commands: type: string default: "" # if unset, e2e-test.sh specifies the command steps: - - checkout - - run: ./scripts/assert-changed-files.sh "<< parameters.trigger_pattern >>|<< parameters.test_path >>/*" - - <<: *restore_cache - - <<: *install_node_modules - - <<: *persist_cache - <<: *attach_to_bootstrap + # In case of failure, add these steps again. Cache probably got deleted + #- <<: *restore_cache + #- <<: *install_node_modules + #- <<: *persist_cache + - unless: + condition: << parameters.skip_file_change_test >> + steps: + - run: ./scripts/assert-changed-files.sh "<< parameters.trigger_pattern >>|<< parameters.test_path >>/*" - run: ./scripts/e2e-test.sh "<< parameters.test_path >>" "<< parameters.test_command >>" version: 2.1 @@ -99,13 +162,20 @@ jobs: executor: node steps: - checkout - - run: ./scripts/assert-changed-files.sh "packages/*|(e2e|integration)-tests/*|.circleci/*" - <<: *restore_cache - <<: *install_node_modules - <<: *persist_cache + # persist our git checkout and node_modules as the next step (assert-changed-files) might exit this step + # when no files have changed (master). We still need to have these files for jobs like lint & unit_tests_node8 + - persist_to_workspace: + root: ./ + paths: + - "*" + - run: ./scripts/assert-changed-files.sh "packages/*|(e2e|integration)-tests/*|.circleci/*" - run: yarn bootstrap -- concurrency=2 + # Persist the workspace again with all packages already built - persist_to_workspace: - root: packages + root: ./ paths: - "*" @@ -113,12 +183,11 @@ jobs: executor: node parallelism: 2 steps: - - checkout - - <<: *restore_cache - - <<: *install_node_modules - - <<: *persist_cache + - <<: *attach_to_bootstrap - run: yarn lint:code - run: yarn lint:other + - run: ./scripts/assert-changed-files.sh "packages/*|.circleci/*" + - run: yarn typecheck - run: yarn check-repo-fields unit_tests_node8: @@ -176,29 +245,31 @@ jobs: test_path: e2e-tests/path-prefix e2e_tests_gatsby-image: - <<: *e2e-executor - environment: - CYPRESS_PROJECT_ID: ave32k - CYPRESS_RECORD_KEY: fb3cb6e0-a0f9-48b2-aa9a-95e8ef150a85 - steps: - - e2e-test: - test_path: e2e-tests/gatsby-image + <<: *e2e_tests_gatsby-image_alias + + e2e_tests_gatsby-image_with_experimental_react: + <<: *e2e_tests_gatsby-image_alias + + e2e_tests_gatsby-image_with_next_react: + <<: *e2e_tests_gatsby-image_alias e2e_tests_development_runtime: - <<: *e2e-executor - environment: - CYPRESS_PROJECT_ID: s3j3qj - CYPRESS_RECORD_KEY: 3904ca0c-bc98-47d9-8371-b68c5e81fb9b - steps: - - e2e-test: - test_path: e2e-tests/development-runtime + <<: *e2e_tests_development_runtime_alias + + e2e_tests_development_runtime_with_experimental_react: + <<: *e2e_tests_development_runtime_alias + + e2e_tests_development_runtime_with_next_react: + <<: *e2e_tests_development_runtime_alias e2e_tests_production_runtime: - <<: *e2e-executor - steps: - - e2e-test: - test_path: e2e-tests/production-runtime - test_command: CYPRESS_PROJECT_ID=is8aoq CYPRESS_RECORD_KEY=cb4708d2-1578-4665-9a07-c59f8db28d91 yarn test && CYPRESS_PROJECT_ID=htpvkv CYPRESS_RECORD_KEY=0d734841-c613-41d2-86e5-df0b5968f93f yarn test:offline + <<: *e2e_tests_production_runtime_alias + + e2e_tests_production_runtime_with_experimental_react: + <<: *e2e_tests_production_runtime_alias + + e2e_tests_production_runtime_with_next_react: + <<: *e2e_tests_production_runtime_alias themes_e2e_tests_development_runtime: <<: *e2e-executor @@ -230,16 +301,26 @@ jobs: starters_publish: executor: node steps: - - checkout - - <<: *restore_cache - - <<: *install_node_modules - - <<: *persist_cache + - <<: *attach_to_bootstrap - run: yarn markdown - run: sudo apt-get update && sudo apt-get install jq # jq is helpful for parsing json - run: git config --global user.name "GatsbyJS Bot" - run: git config --global user.email "core-team@gatsbyjs.com" - run: sh ./scripts/publish-starters.sh "starters/*" + update_i18n_source: + executor: node + steps: + - checkout + - run: git config --global user.name "GatsbyJS Bot" + - run: git config --global user.email "core-team@gatsbyjs.com" + - run: + command: yarn + working_directory: ~/project/scripts/i18n + - run: + command: yarn run update-source + working_directory: ~/project/scripts/i18n + build_www: docker: - image: circleci/node:12 @@ -247,9 +328,9 @@ jobs: steps: - checkout - restore_cache: - key: v1_www_public_dir + key: v2_www_public_dir - restore_cache: - key: v1_www_cache_dir + key: v2_www_cache_dir - run: command: yarn working_directory: ~/project/www @@ -258,11 +339,11 @@ jobs: command: GATSBY_CPU_COUNT=8 yarn build working_directory: ~/project/www - save_cache: - key: v1_www_public_dir_{{ epoch }} + key: v2_www_public_dir_{{ epoch }} paths: - ~/project/www/public - save_cache: - key: v1_www_cache_dir_{{ epoch }} + key: v2_www_cache_dir_{{ epoch }} paths: - ~/project/www/.cache @@ -272,7 +353,7 @@ jobs: steps: - checkout - restore_cache: - key: v1_www_public_dir + key: v2_www_public_dir - run: command: yarn add netlify-cli working_directory: ~/project/www @@ -302,8 +383,93 @@ jobs: name: "Run Tests" command: yarn test + bootstrap-with-experimental-react: + executor: node + parameters: + version: + type: string + default: "next" + steps: + - checkout + - run: + name: "Update React to prerelease" + command: "REACT_CHANNEL=<< parameters.version >> node ./scripts/upgrade-react" + - run: yarn install + - run: yarn bootstrap -- concurrency=2 + - run: yarn list react + - persist_to_workspace: + root: ./ + paths: + - "*" + + run_benchmarks: + docker: + - image: circleci/node:12 + resource_class: xlarge + steps: + - checkout + - run: ./scripts/build-benchmark.sh + workflows: version: 2 + + run_benchmarks: + jobs: [run_benchmarks] + triggers: + - schedule: + cron: "12 3 * * *" # every day at 03:12 + filters: + branches: + only: + - master + + nightly-react-next: + triggers: + - schedule: + cron: "0 0 * * 1,2,3,4,5" + filters: + branches: + only: + - master + jobs: + - bootstrap-with-experimental-react: + version: "next" + - e2e_tests_gatsby-image_with_next_react: + nightly: true + requires: + - bootstrap-with-experimental-react + - e2e_tests_development_runtime_with_next_react: + nightly: true + requires: + - bootstrap-with-experimental-react + - e2e_tests_production_runtime_with_next_react: + nightly: true + requires: + - bootstrap-with-experimental-react + nightly-react-experimental: + triggers: + - schedule: + cron: "0 0 * * 1,2,3,4,5" + filters: + branches: + only: + - master + jobs: + - bootstrap-with-experimental-react: + version: "experimental" + - e2e_tests_gatsby-image_with_experimental_react: + nightly: true + requires: + - bootstrap-with-experimental-react + - e2e_tests_development_runtime_with_experimental_react: + nightly: true + requires: + - bootstrap-with-experimental-react + - e2e_tests_production_runtime_with_experimental_react: + nightly: true + requires: + - bootstrap-with-experimental-react + build-test: jobs: - windows_unit_tests @@ -350,6 +516,8 @@ workflows: - starters_validate: <<: *ignore_master - starters_publish: + requires: + - bootstrap filters: branches: only: @@ -368,6 +536,11 @@ workflows: requires: - build_www context: build_www + - update_i18n_source: + filters: + branches: + only: + - master www_deploy: triggers: - schedule: diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000000..2a372e586f19d --- /dev/null +++ b/.eslintignore @@ -0,0 +1,25 @@ + +**/coverage/** +**/node_modules/** +bin/ +packages/*/dist/** +packages/*/lib/** +packages/*/scripts/** +**/dist/* +**/__testfixtures__/** +**/__tests__/fixtures/** +peril +docs +plop-templates +starters +www +benchmarks +e2e-tests +examples +integration-tests +**/*.d.ts + +packages/*/*.js +packages/gatsby-plugin-preload-fonts/prepare/*.js +packages/gatsby-image/withIEPolyfill/index.js +packages/gatsby/cache-dir/commonjs/**/* diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000000..943dc704f9739 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,142 @@ +const TSEslint = require("@typescript-eslint/eslint-plugin") + +module.exports = { + parser: "babel-eslint", + extends: [ + "google", + "eslint:recommended", + "plugin:flowtype/recommended", + "plugin:react/recommended", + "prettier", + "prettier/flowtype", + "prettier/react", + ], + plugins: ["flowtype", "prettier", "react", "filenames"], + parserOptions: { + ecmaVersion: 2016, + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + es6: true, + node: true, + jest: true, + }, + globals: { + before: true, + after: true, + spyOn: true, + __PATH_PREFIX__: true, + __BASE_PATH__: true, + __ASSET_PREFIX__: true, + }, + rules: { + "arrow-body-style": [ + "error", + "as-needed", + { requireReturnForObjectLiteral: true }, + ], + "no-unused-expressions": [ + "error", + { + allowTaggedTemplates: true, + }, + ], + "consistent-return": ["error"], + "filenames/match-regex": ["error", "^[a-z-\\d\\.]+$", true], + "no-console": "off", + "no-inner-declarations": "off", + "prettier/prettier": "error", + quotes: ["error", "backtick"], + "react/display-name": "off", + "react/jsx-key": "warn", + "react/no-unescaped-entities": "off", + "react/prop-types": "off", + "require-jsdoc": "off", + "valid-jsdoc": "off", + }, + overrides: [ + { + files: [ + "packages/**/gatsby-browser.js", + "packages/gatsby/cache-dir/**/*", + ], + env: { + browser: true, + }, + globals: { + ___loader: false, + ___emitter: false, + }, + }, + { + files: ["**/cypress/integration/**/*", "**/cypress/support/**/*"], + globals: { + cy: false, + Cypress: false, + }, + }, + { + files: ["*.ts", "*.tsx"], + parser: "@typescript-eslint/parser", + plugins: ["@typescript-eslint/eslint-plugin"], + rules: { + ...TSEslint.configs.recommended.rules, + // This rule ensures that typescript types do not have semicolons + // at the end of their lines, since our prettier setup is to have no semicolons + // e.g., + // interface Foo { + // - baz: string; + // + baz: string + // } + "@typescript-eslint/member-delimiter-style": [ + "error", + { + multiline: { + delimiter: "none", + }, + }, + ], + // This ensures all interfaces are named with an I as a prefix + // e.g., + // interface IFoo {} + "@typescript-eslint/interface-name-prefix": [ + "error", + { prefixWithI: "always" }, + ], + "@typescript-eslint/no-empty-function": "off", + // This ensures that we always type the return type of functions + // a high level focus of our TS setup is typing fn inputs and outputs. + "@typescript-eslint/explicit-function-return-type": "error", + // This forces us to use interfaces over types aliases for object defintions. + // Type is still useful for opaque types + // e.g., + // type UUID = string + "@typescript-eslint/consistent-type-definitions": [ + "error", + "interface", + ], + + // Allows us to write unions like `type Foo = "baz" | "bar"` + // otherwise eslint will want to switch the strings to backticks, + // which then crashes the ts compiler + quotes: "off", + "@typescript-eslint/quotes": [ + 2, + "backtick", + { + avoidEscape: true, + }, + ], + }, + }, + ], + settings: { + react: { + version: "16.4.2", + }, + }, +} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index c953f88345f75..0000000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "parser": "babel-eslint", - "extends": [ - "google", - "eslint:recommended", - "plugin:flowtype/recommended", - "plugin:react/recommended", - "prettier", - "prettier/flowtype", - "prettier/react" - ], - "plugins": ["flowtype", "prettier", "react", "filenames"], - "parserOptions": { - "ecmaVersion": 2016, - "sourceType": "module", - "ecmaFeatures": { - "jsx": true - } - }, - "env": { - "browser": true, - "es6": true, - "node": true, - "jest": true - }, - "globals": { - "before": true, - "after": true, - "spyOn": true, - "__PATH_PREFIX__": true, - "__BASE_PATH__": true, - "__ASSET_PREFIX__": true - }, - "rules": { - "arrow-body-style": [ - "error", - "as-needed", - { "requireReturnForObjectLiteral": true } - ], - "no-unused-expressions": [ - "error", - { - "allowTaggedTemplates": true - } - ], - "consistent-return": ["error"], - "filenames/match-regex": ["error", "^[a-z-\\d\\.]+$", true], - "no-console": "off", - "no-inner-declarations": "off", - "prettier/prettier": "error", - "quotes": ["error", "backtick"], - "react/display-name": "off", - "react/jsx-key": "warn", - "react/no-unescaped-entities": "off", - "react/prop-types": "off", - "require-jsdoc": "off", - "valid-jsdoc": "off" - }, - "overrides": [ - { - "files": [ - "packages/**/gatsby-browser.js", - "packages/gatsby/cache-dir/**/*" - ], - "env": { - "browser": true - }, - "globals": { - "___loader": false, - "___emitter": false - } - }, - { - "files": ["**/cypress/integration/**/*", "**/cypress/support/**/*"], - "globals": { - "cy": false, - "Cypress": false - } - } - ], - "settings": { - "react": { - "version": "16.4.2" - } - } -} diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index ca1c0bf502ac1..0000000000000 --- a/.flowconfig +++ /dev/null @@ -1,15 +0,0 @@ -[version] -0.109.0 - -[ignore] -.*/test/.* -.*/node_modules/documentation/.* -.*/node_modules/emotion/.* -.*/node_modules/fbjs/.* -.*/node_modules/jss/.* -.*/node_modules/preact/.* -.*/node_modules/react-side-effect/.* -.*/node_modules/styled-components/.* -.*/node_modules/typography/.* -.*/www/.* -.*/examples/.* diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000..bee5d7762b2a3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Gatsby Documentation + url: https://www.gatsbyjs.org/docs/ + about: Check out the Gatsby documentation for answers to common questions + - name: Gatsby Discord + url: http://gatsby.dev/discord + about: Ask questions, get help and discuss new things you're building with the Gatsby community + - name: AskGatsbyJS Twitter + url: https://twitter.com/AskGatsbyJS + about: The official Twitter account to ask questions and get help with Gatsby diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 0000000000000..dc0008a390304 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,49 @@ +--- +name: Documentation 📝 +about: Suggest better docs coverage for a particular tool or process. +--- + + + +## Summary + +What problem(s) did you run into that caused you to request additional documentation? What questions do you think we should answer? What, if any, existing documentation relates to this proposal? + +Some recommended topics to cover: + +- List the topics you think should be here. +- This list does not need to be exhaustive! + +### Motivation + +Why should we document this and who will benefit from it? + +## Steps to resolve this issue + + + +### Draft the doc + +- [ ] Write the doc, following the format listed in these resources: + - [Overview on contributing to documentation](https://www.gatsbyjs.org/contributing/docs-contributions/) + - [Docs Templates](https://www.gatsbyjs.org/contributing/docs-templates/) + - [Example of a similar article]() +- [ ] Add the article to the [docs sidebar](https://github.com/gatsbyjs/gatsby/blob/master/www/src/data/sidebars/doc-links.yaml) under the [parent doc] section. + +### Open a pull request + +- [ ] Open a pull request with your work including the words "closes #[this issue's number]" in the pull request description diff --git a/.github/ISSUE_TEMPLATE/new_translation.md b/.github/ISSUE_TEMPLATE/new_translation.md index 91a713d21a9c0..9d1fd4bd444ff 100644 --- a/.github/ISSUE_TEMPLATE/new_translation.md +++ b/.github/ISSUE_TEMPLATE/new_translation.md @@ -9,11 +9,6 @@ about: Suggest a new language translation of the repo. - *Name*: Language name in *English* - *Code*: [ISO-693 Code]() or [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) of the language - *Maintainers*: list of GitHub usernames of proposed maintainers (at least 2 required) - - Each maintainer listed should respond to the issue with: - - - your experience level in open source - - your level of experience in the target language and localization --> ```yaml @@ -23,3 +18,11 @@ maintainers: - tesseralis - marcysutton ``` + +**Maintainers** + +If you would like to be a maintainer, please respond to this issue with: + +- your experience level in open source +- your level of experience in the target language and localization +- how much time you can commit to being a maintainer diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ce14bcd15e6ef..e8e0a602d9152 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -12,6 +12,18 @@ +### Documentation + + + ## Related Issues ` + (step / p10) * 10 + `%`) + let page = template(step) + let where = path.join(root, step + `.md`) + fs.writeFileSync(where, page) +} +console.log(`--> 100%`) +console.timeEnd(`Generated in`) + +console.log(`Should be written to`, path.resolve(root)) diff --git a/benchmarks/markdown_id/md.tpl.js b/benchmarks/markdown_id/md.tpl.js new file mode 100644 index 0000000000000..01c31fc9c5a95 --- /dev/null +++ b/benchmarks/markdown_id/md.tpl.js @@ -0,0 +1,40 @@ +const faker = require(`faker`) +const matter = require(`gray-matter`) + +const MAX_NUM_ROWS = parseInt(process.env.MAX_NUM_ROWS || 25, 10) + +module.exports = index => `${matter + .stringify(``, { + title: faker.lorem.sentence(), + description: faker.lorem.sentence(), + path: `/${faker.helpers.slugify(faker.lorem.sentence())}`, + date: faker.date + .recent(1000) + .toISOString() + .slice(0, 10), + tags: `[${faker.random + .words(3) + .split(` `) + .map(w => `"${w}"`) + .join(`, `)}]`, + }) + .trim()} + +## Page #${index} : ${faker.random.words(4)} + +### API + + +${new Array(faker.random.number(MAX_NUM_ROWS)) + .fill(undefined) + .map(() => + ` +|${faker.lorem.word()}|${faker.lorem.sentence()}|${faker.random.boolean()}| +`.trim() + ) + .join(`\n`)} + +### More Detail + +${faker.lorem.paragraphs()} +` diff --git a/benchmarks/markdown_id/package.json b/benchmarks/markdown_id/package.json new file mode 100644 index 0000000000000..97e761b0c8dc5 --- /dev/null +++ b/benchmarks/markdown_id/package.json @@ -0,0 +1,58 @@ +{ + "name": "gatsby-bench-md-slug", + "private": true, + "description": "A benchmark for building Gatsby with many simple random md files (index by slug)", + "version": "0.0.1", + "author": "PvdZ ", + "dependencies": { + "del-cli": "^3.0.0", + "gatsby": ">=2.1.0", + "gatsby-image": "*", + "gatsby-plugin-feed": "*", + "gatsby-plugin-google-analytics": "*", + "gatsby-plugin-manifest": "*", + "gatsby-plugin-offline": "*", + "gatsby-plugin-react-helmet": "*", + "gatsby-plugin-sharp": "*", + "gatsby-plugin-typography": "*", + "gatsby-remark-copy-linked-files": "*", + "gatsby-remark-images": "*", + "gatsby-remark-prismjs": "*", + "gatsby-remark-responsive-iframe": "*", + "gatsby-remark-smartypants": "*", + "gatsby-source-filesystem": "*", + "gatsby-transformer-remark": "*", + "gatsby-transformer-sharp": "*", + "prismjs": "^1.17.1", + "react": "^16.12.0", + "react-dom": "^16.12.0", + "react-helmet": "^5.2.1", + "react-typography": "^0.16.19", + "typeface-merriweather": "0.0.72", + "typeface-montserrat": "0.0.75", + "typography": "^0.16.19", + "typography-theme-wordpress-2016": "^0.16.19" + }, + "devDependencies": { + "faker": "^4.1.0", + "gatsby-plugin-benchmark-reporting": "*", + "prettier": "^1.19.1" + }, + "keywords": [ + "gatsby" + ], + "license": "MIT", + "main": "n/a", + "scripts": { + "bench": "rm -r markdown-pages; NUM_PAGES=${NUM_PAGES:-2000} node md.generate.js; gatsby clean; node --max_old_space_size=2000 node_modules/.bin/gatsby build", + "benchnb": "gatsby clean; node --max_old_space_size=2000 node_modules/.bin/gatsby build", + "build": "gatsby build", + "develop": "gatsby develop", + "format": "prettier --write \"**/*.{js,jsx,json,md}\"", + "start": "npm run develop", + "serve": "gatsby serve", + "clean": "gatsby clean", + "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1", + "postinstall": "del-cli markdown-pages && gatsby clean && NUM_PAGES=${NUM_PAGES:-2000} node md.generate.js" + } +} diff --git a/benchmarks/markdown_id/src/components/bio.js b/benchmarks/markdown_id/src/components/bio.js new file mode 100644 index 0000000000000..f74b2e8318dc5 --- /dev/null +++ b/benchmarks/markdown_id/src/components/bio.js @@ -0,0 +1,68 @@ +/** + * Bio component that queries for data + * with Gatsby's useStaticQuery component + * + * See: https://www.gatsbyjs.org/docs/use-static-query/ + */ + +import React from "react" +import { useStaticQuery, graphql } from "gatsby" +import Image from "gatsby-image" + +import { rhythm } from "../utils/typography" + +const Bio = () => { + const data = useStaticQuery(graphql` + query BioQuery { + avatar: file(absolutePath: { regex: "/profile-pic.jpg/" }) { + childImageSharp { + fixed(width: 50, height: 50) { + ...GatsbyImageSharpFixed + } + } + } + site { + siteMetadata { + author + social { + twitter + } + } + } + } + `) + + const { author, social } = data.site.siteMetadata + return ( +
+ {author} +

+ Written by {author} who lives and works in Fan + Srancisco building useful things. + {` `} + + You should follow him on Twitter + +

+
+ ) +} + +export default Bio diff --git a/benchmarks/markdown_id/src/components/layout.js b/benchmarks/markdown_id/src/components/layout.js new file mode 100644 index 0000000000000..5a44c9cacfed2 --- /dev/null +++ b/benchmarks/markdown_id/src/components/layout.js @@ -0,0 +1,75 @@ +import React from "react" +import { Link } from "gatsby" + +import { rhythm, scale } from "../utils/typography" + +class Layout extends React.Component { + render() { + const { location, title, children } = this.props + const rootPath = `${__PATH_PREFIX__}/` + let header + + if (location.pathname === rootPath) { + header = ( +

+ + {title} + +

+ ) + } else { + header = ( +

+ + {title} + +

+ ) + } + return ( +
+
{header}
+
{children}
+
+ © {new Date().getFullYear()}, Built with + {` `} + Gatsby +
+
+ ) + } +} + +export default Layout diff --git a/benchmarks/markdown_id/src/components/seo.js b/benchmarks/markdown_id/src/components/seo.js new file mode 100644 index 0000000000000..e15f59958a3c0 --- /dev/null +++ b/benchmarks/markdown_id/src/components/seo.js @@ -0,0 +1,88 @@ +/** + * SEO component that queries for data with + * Gatsby's useStaticQuery React hook + * + * See: https://www.gatsbyjs.org/docs/use-static-query/ + */ + +import React from "react" +import PropTypes from "prop-types" +import Helmet from "react-helmet" +import { useStaticQuery, graphql } from "gatsby" + +function SEO({ description, lang, meta, title }) { + const { site } = useStaticQuery( + graphql` + query { + site { + siteMetadata { + title + description + author + } + } + } + ` + ) + + const metaDescription = description || site.siteMetadata.description + + return ( + + ) +} + +SEO.defaultProps = { + lang: `en`, + meta: [], + description: ``, +} + +SEO.propTypes = { + description: PropTypes.string, + lang: PropTypes.string, + meta: PropTypes.arrayOf(PropTypes.object), + title: PropTypes.string.isRequired, +} + +export default SEO diff --git a/benchmarks/markdown_id/src/pages/404.js b/benchmarks/markdown_id/src/pages/404.js new file mode 100644 index 0000000000000..008a76b97d146 --- /dev/null +++ b/benchmarks/markdown_id/src/pages/404.js @@ -0,0 +1,32 @@ +import React from "react" +import { graphql } from "gatsby" + +import Layout from "../components/layout" +import SEO from "../components/seo" + +class NotFoundPage extends React.Component { + render() { + const { data } = this.props + const siteTitle = data.site.siteMetadata.title + + return ( + + +

Not Found

+

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

+
+ ) + } +} + +export default NotFoundPage + +export const pageQuery = graphql` + query { + site { + siteMetadata { + title + } + } + } +` diff --git a/benchmarks/markdown_id/src/pages/index.js b/benchmarks/markdown_id/src/pages/index.js new file mode 100644 index 0000000000000..2dd45eb6e060f --- /dev/null +++ b/benchmarks/markdown_id/src/pages/index.js @@ -0,0 +1,75 @@ +import React from "react" +import { Link, graphql } from "gatsby" + +import Bio from "../components/bio" +import Layout from "../components/layout" +import SEO from "../components/seo" +import { rhythm } from "../utils/typography" + +class BlogIndex extends React.Component { + render() { + const { data } = this.props + const siteTitle = data.site.siteMetadata.title + const posts = data.allMarkdownRemark.edges + + return ( + + + + {posts.map(({ node }) => { + const title = node.frontmatter.title || node.fields.slug + return ( +
+
+

+ + {title} + +

+ {node.frontmatter.date} +
+
+

+

+
+ ) + })} +
+ ) + } +} + +export default BlogIndex + +export const pageQuery = graphql` + query { + site { + siteMetadata { + title + } + } + allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { + edges { + node { + excerpt + fields { + slug + } + frontmatter { + date(formatString: "MMMM DD, YYYY") + title + description + } + } + } + } + } +` diff --git a/benchmarks/markdown_id/src/templates/blog-post.js b/benchmarks/markdown_id/src/templates/blog-post.js new file mode 100644 index 0000000000000..f57d6aa77d807 --- /dev/null +++ b/benchmarks/markdown_id/src/templates/blog-post.js @@ -0,0 +1,103 @@ +import React from "react" +import { Link, graphql } from "gatsby" + +import Bio from "../components/bio" +import Layout from "../components/layout" +import SEO from "../components/seo" +import { rhythm, scale } from "../utils/typography" + +class BlogPostTemplate extends React.Component { + render() { + const post = this.props.data.markdownRemark + const siteTitle = this.props.data.site.siteMetadata.title + const { previous, next } = this.props.pageContext + + return ( + + +
+
+

+ {post.frontmatter.title} +

+

+ {post.frontmatter.date} +

+
+
+
+
+ +
+
+ + +
+ ) + } +} + +export default BlogPostTemplate + +export const pageQuery = graphql` + query BlogPostById($id: String!) { + site { + siteMetadata { + title + } + } + markdownRemark(id: { eq: $id }) { + id + excerpt(pruneLength: 160) + html + frontmatter { + title + date(formatString: "MMMM DD, YYYY") + description + } + } + } +` diff --git a/benchmarks/markdown_id/src/utils/typography.js b/benchmarks/markdown_id/src/utils/typography.js new file mode 100644 index 0000000000000..428720b98d131 --- /dev/null +++ b/benchmarks/markdown_id/src/utils/typography.js @@ -0,0 +1,23 @@ +import Typography from "typography" +import Wordpress2016 from "typography-theme-wordpress-2016" + +Wordpress2016.overrideThemeStyles = () => { + return { + "a.gatsby-resp-image-link": { + boxShadow: `none`, + }, + } +} + +delete Wordpress2016.googleFonts + +const typography = new Typography(Wordpress2016) + +// Hot reload typography in development. +if (process.env.NODE_ENV !== `production`) { + typography.injectStyles() +} + +export default typography +export const rhythm = typography.rhythm +export const scale = typography.scale diff --git a/benchmarks/markdown_id/static/favicon.ico b/benchmarks/markdown_id/static/favicon.ico new file mode 100644 index 0000000000000..85a4d9fac03ba Binary files /dev/null and b/benchmarks/markdown_id/static/favicon.ico differ diff --git a/benchmarks/markdown_id/static/robots.txt b/benchmarks/markdown_id/static/robots.txt new file mode 100644 index 0000000000000..eb0536286f308 --- /dev/null +++ b/benchmarks/markdown_id/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/benchmarks/markdown_slug/.gitignore b/benchmarks/markdown_slug/.gitignore new file mode 100644 index 0000000000000..7d861de1f73b2 --- /dev/null +++ b/benchmarks/markdown_slug/.gitignore @@ -0,0 +1,71 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# dotenv environment variable files +.env* + +# gatsby files +.cache/ +public + +# Mac files +.DS_Store + +# Yarn +yarn-error.log +.pnp/ +.pnp.js +# Yarn Integrity file +.yarn-integrity + +markdown-pages diff --git a/benchmarks/markdown_slug/.prettierignore b/benchmarks/markdown_slug/.prettierignore new file mode 100644 index 0000000000000..58d06c368a2ae --- /dev/null +++ b/benchmarks/markdown_slug/.prettierignore @@ -0,0 +1,4 @@ +.cache +package.json +package-lock.json +public diff --git a/benchmarks/markdown_slug/.prettierrc b/benchmarks/markdown_slug/.prettierrc new file mode 100644 index 0000000000000..48e90e8d4025f --- /dev/null +++ b/benchmarks/markdown_slug/.prettierrc @@ -0,0 +1,7 @@ +{ + "endOfLine": "lf", + "semi": false, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5" +} diff --git a/benchmarks/markdown_slug/LICENSE b/benchmarks/markdown_slug/LICENSE new file mode 100644 index 0000000000000..1180a1cf3bdb6 --- /dev/null +++ b/benchmarks/markdown_slug/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Gatsbyjs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/benchmarks/markdown_slug/README.md b/benchmarks/markdown_slug/README.md new file mode 100644 index 0000000000000..31a9e7354945c --- /dev/null +++ b/benchmarks/markdown_slug/README.md @@ -0,0 +1,34 @@ +# Markdown Benchmark Index = slug + +This benchmark first generates a number of randomly generated md pages (configure the number by setting `NUM_PAGES=400`) and then it builds. + +The base for this site is `gatsby-starter-blog`. + +This particular markdown benchmark will query pages by their `slug`, which is (at the time of writing) slower than indexing pages by their `id`. + +The pre-generate script stores pages in root/markdown-pages. + +## Usage + +``` +yarn +yarn bench +``` + +If you want to run the same pages without regenerating them you can use `yarn benchnb`. It's fine to use `gatsby clean` regardless. + +### Detailed steps + +Use `yarn` to install if you want to use `gatsby-dev`. Otherwise I don't think it matters between `yarn` or `npm install`. + +```sh +# Requires node 8+ +# nvm use 8 +yarn +rm -r markdown-pages +NUM_PAGES=2000 node md.generate.js +gatsby clean +node --max_old_space_size=2000 node_modules/.bin/gatsby build +``` + +The last step could also just be `gatsby build` if the number of pages is small enough. The example will increase the maximum reserved "old object space" which you'll need for a larger number of pages. diff --git a/benchmarks/markdown_slug/content/assets/gatsby-icon.png b/benchmarks/markdown_slug/content/assets/gatsby-icon.png new file mode 100644 index 0000000000000..908bc78a7f559 Binary files /dev/null and b/benchmarks/markdown_slug/content/assets/gatsby-icon.png differ diff --git a/benchmarks/markdown_slug/content/assets/profile-pic.jpg b/benchmarks/markdown_slug/content/assets/profile-pic.jpg new file mode 100644 index 0000000000000..ac18e71910187 Binary files /dev/null and b/benchmarks/markdown_slug/content/assets/profile-pic.jpg differ diff --git a/benchmarks/markdown_slug/content/blog/hello-world/index.md b/benchmarks/markdown_slug/content/blog/hello-world/index.md new file mode 100644 index 0000000000000..0dc2e0b77d18a --- /dev/null +++ b/benchmarks/markdown_slug/content/blog/hello-world/index.md @@ -0,0 +1,22 @@ +--- +title: Hello World +date: "2015-05-01T22:12:03.284Z" +description: "Hello World" +--- + +This is my first post on my new fake blog! How exciting! + +I'm sure I'll write a lot more interesting things in the future. + +Oh, and here's a great quote from this Wikipedia on +[salted duck eggs](http://en.wikipedia.org/wiki/Salted_duck_egg). + +> A salted duck egg is a Chinese preserved food product made by soaking duck +> eggs in brine, or packing each egg in damp, salted charcoal. In Asian +> supermarkets, these eggs are sometimes sold covered in a thick layer of salted +> charcoal paste. The eggs may also be sold with the salted paste removed, +> wrapped in plastic, and vacuum packed. From the salt curing process, the +> salted duck eggs have a briny aroma, a gelatin-like egg white and a +> firm-textured, round yolk that is bright orange-red in color. + +![Chinese Salty Egg](./salty_egg.jpg) diff --git a/benchmarks/markdown_slug/content/blog/hello-world/salty_egg.jpg b/benchmarks/markdown_slug/content/blog/hello-world/salty_egg.jpg new file mode 100644 index 0000000000000..653fe7e89114a Binary files /dev/null and b/benchmarks/markdown_slug/content/blog/hello-world/salty_egg.jpg differ diff --git a/benchmarks/markdown_slug/content/blog/my-second-post/index.md b/benchmarks/markdown_slug/content/blog/my-second-post/index.md new file mode 100644 index 0000000000000..d19e92dc87f6d --- /dev/null +++ b/benchmarks/markdown_slug/content/blog/my-second-post/index.md @@ -0,0 +1,13 @@ +--- +title: My Second Post! +date: "2015-05-06T23:46:37.121Z" +--- + +Wow! I love blogging so much already. + +Did you know that "despite its name, salted duck eggs can also be made from +chicken eggs, though the taste and texture will be somewhat different, and the +egg yolk will be less rich."? +([Wikipedia Link](http://en.wikipedia.org/wiki/Salted_duck_egg)) + +Yeah, I didn't either. diff --git a/benchmarks/markdown_slug/content/blog/new-beginnings/index.md b/benchmarks/markdown_slug/content/blog/new-beginnings/index.md new file mode 100644 index 0000000000000..86012ecc57538 --- /dev/null +++ b/benchmarks/markdown_slug/content/blog/new-beginnings/index.md @@ -0,0 +1,108 @@ +--- +title: New Beginnings +date: "2015-05-28T22:40:32.169Z" +description: This is a custom description for SEO and Open Graph purposes, rather than the default generated excerpt. Simply add a description field to the frontmatter. +--- + +Far far away, behind the word mountains, far from the countries Vokalia and +Consonantia, there live the blind texts. Separated they live in Bookmarksgrove +right at the coast of the Semantics, a large language ocean. A small river named +Duden flows by their place and supplies it with the necessary regelialia. + +## On deer horse aboard tritely yikes and much + +The Big Oxmox advised her not to do so, because there were thousands of bad +Commas, wild Question Marks and devious Semikoli, but the Little Blind Text +didn’t listen. She packed her seven versalia, put her initial into the belt and +made herself on the way. + +- This however showed weasel +- Well uncritical so misled + - this is very interesting +- Goodness much until that fluid owl + +When she reached the first hills of the **Italic Mountains**, she had a last +view back on the skyline of her hometown _Bookmarksgrove_, the headline of +[Alphabet Village](http://google.com) and the subline of her own road, the Line +Lane. Pityful a rhetoric question ran over her cheek, then she continued her +way. On her way she met a copy. + +### Overlaid the jeepers uselessly much excluding + +But nothing the copy said could convince her and so it didn’t take long until a +few insidious Copy Writers ambushed her, made her drunk with +[Longe and Parole](http://google.com) and dragged her into their agency, where +they abused her for their projects again and again. And if she hasn’t been +rewritten, then they are still using her. + +> Far far away, behind the word mountains, far from the countries Vokalia and +> Consonantia, there live the blind texts. Separated they live in Bookmarksgrove +> right at the coast of the Semantics, a large language ocean. + +It is a paradisematic country, in which roasted parts of sentences fly into your +mouth. Even the all-powerful Pointing has no control about the blind texts it is +an almost unorthographic life One day however a small line of blind text by the +name of Lorem Ipsum decided to leave for the far World of Grammar. + +### According a funnily until pre-set or arrogant well cheerful + +The Big Oxmox advised her not to do so, because there were thousands of bad +Commas, wild Question Marks and devious Semikoli, but the Little Blind Text +didn’t listen. She packed her seven versalia, put her initial into the belt and +made herself on the way. + +1. So baboon this +2. Mounted militant weasel gregariously admonishingly straightly hey +3. Dear foresaw hungry and much some overhung +4. Rash opossum less because less some amid besides yikes jeepers frenetic + impassive fruitlessly shut + +When she reached the first hills of the Italic Mountains, she had a last view +back on the skyline of her hometown Bookmarksgrove, the headline of Alphabet +Village and the subline of her own road, the Line Lane. Pityful a rhetoric +question ran over her cheek, then she continued her way. On her way she met a +copy. + +> The copy warned the Little Blind Text, that where it came from it would have +> been rewritten a thousand times and everything that was left from its origin +> would be the word "and" and the Little Blind Text should turn around and +> return to its own, safe country. + +But nothing the copy said could convince her and so it didn’t take long until a +few insidious Copy Writers ambushed her, made her drunk with Longe and Parole +and dragged her into their agency, where they abused her for their projects +again and again. And if she hasn’t been rewritten, then they are still using +her. Far far away, behind the word mountains, far from the countries Vokalia and +Consonantia, there live the blind texts. + +#### Silent delightfully including because before one up barring chameleon + +Separated they live in Bookmarksgrove right at the coast of the Semantics, a +large language ocean. A small river named Duden flows by their place and +supplies it with the necessary regelialia. It is a paradisematic country, in +which roasted parts of sentences fly into your mouth. + +Even the all-powerful Pointing has no control about the blind texts it is an +almost unorthographic life One day however a small line of blind text by the +name of Lorem Ipsum decided to leave for the far World of Grammar. The Big Oxmox +advised her not to do so, because there were thousands of bad Commas, wild +Question Marks and devious Semikoli, but the Little Blind Text didn’t listen. + +##### Wherever far wow thus a squirrel raccoon jeez jaguar this from along + +She packed her seven versalia, put her initial into the belt and made herself on +the way. When she reached the first hills of the Italic Mountains, she had a +last view back on the skyline of her hometown Bookmarksgrove, the headline of +Alphabet Village and the subline of her own road, the Line Lane. Pityful a +rhetoric question ran over her cheek, then she continued her way. On her way she +met a copy. + +###### Slapped cozy a that lightheartedly and far + +The copy warned the Little Blind Text, that where it came from it would have +been rewritten a thousand times and everything that was left from its origin +would be the word "and" and the Little Blind Text should turn around and return +to its own, safe country. But nothing the copy said could convince her and so it +didn’t take long until a few insidious Copy Writers ambushed her, made her drunk +with Longe and Parole and dragged her into their agency, where they abused her +for their projects again and again. diff --git a/benchmarks/markdown_slug/gatsby-browser.js b/benchmarks/markdown_slug/gatsby-browser.js new file mode 100644 index 0000000000000..466e18ad0d1f1 --- /dev/null +++ b/benchmarks/markdown_slug/gatsby-browser.js @@ -0,0 +1,3 @@ +// custom typefaces +import "typeface-montserrat" +import "typeface-merriweather" diff --git a/benchmarks/markdown_slug/gatsby-config.js b/benchmarks/markdown_slug/gatsby-config.js new file mode 100644 index 0000000000000..c380d4d0c2f40 --- /dev/null +++ b/benchmarks/markdown_slug/gatsby-config.js @@ -0,0 +1,78 @@ +module.exports = { + siteMetadata: { + title: `Gatsby MD Benchmark Blog`, + author: `Myle Kathews`, + description: `The MD starter blog turned into a benchmark`, + siteUrl: `https://gatsby-starter-blog-demo.netlify.com/`, + social: { + twitter: `gatsbyjs`, + }, + }, + plugins: [ + `gatsby-plugin-benchmark-reporting`, + { + resolve: `gatsby-source-filesystem`, + options: { + path: `${__dirname}/markdown-pages`, + name: `blog`, + }, + }, + { + resolve: `gatsby-source-filesystem`, + options: { + path: `${__dirname}/content/assets`, + name: `assets`, + }, + }, + { + resolve: `gatsby-transformer-remark`, + options: { + plugins: [ + { + resolve: `gatsby-remark-images`, + options: { + maxWidth: 590, + }, + }, + { + resolve: `gatsby-remark-responsive-iframe`, + options: { + wrapperStyle: `margin-bottom: 1.0725rem`, + }, + }, + `gatsby-remark-prismjs`, + `gatsby-remark-copy-linked-files`, + `gatsby-remark-smartypants`, + ], + }, + }, + `gatsby-transformer-sharp`, + `gatsby-plugin-sharp`, + { + resolve: `gatsby-plugin-google-analytics`, + options: { + trackingId: `do-not-track`, + }, + }, + { + resolve: `gatsby-plugin-manifest`, + options: { + name: `Gatsby Starter Blog`, + short_name: `GatsbyJS`, + start_url: `/rss`, + background_color: `#ffffff`, + theme_color: `#663399`, + display: `minimal-ui`, + icon: `content/assets/gatsby-icon.png`, + }, + }, + `gatsby-plugin-offline`, + `gatsby-plugin-react-helmet`, + { + resolve: `gatsby-plugin-typography`, + options: { + pathToConfigModule: `src/utils/typography`, + }, + }, + ], +} diff --git a/benchmarks/markdown_slug/gatsby-node.js b/benchmarks/markdown_slug/gatsby-node.js new file mode 100644 index 0000000000000..8c980141d3a5b --- /dev/null +++ b/benchmarks/markdown_slug/gatsby-node.js @@ -0,0 +1,61 @@ +const path = require(`path`) +const { createFilePath } = require(`gatsby-source-filesystem`) + +exports.createPages = async ({ graphql, actions }) => { + const { createPage } = actions + + const blogPost = path.resolve(`./src/templates/blog-post.js`) + const result = await graphql( + ` + { + allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { + edges { + node { + fields { + slug + } + frontmatter { + title + } + } + } + } + } + ` + ) + + if (result.errors) { + throw result.errors + } + + // Create blog posts pages. + const posts = result.data.allMarkdownRemark.edges + + posts.forEach((post, index) => { + const previous = index === posts.length - 1 ? null : posts[index + 1].node + const next = index === 0 ? null : posts[index - 1].node + + createPage({ + path: post.node.fields.slug, + component: blogPost, + context: { + slug: post.node.fields.slug, + previous, + next, + }, + }) + }) +} + +exports.onCreateNode = ({ node, actions, getNode }) => { + const { createNodeField } = actions + + if (node.internal.type === `MarkdownRemark`) { + const value = createFilePath({ node, getNode }) + createNodeField({ + name: `slug`, + node, + value, + }) + } +} diff --git a/benchmarks/markdown_slug/md.generate.js b/benchmarks/markdown_slug/md.generate.js new file mode 100644 index 0000000000000..1b460ed072851 --- /dev/null +++ b/benchmarks/markdown_slug/md.generate.js @@ -0,0 +1,60 @@ +const fs = require(`fs`) +const path = require(`path`) + +const template = require(`./md.tpl.js`) + +const root = `markdown-pages` + +const MAX_NUM_ROWS = parseInt(process.env.MAX_NUM_ROWS || 25, 10) +if ( + typeof MAX_NUM_ROWS !== `number` || + !Number.isInteger(MAX_NUM_ROWS) || + MAX_NUM_ROWS <= 0 +) { + throw new Error( + `Error: the valeue for MAX_NUM_ROWS is invalid: \`` + + process.env.MAX_NUM_ROWS + + `\`` + ) +} +const NUM_PAGES = parseInt(process.env.NUM_PAGES || 1000) +if ( + typeof NUM_PAGES !== `number` || + !Number.isInteger(NUM_PAGES) || + NUM_PAGES <= 0 +) { + throw new Error( + `Error: the valeue for MAX_NUM_ROWS is invalid: \`` + + process.env.NUM_PAGES + + `\`` + ) +} + +console.log( + `Generating`, + NUM_PAGES, + `pseudo random md files in`, + path.resolve(root) +) +if (!process.env.NUM_PAGES || process.env.NUM_PAGES === `2000`) { + console.log(` Set \`NUM_PAGES=200\` to change the volume`) +} + +if (!fs.existsSync(root)) { + fs.mkdirSync(root, { recursive: true }) +} + +console.time(`Generated in`) +// Create markdown nodes +let p10 = Math.round(NUM_PAGES / 10) +for (let step = 0; step < NUM_PAGES; step++) { + if (step > 0 && step % p10 === 0) + console.log(`--> ` + (step / p10) * 10 + `%`) + let page = template(step) + let where = path.join(root, step + `.md`) + fs.writeFileSync(where, page) +} +console.log(`--> 100%`) +console.timeEnd(`Generated in`) + +console.log(`Should be written to`, path.resolve(root)) diff --git a/benchmarks/markdown_slug/md.tpl.js b/benchmarks/markdown_slug/md.tpl.js new file mode 100644 index 0000000000000..01c31fc9c5a95 --- /dev/null +++ b/benchmarks/markdown_slug/md.tpl.js @@ -0,0 +1,40 @@ +const faker = require(`faker`) +const matter = require(`gray-matter`) + +const MAX_NUM_ROWS = parseInt(process.env.MAX_NUM_ROWS || 25, 10) + +module.exports = index => `${matter + .stringify(``, { + title: faker.lorem.sentence(), + description: faker.lorem.sentence(), + path: `/${faker.helpers.slugify(faker.lorem.sentence())}`, + date: faker.date + .recent(1000) + .toISOString() + .slice(0, 10), + tags: `[${faker.random + .words(3) + .split(` `) + .map(w => `"${w}"`) + .join(`, `)}]`, + }) + .trim()} + +## Page #${index} : ${faker.random.words(4)} + +### API + + +${new Array(faker.random.number(MAX_NUM_ROWS)) + .fill(undefined) + .map(() => + ` +|${faker.lorem.word()}|${faker.lorem.sentence()}|${faker.random.boolean()}| +`.trim() + ) + .join(`\n`)} + +### More Detail + +${faker.lorem.paragraphs()} +` diff --git a/benchmarks/markdown_slug/package.json b/benchmarks/markdown_slug/package.json new file mode 100644 index 0000000000000..51af7d8993385 --- /dev/null +++ b/benchmarks/markdown_slug/package.json @@ -0,0 +1,58 @@ +{ + "name": "gatsby-starter-blog", + "private": true, + "description": "A benchmark for building Gatsby with many simple random md files (index by slug)", + "version": "0.0.1", + "author": "PvdZ ", + "dependencies": { + "del-cli": "^3.0.0", + "gatsby": ">=2.1.0", + "gatsby-image": "*", + "gatsby-plugin-feed": "*", + "gatsby-plugin-google-analytics": "*", + "gatsby-plugin-manifest": "*", + "gatsby-plugin-offline": "*", + "gatsby-plugin-react-helmet": "*", + "gatsby-plugin-sharp": "*", + "gatsby-plugin-typography": "*", + "gatsby-remark-copy-linked-files": "*", + "gatsby-remark-images": "*", + "gatsby-remark-prismjs": "*", + "gatsby-remark-responsive-iframe": "*", + "gatsby-remark-smartypants": "*", + "gatsby-source-filesystem": "*", + "gatsby-transformer-remark": "*", + "gatsby-transformer-sharp": "*", + "prismjs": "^1.17.1", + "react": "^16.12.0", + "react-dom": "^16.12.0", + "react-helmet": "^5.2.1", + "react-typography": "^0.16.19", + "typeface-merriweather": "0.0.72", + "typeface-montserrat": "0.0.75", + "typography": "^0.16.19", + "typography-theme-wordpress-2016": "^0.16.19" + }, + "devDependencies": { + "faker": "^4.1.0", + "gatsby-plugin-benchmark-reporting": "*", + "prettier": "^1.19.1" + }, + "keywords": [ + "gatsby" + ], + "license": "MIT", + "main": "n/a", + "scripts": { + "bench": "rm -r markdown-pages; NUM_PAGES=${NUM_PAGES:-2000} node md.generate.js; gatsby clean; node --max_old_space_size=2000 node_modules/.bin/gatsby build", + "benchnb": "gatsby clean; node --max_old_space_size=2000 node_modules/.bin/gatsby build", + "build": "gatsby build", + "develop": "gatsby develop", + "format": "prettier --write \"**/*.{js,jsx,json,md}\"", + "start": "npm run develop", + "serve": "gatsby serve", + "clean": "gatsby clean", + "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1", + "postinstall": "del-cli markdown-pages && gatsby clean && NUM_PAGES=${NUM_PAGES:-2000} node md.generate.js" + } +} diff --git a/benchmarks/markdown_slug/src/components/bio.js b/benchmarks/markdown_slug/src/components/bio.js new file mode 100644 index 0000000000000..f74b2e8318dc5 --- /dev/null +++ b/benchmarks/markdown_slug/src/components/bio.js @@ -0,0 +1,68 @@ +/** + * Bio component that queries for data + * with Gatsby's useStaticQuery component + * + * See: https://www.gatsbyjs.org/docs/use-static-query/ + */ + +import React from "react" +import { useStaticQuery, graphql } from "gatsby" +import Image from "gatsby-image" + +import { rhythm } from "../utils/typography" + +const Bio = () => { + const data = useStaticQuery(graphql` + query BioQuery { + avatar: file(absolutePath: { regex: "/profile-pic.jpg/" }) { + childImageSharp { + fixed(width: 50, height: 50) { + ...GatsbyImageSharpFixed + } + } + } + site { + siteMetadata { + author + social { + twitter + } + } + } + } + `) + + const { author, social } = data.site.siteMetadata + return ( +
+ {author} +

+ Written by {author} who lives and works in Fan + Srancisco building useful things. + {` `} + + You should follow him on Twitter + +

+
+ ) +} + +export default Bio diff --git a/benchmarks/markdown_slug/src/components/layout.js b/benchmarks/markdown_slug/src/components/layout.js new file mode 100644 index 0000000000000..5a44c9cacfed2 --- /dev/null +++ b/benchmarks/markdown_slug/src/components/layout.js @@ -0,0 +1,75 @@ +import React from "react" +import { Link } from "gatsby" + +import { rhythm, scale } from "../utils/typography" + +class Layout extends React.Component { + render() { + const { location, title, children } = this.props + const rootPath = `${__PATH_PREFIX__}/` + let header + + if (location.pathname === rootPath) { + header = ( +

+ + {title} + +

+ ) + } else { + header = ( +

+ + {title} + +

+ ) + } + return ( +
+
{header}
+
{children}
+
+ © {new Date().getFullYear()}, Built with + {` `} + Gatsby +
+
+ ) + } +} + +export default Layout diff --git a/benchmarks/markdown_slug/src/components/seo.js b/benchmarks/markdown_slug/src/components/seo.js new file mode 100644 index 0000000000000..e15f59958a3c0 --- /dev/null +++ b/benchmarks/markdown_slug/src/components/seo.js @@ -0,0 +1,88 @@ +/** + * SEO component that queries for data with + * Gatsby's useStaticQuery React hook + * + * See: https://www.gatsbyjs.org/docs/use-static-query/ + */ + +import React from "react" +import PropTypes from "prop-types" +import Helmet from "react-helmet" +import { useStaticQuery, graphql } from "gatsby" + +function SEO({ description, lang, meta, title }) { + const { site } = useStaticQuery( + graphql` + query { + site { + siteMetadata { + title + description + author + } + } + } + ` + ) + + const metaDescription = description || site.siteMetadata.description + + return ( + + ) +} + +SEO.defaultProps = { + lang: `en`, + meta: [], + description: ``, +} + +SEO.propTypes = { + description: PropTypes.string, + lang: PropTypes.string, + meta: PropTypes.arrayOf(PropTypes.object), + title: PropTypes.string.isRequired, +} + +export default SEO diff --git a/benchmarks/markdown_slug/src/pages/404.js b/benchmarks/markdown_slug/src/pages/404.js new file mode 100644 index 0000000000000..008a76b97d146 --- /dev/null +++ b/benchmarks/markdown_slug/src/pages/404.js @@ -0,0 +1,32 @@ +import React from "react" +import { graphql } from "gatsby" + +import Layout from "../components/layout" +import SEO from "../components/seo" + +class NotFoundPage extends React.Component { + render() { + const { data } = this.props + const siteTitle = data.site.siteMetadata.title + + return ( + + +

Not Found

+

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

+
+ ) + } +} + +export default NotFoundPage + +export const pageQuery = graphql` + query { + site { + siteMetadata { + title + } + } + } +` diff --git a/benchmarks/markdown_slug/src/pages/index.js b/benchmarks/markdown_slug/src/pages/index.js new file mode 100644 index 0000000000000..2dd45eb6e060f --- /dev/null +++ b/benchmarks/markdown_slug/src/pages/index.js @@ -0,0 +1,75 @@ +import React from "react" +import { Link, graphql } from "gatsby" + +import Bio from "../components/bio" +import Layout from "../components/layout" +import SEO from "../components/seo" +import { rhythm } from "../utils/typography" + +class BlogIndex extends React.Component { + render() { + const { data } = this.props + const siteTitle = data.site.siteMetadata.title + const posts = data.allMarkdownRemark.edges + + return ( + + + + {posts.map(({ node }) => { + const title = node.frontmatter.title || node.fields.slug + return ( +
+
+

+ + {title} + +

+ {node.frontmatter.date} +
+
+

+

+
+ ) + })} +
+ ) + } +} + +export default BlogIndex + +export const pageQuery = graphql` + query { + site { + siteMetadata { + title + } + } + allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { + edges { + node { + excerpt + fields { + slug + } + frontmatter { + date(formatString: "MMMM DD, YYYY") + title + description + } + } + } + } + } +` diff --git a/benchmarks/markdown_slug/src/templates/blog-post.js b/benchmarks/markdown_slug/src/templates/blog-post.js new file mode 100644 index 0000000000000..1bbf39bbe0c92 --- /dev/null +++ b/benchmarks/markdown_slug/src/templates/blog-post.js @@ -0,0 +1,103 @@ +import React from "react" +import { Link, graphql } from "gatsby" + +import Bio from "../components/bio" +import Layout from "../components/layout" +import SEO from "../components/seo" +import { rhythm, scale } from "../utils/typography" + +class BlogPostTemplate extends React.Component { + render() { + const post = this.props.data.markdownRemark + const siteTitle = this.props.data.site.siteMetadata.title + const { previous, next } = this.props.pageContext + + return ( + + +
+
+

+ {post.frontmatter.title} +

+

+ {post.frontmatter.date} +

+
+
+
+
+ +
+
+ + +
+ ) + } +} + +export default BlogPostTemplate + +export const pageQuery = graphql` + query BlogPostBySlug($slug: String!) { + site { + siteMetadata { + title + } + } + markdownRemark(fields: { slug: { eq: $slug } }) { + id + excerpt(pruneLength: 160) + html + frontmatter { + title + date(formatString: "MMMM DD, YYYY") + description + } + } + } +` diff --git a/benchmarks/markdown_slug/src/utils/typography.js b/benchmarks/markdown_slug/src/utils/typography.js new file mode 100644 index 0000000000000..428720b98d131 --- /dev/null +++ b/benchmarks/markdown_slug/src/utils/typography.js @@ -0,0 +1,23 @@ +import Typography from "typography" +import Wordpress2016 from "typography-theme-wordpress-2016" + +Wordpress2016.overrideThemeStyles = () => { + return { + "a.gatsby-resp-image-link": { + boxShadow: `none`, + }, + } +} + +delete Wordpress2016.googleFonts + +const typography = new Typography(Wordpress2016) + +// Hot reload typography in development. +if (process.env.NODE_ENV !== `production`) { + typography.injectStyles() +} + +export default typography +export const rhythm = typography.rhythm +export const scale = typography.scale diff --git a/benchmarks/markdown_slug/static/favicon.ico b/benchmarks/markdown_slug/static/favicon.ico new file mode 100644 index 0000000000000..85a4d9fac03ba Binary files /dev/null and b/benchmarks/markdown_slug/static/favicon.ico differ diff --git a/benchmarks/markdown_slug/static/robots.txt b/benchmarks/markdown_slug/static/robots.txt new file mode 100644 index 0000000000000..eb0536286f308 --- /dev/null +++ b/benchmarks/markdown_slug/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/benchmarks/markdown/.gitignore b/benchmarks/markdown_table/.gitignore similarity index 100% rename from benchmarks/markdown/.gitignore rename to benchmarks/markdown_table/.gitignore diff --git a/benchmarks/markdown/LICENSE b/benchmarks/markdown_table/LICENSE similarity index 100% rename from benchmarks/markdown/LICENSE rename to benchmarks/markdown_table/LICENSE diff --git a/benchmarks/markdown_table/README.md b/benchmarks/markdown_table/README.md new file mode 100644 index 0000000000000..ad45ae8592938 --- /dev/null +++ b/benchmarks/markdown_table/README.md @@ -0,0 +1,30 @@ +## Markdown Table Benchmark + +This benchmark was originally created to benchmark Gatsby's node creation and query running by creating lots of pages rendered from Markdown. + +However, it generates the pages as part of the test, which adds overhead and skews timing (warms up node / memory). + +Additionally it was leaning heavily on the markdown plugin because the tables were taking a lot of time to process. And it was indexing by `slug`, rather than `id`. + +For a more representative benchmark, based on this one, see the `markdown-slug` and `markdown-id` sites in the parent benchmark folder. They do the same as this site, without the tables, and one indexes by `slug` and the other by `id`. + +Keeping this benchmark for historical reasons but would suggest to pick one of the other markdown benchmarks. + +## Usage + +Defaults to building a site with 5k markdown pages and 25 maximum rows per age. Set the `NUM_PAGES` and `MAX_NUM_ROWS` environment variables to change that e.g. `NUM_PAGES=25000 MAX_NUM_ROWS=100 gatsby build` + +## Running the benchmark + +First, install node modules required by package.json. This is needed only one time. Then run the build + +```bash +yarn +yarn build +``` + +Alternatively + +```sh +yarn bench +``` diff --git a/benchmarks/markdown_table/gatsby-config.js b/benchmarks/markdown_table/gatsby-config.js new file mode 100644 index 0000000000000..b03519749226f --- /dev/null +++ b/benchmarks/markdown_table/gatsby-config.js @@ -0,0 +1,3 @@ +module.exports = { + plugins: [`gatsby-plugin-benchmark-reporting`, `gatsby-transformer-remark`], +} diff --git a/benchmarks/markdown/gatsby-node.js b/benchmarks/markdown_table/gatsby-node.js similarity index 100% rename from benchmarks/markdown/gatsby-node.js rename to benchmarks/markdown_table/gatsby-node.js diff --git a/benchmarks/markdown/package.json b/benchmarks/markdown_table/package.json similarity index 65% rename from benchmarks/markdown/package.json rename to benchmarks/markdown_table/package.json index 261edadf90144..5750502e9fa55 100644 --- a/benchmarks/markdown/package.json +++ b/benchmarks/markdown_table/package.json @@ -3,18 +3,20 @@ "description": "Gatsby hello world starter", "license": "MIT", "scripts": { + "bench": "set -x; gatsby clean; NUM_PAGES=${NUM_PAGES:-2000} gatsby build", "develop": "gatsby develop", "build": "gatsby build", "serve": "gatsby serve" }, "dependencies": { - "gatsby": "^2.0.118", - "gatsby-transformer-remark": "^2.2.4", + "gatsby": "^2.18.25", + "gatsby-transformer-remark": "^2.6.48", "react": "^16.8.0", "react-dom": "^16.8.0" }, "devDependencies": { "faker": "^4.1.0", + "gatsby-plugin-benchmark-reporting": "*", "gray-matter": "^4.0.1" } } diff --git a/benchmarks/markdown/page-template.js b/benchmarks/markdown_table/page-template.js similarity index 100% rename from benchmarks/markdown/page-template.js rename to benchmarks/markdown_table/page-template.js diff --git a/benchmarks/markdown/src/pages/index.js b/benchmarks/markdown_table/src/pages/index.js similarity index 100% rename from benchmarks/markdown/src/pages/index.js rename to benchmarks/markdown_table/src/pages/index.js diff --git a/benchmarks/markdown/src/templates/blank.js b/benchmarks/markdown_table/src/templates/blank.js similarity index 100% rename from benchmarks/markdown/src/templates/blank.js rename to benchmarks/markdown_table/src/templates/blank.js diff --git a/benchmarks/plugin-manifest/README.md b/benchmarks/plugin-manifest/README.md index 8af7de02029ab..67a2b4cc2437b 100644 --- a/benchmarks/plugin-manifest/README.md +++ b/benchmarks/plugin-manifest/README.md @@ -1,7 +1,7 @@ # gatsby-plugin-manifest performance tests - Setup: `yarn` -- Run: `yarn test` +- Run: `yarn bench` Benchmarks the current production version of the plugin unless you use `gatsby-dev`. @@ -9,13 +9,13 @@ Benchmarks the current production version of the plugin unless you use `gatsby-d ```shell # In the root of the Gatsby repository -$ yarn run watch --scope=gatsby-plugin-manifest . +yarn run watch --scope=gatsby-plugin-manifest . ``` ```shell # In ./benchmarks/plugin-manifest # You'll need 'gatsby-dev' installed and configured globally. -$ gatsby-dev --packages gatsby-plugin-manifest +gatsby-dev --packages gatsby-plugin-manifest ``` You may now switch branches using `git checkout` and edit code on the current branch. Changes will be compiled into the local `node_modules` for the benchmark. diff --git a/benchmarks/plugin-manifest/gatsby-config.js b/benchmarks/plugin-manifest/gatsby-config.js new file mode 100644 index 0000000000000..654c61934400e --- /dev/null +++ b/benchmarks/plugin-manifest/gatsby-config.js @@ -0,0 +1,3 @@ +module.exports = { + plugins: [`gatsby-plugin-benchmark-reporting`], +} diff --git a/benchmarks/plugin-manifest/package.json b/benchmarks/plugin-manifest/package.json index 1679e1d59140c..b24360b3675b2 100644 --- a/benchmarks/plugin-manifest/package.json +++ b/benchmarks/plugin-manifest/package.json @@ -4,12 +4,18 @@ "description": "Run manifest lots of times", "main": "index.js", "scripts": { - "test": "node index.js" + "bench": "set -x; node index.js", + "build": "gatsby build", + "develop": "gatsby develop", + "serve": "gatsby serve" }, "author": "Alex Moon + +## Use #100DaysOfGatsby on Social Media + +As you work on your Gatsby project, connect with the community by using #100DaysOfGatsby in your tweets or posts on social media. If you need help with a challenge, or want to share a tool or technique that was useful, visit our [Gatsby communities](/contributing/community/#where-to-get-support) on [Discord](https://discordapp.com/invite/gatsby), [Spectrum](https://spectrum.chat/gatsby-js), [Dev](https://dev.to/t/gatsby), and [Reddit](https://www.reddit.com/r/gatsbyjs/). + +## 👉🏽 New to React or Web Development? + +If you are an aspiring React developer, then this challenge will supercharge your learning. Gatsby is a great framework to adopt first so you can master React, Node.js, and JavaScript. Register your email in the form above and we will send you beginner-friendly, interesting projects that will help you explore the Gatsby and React ecosystem. + +## 👉🏽 Experienced React Developer? + +If you are comfortable building webapps with React and its related tooling and if you are already familiar with Gatsby, we invite you to take your knowledge deeper by building your first Gatsby theme, plugin, or dynamic app. Register your email in the form above and we will send you resources for building advanced Gatsby projects. + +Happy coding! diff --git a/docs/blog/100days/react-component/index.md b/docs/blog/100days/react-component/index.md new file mode 100644 index 0000000000000..ba6435bac025f --- /dev/null +++ b/docs/blog/100days/react-component/index.md @@ -0,0 +1,38 @@ +--- +title: Challenge 4 - Add Third-Party React Components to Your Gatsby Site +date: 2020-01-23 +author: "Hashim Warren" +tags: ["learning-to-code", "contest", "100-Days-of-Gatsby"] +--- + +_Gatsby was named the [#1 new technology to learn in 2020](https://www.cnbc.com/2019/12/02/10-hottest-tech-skills-that-could-pay-off-most-in-2020-says-new-report.html)!_ + +_To help you learn about Gatsby and our ecosystem, we invite you to take the #100DaysOfGatsby challenge! If you are new to Gatsby, you can follow along with our beginner-friendly weekly prompts. Or if you are familiar with Gatsby and want to go deeper, we invite you to [build your first Gatsby Theme](/docs/themes/building-themes/)._ + +_Learn more about [#100DaysOfGatsby here](/blog/100days)!_ + +## Challenge 4: Add a Form to Your Site (Using a Third-Party React Library) + +The Gatsby framework is [based on React](/docs/glossary/react/). So, a Gatsby project is a React project. And the Gatsby ecosystem is a subset of the React ecosystem. + +This is exciting! There are hundreds of [Gatsby plugins and themes](/plugins/) you can use on your site, with more being added every day. But there are already thousands of free, well-tested React projects that you can use on your site too! + +For example, you can hide/show your site header with [React headroom](https://kyleamathews.github.io/react-headroom/), organize your CSS with [Theme UI](https://theme-ui.com/), or control your HTML head with [React Helmet](https://github.com/nfl/react-helmet). + +In this prompt, we invite you to add forms to your Gatsby site using [Formik, a popular and powerful React library](https://jaredpalmer.com/formik). We suggest adding the form to the “About” page you created in a previous challenge. + +(In a future challenge we will show you how to add your form, or any React component to your Markdown-powered blog pages.) + +### Challenge Resources + +Learn how to [import and use almost any React component](/docs/adding-react-components/) in your Gatsby project. However, instead of using the example in our documentation, install [Formik from npm](https://www.npmjs.com/package/formik). + +Next, follow [Formik’s step-by-step tutorial](https://jaredpalmer.com/formik/docs/tutorial) for creating a newsletter signup form. + +Lastly, familiarize yourself with the [acessibility guidelines regarding forms](/docs/building-a-contact-form/#creating-an-accessible-form), and ensure your form meets those standards. + +### What to Do If You Need Help + +If you get stuck during the challenge, you can ask for help from the [Gatsby community](/contributing/community/) and the [ASKGatsbyJS](https://twitter.com/AskGatsbyJS) Twitter account. You can find fellow Gatsby Developers on [Discord](https://discordapp.com/invite/gatsby), [Reddit](https://www.reddit.com/r/gatsbyjs/), [Spectrum](https://spectrum.chat/gatsby-js), and [Dev](https://dev.to/t/gatsby). + +For this challenge, you can also ask the [Formik community](https://jaredpalmer.com/formik/help) for help. diff --git a/docs/blog/100days/start-blog/index.md b/docs/blog/100days/start-blog/index.md new file mode 100644 index 0000000000000..900500df2f63f --- /dev/null +++ b/docs/blog/100days/start-blog/index.md @@ -0,0 +1,32 @@ +--- +title: Challenge 1 - Track Your Coding Progress with a Blazing Fast Blog +date: 2019-12-31 +author: "Hashim Warren" +tags: ["learning-to-code", "contest", "100-Days-of-Gatsby"] +--- + +_Did you hear the news? Gatsby was named the [#1 new technology to learn in 2020](https://www.cnbc.com/2019/12/02/10-hottest-tech-skills-that-could-pay-off-most-in-2020-says-new-report.html)!_ + +_To help you learn about Gatsby and our ecosystem, we invite you to take the #100DaysOfGatsby challenge! If you are new to Gatsby, you can follow along with our beginner-friendly weekly prompts. Or if you are familiar with Gatsby and want to go deeper, we invite you to [build your first Gatsby Theme](/docs/themes/building-themes/)._ + +_Learn more about [#100DaysOfGatsby here](/blog/100days)!_ + +## Challenge 1: Create a Gatsby Blog from Scratch + +Why share all of your ideas with just Reddit and Twitter? Your best writing needs a home - on your very own blog! + +This week, let’s get a Gatsby blog up-and-running from scratch. You’ll get practice setting up your local environment, creating new pages from React components, sourcing content from Markdown files, and deploying your site to a host! + +If you are new to Node.js or React development, a Gatsby blog is a terrific project to start with. + +_Bonus:_ use your new blog to track your #100DaysOfGatsby progress! Research shows that writing about what you learn, or even what you’re struggling with helps you to retain that information, or even discover a solution. So, during your #100DaysOfGatsby journey, we encourage you to use this blog to write about your ups and downs, victories and challenges. + +### Challenge Resources + +To create your blog, start with our [beginner-focused Gatsby tutorials](/tutorial/) and complete lessons 0-8. Depending on your current skill level, erecting a Gatsby blog make take you an afternoon or a full week (or more) to complete. + +If you are already familiar with Gatsby's APIs and conventions, and want a more advanced challenge, you can [create a Gatsby theme for your blog](/tutorial/theme-tutorials/). + +### What to Do If You Need Help + +If you get stuck during the challenge, you can ask for help from the [Gatsby community](https://www.gatsbyjs.org/contributing/community/). You can find fellow Gatsby Developers on [Discord](https://discordapp.com/invite/gatsby), [Reddit](https://www.reddit.com/r/gatsbyjs/), [Spectrum](https://spectrum.chat/gatsby-js), and [Dev](https://dev.to/t/gatsby). diff --git a/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md b/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md index 3402029dd9c94..404b9201c14c9 100644 --- a/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md +++ b/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md @@ -27,7 +27,7 @@ generated content. 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 +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! diff --git a/docs/blog/2017-09-26-embracing-graphql/index.md b/docs/blog/2017-09-26-embracing-graphql/index.md index 31abc50971019..9909e6e6a8461 100644 --- a/docs/blog/2017-09-26-embracing-graphql/index.md +++ b/docs/blog/2017-09-26-embracing-graphql/index.md @@ -7,7 +7,7 @@ excerpt: "Moving to Gatsby 1.x and embracing the new GraphQL setup can be daunti tags: ["v1", "graphql", "getting-started"] --- -Before I built [React FAQ](https://reactfaq.site/), I went looking for a static +Before I built "React FAQ" (GitHub: https://github.com/timarney/react-faq), I went looking for a static site generator. I had a few criteria in mind. @@ -65,7 +65,7 @@ reviews were solid but I was still stuck on my pre-1.0 mindset. Then three weeks ago I saw this tweet from [@ryanflorence](https://twitter.com/ryanflorence): - +https://twitter.com/ryanflorence/status/906233888560758784 Well, that sounded like a pretty good endorsement. diff --git a/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md b/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md index 7cf814aa3749c..057449257c40d 100644 --- a/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md +++ b/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md @@ -60,7 +60,7 @@ where to hold your content, and moved everything else away or removed it. Here's what that looks like for me: -``` +```text . ├── content │ ├── _drafts @@ -82,7 +82,7 @@ are many ways you could do this but I'll go over what I did. To get all the Gatsby files you can use the Gatsby CLI. ```yaml -gatsby new temp-gatsby-files # Initialize gatsby in a temp directory +gatsby new temp-gatsby-files # Initialize Gatsby in a temp directory cp -R temp-gatsby-files/* ./ # Copy all the files into your root directory rm -rf temp-gatsby-files # Remove the temp directory ``` @@ -90,7 +90,7 @@ rm -rf temp-gatsby-files # Remove the temp directory However you get Gatsby initialized in your repository root, afterwards you should have a file structure that looks something like this: -``` +```text . ├── content │ └── [ Markdown files ... ] @@ -110,7 +110,7 @@ should have a file structure that looks something like this: Now run the Gatsby dev server to make sure everything works: -``` +```bash npm run develop ``` @@ -130,7 +130,7 @@ probably want to customize the header and overall layout. This is pretty simple. Just modify the primary layout file that was generated: -``` +```text src/layouts/index.js ``` @@ -146,7 +146,7 @@ I talked about in part 1. Also straightforward, just edit: -``` +```text src/pages/index.js ``` @@ -180,7 +180,7 @@ If you play around with GraphiQL you'll notice there's not that much there. Let's fix that. We need to teach Gatsby how to query the file system. Luckily this is so common it's been done for you. Install the file system source plugin: -``` +```bash npm i --save gatsby-source-filesystem ``` @@ -229,7 +229,7 @@ Being able to query files is a big win, and if you have a directory of HTML files this is all you will need. But if you want to render markdown files as HTML you will need another plugin. Let's add that now: -``` +```bash npm i --save gatsby-transformer-remark ``` @@ -268,7 +268,7 @@ This query gives you the full HTML for all your markdown files. If you are using frontmatter you can also access that here. I'm assuming you have a `title` field in your frontmatter: -``` +```graphql query { allMarkdownRemark { edges { @@ -397,27 +397,29 @@ Let's remedy that. Import the `Link` component and swap it for the simple `` tag that was in there before: ```jsx -import React from 'react'; -import { Link } from 'gatsby'; +import React from "react" +import { Link } from "gatsby" export default class BlogIndex extends React.Component { render() { // Handle graphql errors if (this.props.errors && this.props.errors.length) { this.props.errors.forEach(({ message }) => { - console.error(`BlogIndex render errr: ${message}`); - }); - return

Errors found: Check the console for details

; + console.error(`BlogIndex render errr: ${message}`) + }) + return

Errors found: Check the console for details

} return (

Some things I wrote

{this.props.data.allMarkdownRemark.edges.map(({ node }, i) => ( - {node.frontmatter.title} + + {node.frontmatter.title} + ))}
- ); + ) } } ``` @@ -458,7 +460,7 @@ export const pageQuery = graphql` Many existing Gatsby examples use `path` within each markdown file's frontmatter to designate the url. For example: -```md +```markdown --- title: My Post path: my-post diff --git a/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md b/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md index 709ed31065b39..faa480ee3b49f 100644 --- a/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md +++ b/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md @@ -129,7 +129,7 @@ project I didn't know a lot about: - WordPress REST API Moving forward with Gatsby, I'd like to extend my site to include pagination -within the blog, use [Styled Components](https://www.styled-components.com/) and +within the blog, use [Styled Components](https://styled-components.com/) and ensure the site scores a 90+ overall on [Lighthouse](https://developers.google.com/web/tools/lighthouse/), Google’s performance auditing tool. diff --git a/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md b/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md index 49381e085a4a2..44af9a21a4a46 100644 --- a/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md +++ b/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md @@ -124,7 +124,7 @@ we create a JSON file for each component we want to translate. For our site we're currently supporting English and Welsh, so our locales folder looks like this. -``` +```text - src - locales - en @@ -231,16 +231,10 @@ import { translate } from "react-i18next" class LanguageSwitcher extends Component { constructor(props) { super(props) - const { i18n } = this.props - this.state = { language: i18n.language } this.handleChangeLanguage = this.handleChangeLanguage.bind(this) } - componentWillReceiveProps(nextProps) { - this.setState({ language: nextProps.i18n.language }) - } - handleChangeLanguage(lng) { const { i18n } = this.props i18n.changeLanguage(lng) @@ -248,7 +242,7 @@ class LanguageSwitcher extends Component { renderLanguageChoice({ code, label }) { const buttonClass = classNames("LanguageSwitcher__button", { - "LanguageSwitcher__button--selected": this.state.language === code, + "LanguageSwitcher__button--selected": this.props.i18n.language === code, }) return ( @@ -279,8 +273,8 @@ class LanguageSwitcher extends Component { export default translate("LanguageSwitcher")(LanguageSwitcher) ``` -This is a pretty simple component. We're setting the `language` state based on -the i18n prop so that we can check which language is currently active and show +This is a pretty small component. We're getting the `language` in the +i18n prop so that we can check which language is currently active and show that in our menu. The `handleLanguageChange` function just wraps the `react-i18n` function passed diff --git a/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md b/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md index e82d63b6e7d23..4f81e1afc654a 100644 --- a/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md +++ b/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md @@ -138,7 +138,7 @@ recently. Be warned: the tutorial isn’t quite finished yet, you might be better off starting with -[one of the starter kits already available](/docs/gatsby-starters/), +[one of the starter kits already available](/starters/), so that you get `react-helmet` and active links implemented, the 2 things I had to learn independently. diff --git a/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md b/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md index 10103b4563188..86985b79c4b4e 100644 --- a/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md +++ b/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md @@ -172,7 +172,7 @@ Steps were: Add `gatsby-plugin-typography` and `typography-theme-moraga` (for example) and "enable" the plugin in the `gatsby-config.js` file: -```javascript= +```javascript { resolve: `gatsby-plugin-typography`, options: { @@ -183,7 +183,7 @@ Add `gatsby-plugin-typography` and `typography-theme-moraga` (for example) and In `src/utils/typograhy` add: -```javascript= +```javascript import Typography from "typography" import theme from "typography-theme-moraga" diff --git a/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md b/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md index 08c5afacbe0cd..34d4adaeb4e6a 100644 --- a/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md +++ b/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md @@ -67,7 +67,7 @@ need to extract the date from the file name. The slug in my case is generated with this (default in Jekyll) structure: -``` +```text https://blog.singuerinc.com/[n-categories]/YYYY/MM/DD/dashed-title/ // Given this data: diff --git a/docs/blog/2017-11-09-why-i-created-my-blog-with-gatsby-and-contentful/index.md b/docs/blog/2017-11-09-why-i-created-my-blog-with-gatsby-and-contentful/index.md index f4e8b051c5466..bafd9cd00d3cd 100644 --- a/docs/blog/2017-11-09-why-i-created-my-blog-with-gatsby-and-contentful/index.md +++ b/docs/blog/2017-11-09-why-i-created-my-blog-with-gatsby-and-contentful/index.md @@ -133,8 +133,6 @@ nothing and end up with an infinitely more secure, scalable and faster website. Say what? -

via GIPHY

- ## Enter the world of static site generators... If you are a developer, you probably are familiar with Static Site Generators, @@ -197,12 +195,12 @@ thought of that and created Gatsby.js. A little disclaimer: I absolutely love React, so, when I first learned that there were some emerging Static Site Generators who leveraged only React and Webpack, I knew that I had to try at least one of them for the new upcoming blog -I was planning to build. These projects were [Gatsby.js ](http://gatsbyjs.org/) +I was planning to build. These projects were [Gatsby.js](https://gatsbyjs.org/) and [Phenomic](https://phenomic.io/), and both were still quite young back then, neither of them having reached the 1.0 release yet. Ironically I chose Phenomic, mainly because I liked what the guys from -[Serverless.com ](http://serverless.com/)had done with their website at that +[Serverless.com](http://serverless.com/) had done with their website at that time -- built using Phenomic. So, I went ahead and built my blog using Phenomic. Overall, I thought it was a @@ -338,6 +336,6 @@ paradigms like Serverless, I predict it could be very far. But whatever that limit is, I am quite sure that this is a step in the right direction towards making the web a safer, faster and more enjoyable experience -for both developers and end-users. +for both developers and end users.

via GIPHY

diff --git a/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md b/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md index c52e777264d16..f4da51c15b2e9 100644 --- a/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md +++ b/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md @@ -51,7 +51,7 @@ Gatsby definitely delivers on speed. The whole PRPL pattern thing seems to work Data from anywhere with static output. That's sort of the holy grail isn't it? Right now the data I use in this site comes from markdown files, but I can already see that switching to another content source is going to be a breeze with GraphQL. The queries are clean and readable and the Graph*i*QL IDE is the perfect helper. In a way, GraphQL allows you to separate your frontend from the type of data source. -```es6 +```javascript export const query = graphql` query BlogPostQuery($slug: String!) { markdownRemark(fields: { slug: { eq: $slug } }) { @@ -79,7 +79,7 @@ export const query = graphql` After reading some articles on the Gatsby site, I decided to set up my Gatsby hosting on a free plan from [Netlify](https://www.netlify.com/) (which is ridiculously generous by the way, what's the catch?) and that has been a fun experience. Netlify already supports Gatsby out of the box, which means you can configure automatic deploys with `git` in a few clicks. Every time I push to master, the site gets rebuild and uploaded by Netlify. _Magic_. There's also the possibility to configure staging servers based on your branches, so you can always test out your changes before merging to master and deploying. -But wait, there's more. If you use [Contentful](https://www.contentful.com/) as Content Management System and Netlify as your host, you can easily create a Webhook to trigger a rebuild on every content update! I haven't tried this myself yet, but [this posts](https://www.halfelectronic.com/post/setting-up-gatsby-js-contentful-and-netlify/) by [Fernando Poumián](https://twitter.com/fernandopoumian) is a great resource to get you going. +But wait, there's more. If you use [Contentful](https://www.contentful.com/) as Content Management System and Netlify as your host, you can easily create a Webhook to trigger a rebuild on every content update! I haven't tried this myself yet, but [this posts](https://www.halfelectronic.com/post/setting-up-gatsby-js-contentful-and-netlify/) by Fernando Poumián is a great resource to get you going. Incremental builds aren't yet possible, so every update means a complete rebuild. I'm sure that's no cause for concern on smaller sites, but with larger sites that are updated often it could be a problem. Luckily, incremental builds will be part of Gatsby ['sooner than later'](https://twitter.com/gatsbyjs/status/937053640652611584), which will take care of that problem. diff --git a/docs/blog/2018-03-07-why-we-created-the-plugin-library/index.md b/docs/blog/2018-03-07-why-we-created-the-plugin-library/index.md index 430533bc29f64..11a07dc9de36f 100644 --- a/docs/blog/2018-03-07-why-we-created-the-plugin-library/index.md +++ b/docs/blog/2018-03-07-why-we-created-the-plugin-library/index.md @@ -5,7 +5,7 @@ author: Shannon Soper tags: ["plugins", "documentation"] --- -Earlier this week, we launched a [Plugin Library](/packages/) on Gatsbyjs.org and are excited for you to use it! This article explains how UX research drove the design of this library and the accompanying [Plugin Authoring](/docs/creating-plugins/) doc. +Earlier this week, we launched a [Plugin Library](/plugins/) on Gatsbyjs.org and are excited for you to use it! This article explains how UX research drove the design of this library and the accompanying [Plugin Authoring](/docs/creating-plugins/) doc. ![Plugin tweet](plugin-tweet.png) @@ -32,7 +32,6 @@ With the empathy map and the interviews as our guide, we learned that most peopl Next, we analyzed over 10 admirable and/or popular plugin libraries to draw from their strengths and learn from their weaknesses. Examples, in no particular order, include: -- [JS.coach](https://js.coach/) - [VIM Awesome](https://vimawesome.com/) - [Best of JS](https://bestof.js.org/) - [Sketch extension library](https://sketchapp.com/extensions/) diff --git a/docs/blog/2018-04-04-gatsby-contentful-starter-tutorial/index.md b/docs/blog/2018-04-04-gatsby-contentful-starter-tutorial/index.md index be3eb9311c5c9..02295f8fc08c5 100644 --- a/docs/blog/2018-04-04-gatsby-contentful-starter-tutorial/index.md +++ b/docs/blog/2018-04-04-gatsby-contentful-starter-tutorial/index.md @@ -26,7 +26,7 @@ Here’s an overview of what’s involved: - Preview a production build - Publish and go live -###Getting started +### Getting started This guide assumes that you have [GatsbyJS installed](/docs/) and, optionally, a [GitHub account](https://github.com/join). You will also need a free Contentful account - [creating one](https://www.contentful.com/sign-up/) only takes a moment. @@ -48,7 +48,7 @@ And go into the directory and install the required dependencies with: npm install ``` -###Create a new space to store content +### Create a new space to store content [A Space within Contentful](https://www.contentful.com/r/knowledgebase/spaces-and-organizations/) serves as a storage area for content that will be used in your website and can be configured to serve specific purposes. Content is described and stored using a data model which we call content types; these are entirely configurable. @@ -56,7 +56,7 @@ Create a new empty space by opening the sidebar menu and adding a Space. Give th ![create a new space](new_space.png) -###Generate access tokens +### Generate access tokens Before getting to the exciting part of setting up your website, you first need to generate three access tokens to get your Contentful-powered website up and running by fetching data from the API. @@ -76,7 +76,7 @@ The Content Preview API works much like the Content Delivery API, except it show ![Creating a new API key](api_key.png) -###Content model and configuration +### Content model and configuration Start setting things up with the npm run setup command, which first prompts you for the ID of the empty Space you just created along with the API access tokens for Content Management, Content Delivery, and Content Preview. @@ -98,21 +98,19 @@ After that, it writes the credentials you provided into a file named .contentful Using the credentials in the .contentful.json file, [content can now be imported](https://www.contentful.com/developers/docs/tutorials/general/import-and-export/) into your space to being displayed on your website via our API. -###It’s ready, let’s publish +### It’s ready, let’s publish Time to check out your new website - preview changes in a local environment by running your project using the npm run dev command. This uses the [Contentful Preview API](https://www.contentful.com/developers/docs/references/content-preview-api/) to show unpublished content as if they were already published - perfect for a development or staging environment. If you like what you see, use the npm run build command to start a static production build of your near-ready website and put it on a static host of your choice. After that, the npm run deploy command allows you to publish what you have on the production build onto GitHub Pages. -###Deployment +### Deployment Your static files can then be deployed on a variety of platforms of your choice, like [BitBalloon](https://www.bitballoon.com/) and [GitHub Pages](https://pages.github.com/). Take your pick. Contentful gives you infrastructure for the content in your stack, that matches your modular and agile way of working with platform independence and by serving as a layer in your stack. Contentful ensures your website and its users can access your content quickly and reliably. Your content is just an API call away. -###Summary - -###Summary +### Summary That’s a quick overview of how to get your website up and running from scratch using Contentful and GatsbyJS. diff --git a/docs/blog/2018-04-10-how-to-handle-comments-in-gatsby-blogs/index.md b/docs/blog/2018-04-10-how-to-handle-comments-in-gatsby-blogs/index.md index 72e3796a8b7fe..362adc97b5b40 100644 --- a/docs/blog/2018-04-10-how-to-handle-comments-in-gatsby-blogs/index.md +++ b/docs/blog/2018-04-10-how-to-handle-comments-in-gatsby-blogs/index.md @@ -40,11 +40,11 @@ You could create your own staticman alternative. You could use a framework like ### Netlify -Are you hosting on [netlify](https://serverless.com/)? Then you could use their forms service. If you pay for netlify, you can link forms to functions. Similar to serverless. You could use that to make PRs. Or push content to GitHub. Or other Git hosts. Too complicated. Not worth it. +Are you hosting on [Netlify](https://serverless.com/)? Then you could use their forms service. If you pay for Netlify, you can link forms to functions. Similar to serverless. You could use that to make PRs. Or push content to GitHub. Or other Git hosts. Too complicated. Not worth it. ### Email -You could link your comment form to an email address. Then you could copy and paste comments into Git. Manual comment moderation. Maybe with netlify's form service? Or a serverless setup. Again, this could be fun to setup. Again, it's probably not a very good idea! +You could link your comment form to an email address. Then you could copy and paste comments into Git. Manual comment moderation. Maybe with Netlify's form service? Or a serverless setup. Again, this could be fun to setup. Again, it's probably not a very good idea! ## Crazy diff --git a/docs/blog/2018-04-11-trying-out-gatsby-at-work-and-co/index.md b/docs/blog/2018-04-11-trying-out-gatsby-at-work-and-co/index.md index 0f43b52b93c79..29cea1fc1038a 100644 --- a/docs/blog/2018-04-11-trying-out-gatsby-at-work-and-co/index.md +++ b/docs/blog/2018-04-11-trying-out-gatsby-at-work-and-co/index.md @@ -77,7 +77,7 @@ Figuring out how to set this up in GraphQL took some trial and error, but we set The GraphQL looks like this: -``` +```graphql ContentfulContentPage { headline slug @@ -127,7 +127,7 @@ Building off of Gatsby’s Contentful example, we were able to easily support dy This worked so well that at first I was sure we wouldn’t even need to create any pages with static urls, but these wound up coming in handy for development and testing. We settled on a structure like this: -``` +```text |-pages/ |-dev/ |-article-components.js @@ -155,7 +155,7 @@ That same validation page also served as a site status page, containing the time Capturing this information was easy and only took a few additional lines in our `createPages` hook. Netlify exposes a lot of interesting [environment variables](https://www.netlify.com/docs/continuous-deployment/#build-environment-variables) (including some I hope to play with more on a future project, like `WEBHOOK_TITLE`, which can help you deduce the origin of the current build). In order to display these variables on the frontend, we needed to rename them to begin with `GATSBY_`: -``` +```javascript exports.createPages = () => { ['COMMIT_REF', ‘BRANCH’]].forEach((variableName) => { // only variables beginning with GATSBY_ are available client-side @@ -166,21 +166,21 @@ exports.createPages = () => { After that, we just added one more variable to store the current time: -``` -process.env.GATSBY_BUILD_TIME = Date.now(); +```javascript +process.env.GATSBY_BUILD_TIME = Date.now() ``` #### Covering our tracks We filtered out our dev pages in production by adding a simple `onCreatePage` hook to our `gatsby-node` file: -``` +```javascript exports.onCreatePage = ({ page, boundActionCreators }) => { if (process.env.GATSBY_ENV === ENV.PRODUCTION) { - const { deletePage } = boundActionCreators; - if (/^\/dev\//.test(page.path)) deletePage(page); + const { deletePage } = boundActionCreators + if (/^\/dev\//.test(page.path)) deletePage(page) } -}; +} ``` ### Staging @@ -213,13 +213,13 @@ Backing up a second, let’s review why we selected the preview URLs `mystagingu Here’s why: Contentful’s Content Preview dashboard doesn’t give you that kind of flexibility. To get around this, we opted to build special paths just for the staging environment. Here’s how we set it up in `gatsby-node.js`: -``` +```javascript // Always create a page at the regular path createPage({ component: contentPageTemplate, context, - path: `${language}/${slugs.join('/')}/`, -}); + path: `${language}/${slugs.join("/")}/`, +}) // On staging, recreate the page with a path corresponding to its ID if (process.env.GATSBY_ENV === ENV.STAGING) { @@ -227,7 +227,7 @@ if (process.env.GATSBY_ENV === ENV.STAGING) { component: contentPageTemplate, context, path: `${language}/${id}/`, - }); + }) } ``` @@ -277,7 +277,7 @@ As I said, I was impressed by the Gatsby team’s quick turnaround time with PR Of course, this is something developers do all the time. They push their fork to Git and link to it in their project’s `package.json`: -``` +```json “dependencies”: { "some-library": "git+ssh://git@github.com:workco/some-library.git#cool-feature" } diff --git a/docs/blog/2018-05-24-launching-new-gatsby-company/index.md b/docs/blog/2018-05-24-launching-new-gatsby-company/index.md index 69a9d33ef1988..b520e23170fb9 100644 --- a/docs/blog/2018-05-24-launching-new-gatsby-company/index.md +++ b/docs/blog/2018-05-24-launching-new-gatsby-company/index.md @@ -96,15 +96,17 @@ But static sites, despite how much developers love them, have never gained wides As I thought deeply about this problem, it occurred to me that there were strong parallels between this problem and everything I’d learned about event sourcing and building cloud-native applications. - - +https://twitter.com/kylemathews/status/825512417337544705 + +https://twitter.com/kylemathews/status/825513977329307648 I realized you could view a website as the current computed state of a long stream of content and code changes. When viewed through that lens, the architecture became clear for a new version of Gatsby that would glue Gatsby to various data sources & solve the really hard problems of static sites: fast incremental builds and parallelizing builds for large and complex sites. This architecture would enable Gatsby to eliminate the build step entirely—any code or content change would be quickly incorporated into the site and go live immediately. We could port the ideas of real-time event processing to building websites. - - +https://twitter.com/kylemathews/status/916165920359198720 + +https://twitter.com/kylemathews/status/916165988772487168 ### Launching new version of Gatsby diff --git a/docs/blog/2018-06-08-life-after-layouts/index.md b/docs/blog/2018-06-08-life-after-layouts/index.md index a0d5eed95ef71..532d23eab1b74 100644 --- a/docs/blog/2018-06-08-life-after-layouts/index.md +++ b/docs/blog/2018-06-08-life-after-layouts/index.md @@ -109,7 +109,7 @@ Removing layouts isn't the only improvement coming in Gatsby V2. We're really ex - Much faster hot reloading, which enables Ludicrous Mode - +https://twitter.com/gatsbyjs/status/974507205121617920 - We can now add GraphQL queries to any component in our app (not just page components) using [`StaticQuery`](/docs/static-query/) - Upgraded to the latest versions of React, Babel, Webpack, and other libraries Gatsby depends on @@ -121,7 +121,7 @@ For a full list of what's new, check out our [V2 migration guide](/docs/migratin - You can get started using Gatsby V2 right now by installing our V2 default starter: - ``` + ```shell gatsby new my-gatsby-v2-site https://github.com/gatsbyjs/gatsby-starter-default ``` diff --git a/docs/blog/2018-06-18-moving-from-create-react-app-to-gatsby-js/index.md b/docs/blog/2018-06-18-moving-from-create-react-app-to-gatsby-js/index.md index 32f79c1f2a599..0f67641dd7521 100644 --- a/docs/blog/2018-06-18-moving-from-create-react-app-to-gatsby-js/index.md +++ b/docs/blog/2018-06-18-moving-from-create-react-app-to-gatsby-js/index.md @@ -40,7 +40,7 @@ Gatsby uses [GraphQL](https://graphql.org/learn/) to share data across pages. Yo ## Gatsby project folder structure -```shell +```text ├── LICENSE ├── README.md ├── gatsby-config.js @@ -66,7 +66,7 @@ There are two types of routes: Let's assume you have the following static routes in your `create-react-app` project: -```js +```jsx @@ -74,7 +74,7 @@ Let's assume you have the following static routes in your `create-react-app` pro Gatsby will create these routes automatically based on files you create in your `pages` folder. The good news is you've already created the React components so it's a matter of copying them to the right place. The exception is the home page which should be named `index.js`.  You will end up with something like this: -```shell +```text ├── LICENSE ├── README.md ├── gatsby-config.js @@ -98,13 +98,13 @@ I will take an example of blog posts in this case loaded from Contentful. Every In a normal React app the route will look something like this. -```js +```jsx ``` And your `BlogPost` component will look something like this: -```js +```jsx // a function that requests a blog post from Contentful's API import { getBlogPost } from "./contentful-service" import marked from "marked" @@ -188,7 +188,7 @@ Since you already have the `BlogPost` component from your React project move it Your Gatsby project will look like this: -```shell +```text ├── LICENSE ├── README.md ├── gatsby-config.js @@ -211,7 +211,7 @@ You need to make some slight modifications to your `BlogPost` component. `src/templates/blog-post.js`: -```js +```jsx import React from "react" import { graphql } from "gatsby" diff --git a/docs/blog/2018-08-09-swag-store/index.md b/docs/blog/2018-08-09-swag-store/index.md index e695f9eff0a97..0a3a6d83232e4 100644 --- a/docs/blog/2018-08-09-swag-store/index.md +++ b/docs/blog/2018-08-09-swag-store/index.md @@ -8,24 +8,7 @@ tags: ["open-source", "community"] Today, we’re _so excited_ to announce the launch of the [Gatsby Swag Store][store]! If you’ve been following along [on Twitter][twitter], you may have seen the news a little while back. - +https://twitter.com/marisamorby/status/1019256499799912449 We’ve spent the last couple weeks working the kinks out, and we couldn’t be happier with the response we’ve seen. @@ -55,15 +38,7 @@ We’re extremely excited about the launch of the store because it means contrib Going forward, all contributors to the [Gatsby organization on GitHub][org] will automatically qualify for free Gatsby swag. **And when we say _all_ contributors, we mean it: even if you contributed to Gatsby before the store was launched, you’re qualified for free swag!** - +https://twitter.com/lekoarts_de/status/1023823370620727296 For more details and instructions on how to claim your free swag, see [the “swag for contributors” section of the docs][swag]. @@ -84,30 +59,7 @@ We know how much it sucks when things aren’t available in your country, so — We love seeing how great the community looks in purple, so please post your Gatsby swag photos with the hashtag [#buildwithgatsby](https://twitter.com/search?q=%23buildwithgatsby). - +https://twitter.com/amanhimself/status/1023124667446509570 ## How the store works @@ -115,14 +67,7 @@ All of the source code for the swag store [has been open sourced][swag-source]. We also use [Peril][peril] to [automatically invite contributors][invite] to the Gatsby organization on GitHub and post details about claiming swag. Here’s an example (and some kind words from Gatsby contributor [Payton Burdette](https://twitter.com/beardedpayton)) showing what the automated response looks like: - +https://twitter.com/beardedpayton/status/1020339698332512256 ## What’s next? @@ -130,16 +75,7 @@ We have a lot of ideas for the Gatsby store — from [new swag ideas](https://gi For now, that’s it! We’ll leave you with our favorite genre of tweet: “dogs wearing Gatsby swag”. - +https://twitter.com/ryanwiemer/status/1022267081998266368 Thanks for being part of the open source community! 💪💜 diff --git a/docs/blog/2018-08-11-gatsby-pair-programming/index.md b/docs/blog/2018-08-11-gatsby-pair-programming/index.md index 2a220ec085ea1..a2a5851cc9dba 100644 --- a/docs/blog/2018-08-11-gatsby-pair-programming/index.md +++ b/docs/blog/2018-08-11-gatsby-pair-programming/index.md @@ -10,7 +10,7 @@ I love pair programming. This is one of the practices we do in our trainings at A couple of weeks ago, we were planning to rebuild our websites using Gatsby, and then I saw this: - +https://twitter.com/jlengstorf/status/1016721019376025600 I didn’t have to think about that twice--I booked it! It was funny because the week before this tweet I was talking to [Alex](https://twitter.com/alex_lobera) and [Richard](https://twitter.com/ric9176) about a similar idea I had with ReactJS Academy. We want to do something similar to pair programming with developers who want to learn React (if you are interested please send me a DM!). diff --git a/docs/blog/2018-08-24-gatsby-aws-hosting/index.md b/docs/blog/2018-08-24-gatsby-aws-hosting/index.md index ea7f7f31866f6..4827ef0e41084 100644 --- a/docs/blog/2018-08-24-gatsby-aws-hosting/index.md +++ b/docs/blog/2018-08-24-gatsby-aws-hosting/index.md @@ -7,7 +7,7 @@ excerpt: "In this post, we'll walk through how to host & publish your next Gatsb canonicalLink: "https://aws-amplify.github.io/amplify-js/media/hosting_guide" --- -![Publishing Your Next Gatsby Site to AWS With AWS Amplify](images/gatsbyaws.jpeg) +![Publishing Your Next Gatsby Site to AWS With AWS Amplify](./images/gatsbyaws.jpeg) In this post, we'll walk through how to host & publish your next Gatsby site to AWS using [AWS Amplify](https://aws-amplify.github.io/). @@ -57,33 +57,33 @@ Now that the GitHub project has been created we can log into the [Amplify Consol From here, under Deploy we can click GET STARTED: -![Amplify Console](images/amplify1.png) +![Amplify Console](./images/amplify1.png) Next, we'll choose GitHub as our repository & click **Next**. -![Choosing repo](images/amplify2.png) +![Choosing repo](./images/amplify2.png) Then connect the mater branch of the new repo we just created & click **Next**: -![Choosing branch](images/amplify3.png) +![Choosing branch](./images/amplify3.png) In this view, we can review the default build settings & click **Next** to continue: -![Build settings](images/amplify4.png) +![Build settings](./images/amplify4.png) Finally, we can review the deployment & click **Save & Deploy** when we're ready to deploy our app: -![Deploying](images/amplify5.png) +![Deploying](./images/amplify5.png) Once the deployment is successful, you should see this: -![Successful deployment](images/amplify6.png) +![Successful deployment](./images/amplify6.png) To view details of the deployment, click on the name of the branch (in our case, **master**). In this view, you can see details about the deployment including a link to view the app & screenshots of the app on different devices. -![Deployment details](images/amplify7.png) +![Deployment details](./images/amplify7.png) ## Kicking off a new build @@ -113,11 +113,11 @@ git push origin master Now, when we go back into the Amplify console we'll see that a new build has been started: -![New build](images/amplify8.png) +![New build](./images/amplify8.png) When the build is completed & we launch the app, we should now see our new heading: -![New build completed](images/amplify9.png) +![New build completed](./images/amplify9.png) ## Next Steps diff --git a/docs/blog/2018-09-07-gatsby-values/index.md b/docs/blog/2018-09-07-gatsby-values/index.md index 8bcd4d3085019..a4238b014cd14 100644 --- a/docs/blog/2018-09-07-gatsby-values/index.md +++ b/docs/blog/2018-09-07-gatsby-values/index.md @@ -82,15 +82,7 @@ As we wrote these out, we discussed them with the whole team to make sure we wer At the end of the exercise, we’d extracted 8 shared core values, all of which the team is fully aligned on and deeply committed to. - +https://twitter.com/jlengstorf/status/1032319257298628608 ## What we learned — Gatsby’s core values @@ -154,16 +146,7 @@ Open source doesn’t have the best reputation for being friendly and welcoming, We will never judge, condescend, or exclude anyone. Instead, we will go above and beyond to support the community, through [pair programming](https://gatsby.dev/pairing), offering [free swag for contributors](https://gatsby.dev/swag), giving control to the community by [auto-inviting all contributors to the Gatsby GitHub org](https://github.com/gatsbyjs/gatsby/pull/7699#issuecomment-416665803), an open and inclusive [code of conduct](/contributing/code-of-conduct/), and other means that empower and embrace the incredible community that makes Gatsby possible. - +https://twitter.com/AustenAllred/status/1038084753008652289 We’re so happy you’re here. 💪💜 diff --git a/docs/blog/2018-09-17-gatsby-v2.md b/docs/blog/2018-09-17-gatsby-v2.md index 2ea78e0020e10..cda3688c262fc 100644 --- a/docs/blog/2018-09-17-gatsby-v2.md +++ b/docs/blog/2018-09-17-gatsby-v2.md @@ -125,14 +125,14 @@ We've added experimental support for GraphQL stitching. More and more services offer native GraphQL APIs and GraphQL stitching lets you use their API directly in your Gatsby site without having to wrap the API with a source plugin. -- [Read the RFC](https://github.com/gatsbyjs/rfcs/blob/master/text/0000-native-graphql-source.md) +- [Read the RFC](https://github.com/gatsbyjs/rfcs/blob/master/text/0004-native-graphql-source.md) - [Try out the plugin gatsby-source-graphql](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/README.md) ### Ludicrous Mode (aka faster data hot reloading) We spent some time optimizing Gatsby's data processing layer to make Markdown editing even nicer! - +https://twitter.com/gatsbyjs/status/974507205121617920 ### Remove special layout component diff --git a/docs/blog/2018-09-27-reach-router/index.md b/docs/blog/2018-09-27-reach-router/index.md index 6fb3d974a8cb6..23330009d4697 100644 --- a/docs/blog/2018-09-27-reach-router/index.md +++ b/docs/blog/2018-09-27-reach-router/index.md @@ -25,15 +25,7 @@ When a user navigates between traditional server-rendered pages, the page is ful The video below demonstrates this challenge (Video by [Rob DeLuca](https://twitter.com/robdel12), which accompanied his related article, “[Single page app routers are broken](https://medium.com/@robdel12/single-page-apps-routers-are-broken-255daa310cf)”) - +https://youtu.be/STtpXBvJmDA You can experience it yourself with the sample [company website](https://github.com/sanity-io/example-company-website-gatsby-sanity-combo) we built for the launch. We ship it in a monorepo along with a Sanity project that has content models for _people_, _project case studies_ and _blogging_. We made it pretty minimal to make it easier to extend. @@ -27,7 +27,7 @@ Add the source plugin to your Gatsby project: npm install --save gatsby-source-sanity ``` -The source plugin gives you a comprehensive GraphQL API in Gatsby for your structured content from Sanity. We strongly recommend using the [GraphiQL explorer](/docs/introducing-graphiql/) to test queries and familiarize yourself with the schema documentation. It's super useful! +The source plugin gives you a comprehensive GraphQL API in Gatsby for your structured content from Sanity. We strongly recommend using the [GraphiQL explorer](/docs/running-queries-with-graphiql/) to test queries and familiarize yourself with the schema documentation. It's super useful! Once you have installed the plugin, add this configuration to `gatsby-config.js`: diff --git a/docs/blog/2019-01-30-flamingo-case-study/index.md b/docs/blog/2019-01-30-flamingo-case-study/index.md index 4c3390338af21..955d16bd07159 100644 --- a/docs/blog/2019-01-30-flamingo-case-study/index.md +++ b/docs/blog/2019-01-30-flamingo-case-study/index.md @@ -1,5 +1,5 @@ --- -title: "Flamingo, women’s body care brand from Harry’s, chooses Gatsby for critical ecommerce launch, 5X faster page loads" +title: "Flamingo, women’s body care brand from Harry’s, chooses Gatsby for critical e-commerce launch, 5X faster page loads" date: 2019-01-30 author: Linda Watkins tags: @@ -10,13 +10,13 @@ image: "./images/flamingo.png" showImageInArticle: true --- -Since [Harry's](https://www.harrys.com/en/us) launch in 2013, it has lit up the ecommerce market for men's care products. After years of research, the team put their expertise and technology towards a new brand, [Flamingo](https://www.shopflamingo.com/), that makes body care and hair removal products designed specifically for women. The Flamingo site went live in October 2018 with thousands of users visiting the new website and hundreds of thousands of page views in the first week. The launch triggered the need for an optimized website with performance built-in, which was delivered seamlessly by Gatsby. It also carried a surprising internal reward – Harry’s and Flamingo developers are re-engaged about learning, charging into the future of modern website development and performance on the edge. +Since [Harry's](https://www.harrys.com/en/us) launch in 2013, it has lit up the e-commerce market for men's care products. After years of research, the team put their expertise and technology towards a new brand, [Flamingo](https://www.shopflamingo.com/), that makes body care and hair removal products designed specifically for women. The Flamingo site went live in October 2018 with thousands of users visiting the new website and hundreds of thousands of page views in the first week. The launch triggered the need for an optimized website with performance built-in, which was delivered seamlessly by Gatsby. It also carried a surprising internal reward – Harry’s and Flamingo developers are re-engaged about learning, charging into the future of modern website development and performance on the edge. Here’s some of our conversation with Tim Brown, Senior Software Engineer and Johnny Lin, Engineering Manager at Harry’s. ## Performance is King -When it comes to websites, performance is king, especially for ecommerce websites. For every second it takes a page to load, the more customers (and revenue) are lost. And given the success of Harry’s and the public relations push planned for the new product launch, the development team knew they were looking at a big launch with lots of traffic and absolutely no room for failure. Having built the Harry’s site from scratch, they were looking for a fresh approach with Flamingo and **their main goals were simple**: Sell products to users; and be a positive introduction to the new Flamingo brand. +When it comes to websites, performance is king, especially for e-commerce websites. For every second it takes a page to load, the more customers (and revenue) are lost. And given the success of Harry’s and the public relations push planned for the new product launch, the development team knew they were looking at a big launch with lots of traffic and absolutely no room for failure. Having built the Harry’s site from scratch, they were looking for a fresh approach with Flamingo and **their main goals were simple**: Sell products to users; and be a positive introduction to the new Flamingo brand. With that in mind, they also needed it to tick off some major development points, such as: @@ -34,11 +34,11 @@ If the team didn’t find a solution to meet these needs, they’d have to build The manual process required to make the Harry’s website perform was what they were looking to improve for the Flamingo site. And Gatsby made building a high-performing website easy because it leverages modern website tools and is built with performance already an integral part of the technology. -As an ecommerce site, performance (SEO and conversion) is super important and Gatsby takes care of this for us. +As an e-commerce site, performance (SEO and conversion) is super important and Gatsby takes care of this for us. Since Gatsby simply serves html files that are hosted on the edge (CDN: Content Delivery Network), this dramatically improves SEO. The developers can focus on other things because Gatsby just takes care of the performance. The team was excited about the image support from Gatsby that is “out-of-the-box.” They didn’t have to write code in-house, which was game changing for a team looking to lead in mobile-optimized shopping. -The Flamingo team also wanted to shake things up with content and image design by providing the fastest, most seamless shopping experience. Gatsby’s image handling helps reduce raw image sizes and speed up page load times, and serves the right resolution image depending on different screen sizes. This gave the front-end developers the ability to go beyond JS to focus on edge hosting and optimization. With a site driven by modern development tools, Gatsby’s out-of-the-box image support is the cherry on top for Flamingo. “We don’t have to write the code ourselves!” said Johnny. +The Flamingo team also wanted to shake things up with content and image design by providing the fastest, most seamless shopping experience. Gatsby’s image handling helps reduce raw image sizes and speed up page load times, and serves the right resolution image depending on different screen sizes. This gave the frontend developers the ability to go beyond JS to focus on edge hosting and optimization. With a site driven by modern development tools, Gatsby’s out-of-the-box image support is the cherry on top for Flamingo. “We don’t have to write the code ourselves!” said Johnny. The duo also praised the ease of getting up to speed on Gatsby, which gave them the ability to hire new developers and get them going in only a day. If there was familiarity with React, onboarding was successful and reduced the management of dependencies and servers. @@ -66,14 +66,14 @@ Flamingo was able to achieve their sales and brand awareness goals with the new **3) Seamless Integration with the CMS (Contentful):** The marketing leads and content creators are able to update most branded content (copy and images) on the site with zero developer involvement. This enables the team to work without interruption while giving their brand team the flexibility to make quick updates based on customer feedback. -## Inspiring a New Frontier of Ecommerce +## Inspiring a New Frontier of e-commerce -Harry’s had a website that was working, but the web team knew it could do better for Flamingo – it could move to the edge and head for a new frontier in ecommerce. +Harry’s had a website that was working, but the web team knew it could do better for Flamingo – it could move to the edge and head for a new frontier in e-commerce. Reflecting on it post-launch, the team says that Gatsby allowed them to focus on what they weren’t able to in the past – building a beautiful site that was inherently fast. But there’s been a surprise added value of Gatsby - the enthusiasm it has generated for the development team to push and learn. The team has gotten excited about learning – excited about hosting at the edge and optimizing for performance, because Gatsby makes it easy. -Front-end engineers are going beyond JS and tools and focusing on edge hosting, the modern web technology stack and optimizing for speed. The team is using this as a blueprint for how they’ll build websites in the future. +Frontend engineers are going beyond JS and tools and focusing on edge hosting, the modern web technology stack and optimizing for speed. The team is using this as a blueprint for how they’ll build websites in the future. -Gatsby delivered a performance-optimized website for Flamingo, hosted on the edge. It made it easy to onboard new developers and create engaging experiences. It improved the website visitor’s experience with speed and design and it inspired the Flamingo team in a new age of ecommerce design. +Gatsby delivered a performance-optimized website for Flamingo, hosted on the edge. It made it easy to onboard new developers and create engaging experiences. It improved the website visitor’s experience with speed and design and it inspired the Flamingo team in a new age of e-commerce design. diff --git a/docs/blog/2019-01-31-why-themes/index.md b/docs/blog/2019-01-31-why-themes/index.md index e140cae0b2061..4581d200a06d6 100644 --- a/docs/blog/2019-01-31-why-themes/index.md +++ b/docs/blog/2019-01-31-why-themes/index.md @@ -59,24 +59,24 @@ But for many other users, that want easy solutions to a common problems, they fi Some tweets to that effect: - +https://twitter.com/sebmck/status/1085279417151057920 --- - +https://twitter.com/ericalli/status/1083271854653992962 - +https://twitter.com/ericalli/status/1083271856809897985 - +https://twitter.com/ericalli/status/1083271858605023232 --- - +https://twitter.com/jtth/status/1080519113930350592 - +https://twitter.com/jtth/status/1080519116195356674 - +https://twitter.com/jtth/status/1080519116992249858 - +https://twitter.com/jtth/status/1080519117688442880 - +https://twitter.com/jtth/status/1081288682785726464 diff --git a/docs/blog/2019-02-07-pragmatic-lessons-from-converting-to-react-hooks/index.md b/docs/blog/2019-02-07-pragmatic-lessons-from-converting-to-react-hooks/index.md index c2165a2888173..0dbb91f8567c9 100644 --- a/docs/blog/2019-02-07-pragmatic-lessons-from-converting-to-react-hooks/index.md +++ b/docs/blog/2019-02-07-pragmatic-lessons-from-converting-to-react-hooks/index.md @@ -15,7 +15,7 @@ Last week I decided to install the React 16.8 alpha on a branch and experiment w The [Hooks documentation](https://reactjs.org/docs/hooks-intro.html) is well presented and an excellent resource to getting started with hooks. I previously championed the render props pattern for reusable logic and composability. However, the extra syntax often comes with tradeoffs in clarity. These concerns include: "wrapper hell" and more mental overhead to parse nested JSX structure within the component. Adding a second render prop component or ternary operator further compounds these concerns. These additional wrappers also display in the React devTools and can get out of hand. The possibility of cleaning up this syntax and providing clearer code is alluring. -```javascript +```jsx export const PureRandomQuote = ({ data: { contentfulSlideshow: { slides }, diff --git a/docs/blog/2019-02-08-government-open-data-site-with-gatsby/index.md b/docs/blog/2019-02-08-government-open-data-site-with-gatsby/index.md index f8f9eeffa6c40..c40fdc53d9071 100644 --- a/docs/blog/2019-02-08-government-open-data-site-with-gatsby/index.md +++ b/docs/blog/2019-02-08-government-open-data-site-with-gatsby/index.md @@ -65,7 +65,7 @@ We'll look at each of these in the context of our homepage redesign. As mentioned above, our most significant challenge transitioning the codebase from 18F to ONRR was operating system compatibility. We were asking a lot of our IT group, who had to vet our tech stack to ensure it met security requirements. It was a time consuming process that, even when we were granted administrative privileges, still left us with dependency errors and a parallel data-update workflow using separate machines. -Gatsby combines multiple front-end tools into one, and the packages are managed with [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/), so the scope of our IT requests is limited to widely used package managers. From what we can tell so far, running Gatsby is nearly identical regardless of the operating system you're using. As we'll describe in the next section, we were able to build a data-update workflow that we could support using our government-issued computers. +Gatsby combines multiple frontend tools into one, and the packages are managed with [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/), so the scope of our IT requests is limited to widely used package managers. From what we can tell so far, running Gatsby is nearly identical regardless of the operating system you're using. As we'll describe in the next section, we were able to build a data-update workflow that we could support using our government-issued computers. ### GraphQL @@ -182,7 +182,7 @@ Fortunately, Gatsby provides a hook into the entire lifecycle of its build proce Developers tout Gatsby's speed, and [prefetching](/docs/how-code-splitting-works/) page assets is integral to Gatsby's performance advantages. However, Gatsby isn't aware of our deployment structure, which results in an error when a page loads in the production environment. -Basically, the Jekyll part of the site deploys to a directory that isn't known to Gatsby at build time. Consequently, Gatsby creates a `pages.json` object that contains the wrong locations for files. To deal with this, we use another feature of Gatsby's client API, [`onClientEntry`](/docs/browser-apis/#onClientEntry). Using `gatsby-browser.js`, we override `pages.json` by passing the correct assets to Gatsby ([full code here](https://github.com/ONRR/doi-extractives-data/blob/dev/gatsby-site/gatsby-browser.js).) +Basically, the Jekyll part of the site deploys to a directory that isn't known to Gatsby at build time. Consequently, Gatsby creates a `pages.json` object that contains the wrong locations for files. To deal with this, we use another feature of Gatsby's client API, [`onClientEntry`](/docs/browser-apis/#onClientEntry). Using `gatsby-browser.js`, we override `pages.json` by passing the correct assets to Gatsby ([full code here](https://github.com/ONRR/doi-extractives-data/blob/d355ba54a08a4a36a23e4f3d4a06bbca517cee5f/gatsby-browser.js)). ```javascript exports.onClientEntry = () => { diff --git a/docs/blog/2019-02-11-gatsby-themes-livestream-and-example/index.md b/docs/blog/2019-02-11-gatsby-themes-livestream-and-example/index.md index a368489e8a1a8..029b62124b4be 100644 --- a/docs/blog/2019-02-11-gatsby-themes-livestream-and-example/index.md +++ b/docs/blog/2019-02-11-gatsby-themes-livestream-and-example/index.md @@ -29,9 +29,7 @@ No code. No assembling plugins. Just writing content. Recently I had the pleasure of building a theme from scratch with Gatsby’s own [John Otander](https://twitter.com/4lpine) live on [my weekly livestream](https://twitch.tv/jlengstorf). - +https://youtu.be/kN5vrRVD_6Q ## How to sign up @@ -63,4 +63,4 @@ The initial invites for the closed beta have just gone out! We’ll be talking d Curious to see Gatsby Preview in action? Watch our short demo to see how it works: - +https://youtu.be/RrQi6W_8SVQ diff --git a/docs/blog/2019-03-26-what-the-jamstack-means-for-marketing/index.md b/docs/blog/2019-03-26-what-the-jamstack-means-for-marketing/index.md index 8b8f489134484..ff736cbc5aee5 100644 --- a/docs/blog/2019-03-26-what-the-jamstack-means-for-marketing/index.md +++ b/docs/blog/2019-03-26-what-the-jamstack-means-for-marketing/index.md @@ -26,7 +26,7 @@ In terms of what this means to you as a marketer – it's essentially a modern w ![What is JAMstack](./images/whatisjamstack.jpeg) -Put simply, a JAMstack website has an unlimited ecosystem of all of the tools and services you need in the background, but the actual site itself on the front-end is just HTML. +Put simply, a JAMstack website has an unlimited ecosystem of all of the tools and services you need in the background, but the actual site itself on the frontend is just HTML. Building your marketing site on the JAMstack is an efficient and reliable way to combine all of your content and channels and serve it up as a lightning-fast website that your visitors will love. If you need to add ecommerce, paywalls, a podcast or some other content to your site in the future, your team won't have to figure out how to get everything to play ball with your CMS or build a new site from scratch. Instead they'll be able to connect new APIs or services to your existing site. @@ -64,7 +64,7 @@ Site performance and site speed is an increasingly important ranking factor. Not Using plugins to assist the speed at which you can launch marketing campaigns makes sense. But if the end result is hindered by poor performance and reduced page engagement – does it still make sense? -Ditching the concept of the plugin and opting for a JAMstack site which is "just HTML" doesn't actually mean you have to give up functionality, or suddenly need to know how to code like a front-end developer to manage a site and its content. You can still achieve the same results with an ecosystem of tools and services that are tailored specifically for you. Yes it takes some development up-front (let's be real, so does any website) - but the payoff is huge! +Ditching the concept of the plugin and opting for a JAMstack site which is "just HTML" doesn't actually mean you have to give up functionality, or suddenly need to know how to code like a frontend developer to manage a site and its content. You can still achieve the same results with an ecosystem of tools and services that are tailored specifically for you. Yes it takes some development up-front (let's be real, so does any website) - but the payoff is huge! ## Example: Ghost Docs site performance @@ -103,14 +103,14 @@ As always, there is still work to do to ensure the site ranks well for the most **Here's the stack we're using:** - [Ghost](https://ghost.org/) delivering content via the API -- A front-end built in React with [Gatsby](https://gatsbyjs.org/) (our static site generator of choice) +- A frontend built in React with [Gatsby](https://gatsbyjs.org/) (our static site generator of choice) - Deployed with [Netlifly](https://netlify.com/) (really nifty content delivery network) - [Algolia](https://algolia.com/) powering the search functionality - [Zapier](https://zapier.com/) to automate community feedback into Slack for content improvements We have also built and contributed an [advanced sitemap plugin](/packages/gatsby-plugin-advanced-sitemap/?=sitemap) which automatically builds a sitemap for any Gatsby project. -Much of the SEO functionality is being pulled directly from Ghost via the API (which has all of the structured data, custom meta data, canonicals etc built-in). This means I can manage most of the content and meta data directly in the Ghost admin client. When I save new changes they're pushed into the static front-end via Netlify – it's a fantastic workflow! +Much of the SEO functionality is being pulled directly from Ghost via the API (which has all of the structured data, custom meta data, canonicals etc built-in). This means I can manage most of the content and meta data directly in the Ghost admin client. When I save new changes they're pushed into the static frontend via Netlify – it's a fantastic workflow! ![Netlify](./images/netlify.png) diff --git a/docs/blog/2019-04-02-behind-the-scenes-what-makes-gatsby-great/index.md b/docs/blog/2019-04-02-behind-the-scenes-what-makes-gatsby-great/index.md index 33f6c58ce7daf..ed15776fdb9ad 100644 --- a/docs/blog/2019-04-02-behind-the-scenes-what-makes-gatsby-great/index.md +++ b/docs/blog/2019-04-02-behind-the-scenes-what-makes-gatsby-great/index.md @@ -97,8 +97,7 @@ This is the central idea of server-side rendering. Gatsby uses server-side APIs ### Zero Node.js servers required ✋ - - +https://twitter.com/jlengstorf/status/1090659696233463808 To begin describing why build-time SSR is so appealing, let's first take a look at what a deploy and release looks like if we don't require a server. What's required for a typical set-up for deploying static content (which Gatsby produces)? It looks something like: @@ -107,7 +106,7 @@ To begin describing why build-time SSR is so appealing, let's first take a look - Creating a bucket/location to host static content (like S3, Google Cloud Storage, etc.) - Setting up a [Domain Name System (DNS)](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_domain_name) to make your content reachable via a pretty URL, e.g. gatsbyjs.org - Routing the CDN layer in front of your static content -- Set up a Continuous Integration (CI) environment so we can build and deploy code to production with minimal impact to end-users +- Set up a Continuous Integration (CI) environment so we can build and deploy code to production with minimal impact to end users ... and, that's it! We're done as far as setup goes! We can use _whatever_ stack you prefer here. Netlify? [You bet.](https://www.gatsbyjs.org/docs/deploying-to-netlify) More a fan of AWS? [Of course.](https://www.gatsbyjs.org/docs/deploying-to-aws-amplify/) Heroku? [Yup.](https://www.gatsbyjs.org/docs/deploying-to-heroku/) You get the idea. Gatsby can be deployed anywhere easily and cheaply. @@ -152,7 +151,7 @@ Gatsby--like other tools--uses the filesystem as a convention for mapping to rou _also note we expose a [programatic API](/docs/node-apis/#createPages) for dynamic route creation_ -``` +```text ├── src/ ├── pages/ └── about.js @@ -201,7 +200,7 @@ Pretty vanilla looking component! We are rendering a `form` with some validation We use code-splitting (enabled via our internalized dependency [Webpack](https://webpack.js.org)), and in particular, our approach prioritizes app-level dependencies (libraries used by the majority or all routes) coupled with route-based code splitting for dependencies that are likely only used on a particular route. To more fully understand this, let's take a look at a sample structure produced by our build process: `gatsby build`. -```title=public/ +```text:title=public/ ├── 404 │ └── index.html ├── 9-f5d9c17474395c2890a3.js # highlight-line @@ -325,7 +324,7 @@ _Want to dive deeper? Much of this is encapsulated in our internal [Webpack conf ## Modern APIs in Gatsby -Gatsby uses modern browser APIs to both maximize performance and user experience--which oftentimes go hand in hand!--only loading assets when they are necessary and likely to be requested. Specifically, the following APIs are crucial to the end-user experience in Gatsby: +Gatsby uses modern browser APIs to both maximize performance and user experience--which oftentimes go hand in hand!--only loading assets when they are necessary and likely to be requested. Specifically, the following APIs are crucial to the end user experience in Gatsby: 1. `IntersectionObserver` - an API to conditionally perform some action when an element enters the viewport/view 1. `link rel="prefetch"` - an API to prefetch resources in the background when the browser is idle @@ -507,7 +506,7 @@ If you check out the [pull request](https://github.com/DSchau/gatsby-perf-audit/ In this pull request, I _intentionally_ introduce a few dependencies like Bootstrap, lodash, and... jQuery because let's at least make the performance problems clear and obvious! If you check out the [CI logs](https://circleci.com/gh/DSchau/gatsby-perf-audit/13?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link) you can see the output from the failing CI check: -``` +```text ● performance audit expect(received).toBe(expected) // Object.is equality diff --git a/docs/blog/2019-04-08-meet-the-gatsby-team-at-drupalcon-seattle-jamstack-conf-nyc-and-jsheroes/index.md b/docs/blog/2019-04-08-meet-the-gatsby-team-at-drupalcon-seattle-jamstack-conf-nyc-and-jsheroes/index.md index 63fd42690f89e..67ce40b5f94c3 100644 --- a/docs/blog/2019-04-08-meet-the-gatsby-team-at-drupalcon-seattle-jamstack-conf-nyc-and-jsheroes/index.md +++ b/docs/blog/2019-04-08-meet-the-gatsby-team-at-drupalcon-seattle-jamstack-conf-nyc-and-jsheroes/index.md @@ -31,7 +31,7 @@ Four of our team will be behind the table at various times during DrupalCon, inc On Thursday, during the DrupalCon closing plenary, **[Marcy Sutton](https://twitter.com/marcysutton)**, our Head of Learning, will deliver one of the keynotes to close out DrupalCon with a discussion of how to design and build software that fosters inclusion. [“JavaScript and Civil Rights”](https://events.drupal.org/seattle2019/sessions/javascript-and-civil-rights) will take place in Hall 4E from 4:15-5:30pm on Thursday. -“As designers and developers of software, we act as gatekeepers in people’s lives more than we realize,” states the keynote abstract. “Now more than ever, it is our duty to create digital experiences that honor our users’ rights to inclusion–no matter where they live, or how they access the Web. This applies to both authors and contributors, as well as end-users and consumers; we must do more to protect everyone’s rights to access, safety, security, and privacy.” +“As designers and developers of software, we act as gatekeepers in people’s lives more than we realize,” states the keynote abstract. “Now more than ever, it is our duty to create digital experiences that honor our users’ rights to inclusion–no matter where they live, or how they access the Web. This applies to both authors and contributors, as well as end users and consumers; we must do more to protect everyone’s rights to access, safety, security, and privacy.” ### Meet Gatsby CEO Kyle Mathews at Decoupled Summit diff --git a/docs/blog/2019-04-19-gatsby-why-we-write/index.md b/docs/blog/2019-04-19-gatsby-why-we-write/index.md index be666013baa6d..4016d0345047c 100644 --- a/docs/blog/2019-04-19-gatsby-why-we-write/index.md +++ b/docs/blog/2019-04-19-gatsby-why-we-write/index.md @@ -10,7 +10,7 @@ If you're a Gatsby community member, you may have noticed something: we write _a Community members are often surprised by the comprehensiveness of our [documentation](/docs/). We publish new articles on this blog multiple times per week, from both the core team and the community. - +https://twitter.com/mattconvente/status/1099706762897342465 Writing isn't something we just do because we love it (although we do). Writing is core to who we are as a project, a company, and a community. @@ -96,7 +96,7 @@ In the docs, things are structured hierarchically, so usually content is mostly But outside the docs, that's far from the case. We have blog posts, [using-\* example sites / guides](https://github.com/gatsbyjs/gatsby/tree/master/examples), [starters](/starters/), conference talks, podcast appearances, tweets, and whatever Gatsby community members dream up and publish! -**It's a constant challenge to organize these in ways that are useful and obvious for the end-user**. We're always attacking this in five or ten different ways -- discoverability via search, cross-linking, hierarchy, navbars and breadcrumbs, turning conference talks into blog posts and blog posts into docs. +**It's a constant challenge to organize these in ways that are useful and obvious for the end user**. We're always attacking this in five or ten different ways -- discoverability via search, cross-linking, hierarchy, navbars and breadcrumbs, turning conference talks into blog posts and blog posts into docs. Our goal is to make it easy for the user to gather relevant context, know where to look when they get stuck, and feel confident that they can make it if they keep on reading, learning, and trying. diff --git a/docs/blog/2019-04-26-how-to-build-a-blog-with-wordpress-and-gatsby-part-1/index.md b/docs/blog/2019-04-26-how-to-build-a-blog-with-wordpress-and-gatsby-part-1/index.md index e375ceeecbc10..07a99d03cc355 100644 --- a/docs/blog/2019-04-26-how-to-build-a-blog-with-wordpress-and-gatsby-part-1/index.md +++ b/docs/blog/2019-04-26-how-to-build-a-blog-with-wordpress-and-gatsby-part-1/index.md @@ -130,6 +130,6 @@ Not to be too anti-climactic, but there's really not a ton more to do on the Wor That being said, if you are creating custom content types for your blog you will need a way to differentiate them in ACF. Creating a custom page template will serve this purpose so you can filter on the page template to show the custom fields. You can also use the page template to filter in your Gatsby project to make sure you are receiving the desired fields for a given page. -If you have any questions, you can hit me up on twitter at [@iam_timsmith](https://twitter.com/iam_timsmith)! +If you have any questions, you can hit me up on Twitter at [@iam_timsmith](https://twitter.com/iam_timsmith)! See you in [How To Build A Blog with WordPress and Gatsby.js - Part 2](/blog/2019-04-30-how-to-build-a-blog-with-wordpress-and-gatsby-part-2)! diff --git a/docs/blog/2019-04-29-component-shadowing/index.md b/docs/blog/2019-04-29-component-shadowing/index.md index fe8dad6d64e5e..5d9ff55ab8262 100644 --- a/docs/blog/2019-04-29-component-shadowing/index.md +++ b/docs/blog/2019-04-29-component-shadowing/index.md @@ -38,7 +38,7 @@ you can do so with Component Shadowing. `gatsby-theme-blog` has the following file structure (some files have been omitted for brevity): -``` +```text gatsby-theme-blog └── src ├── components @@ -64,7 +64,7 @@ used _instead_ of a file with the same name in the theme's `src` directory: This means that `user-site/src/gatsby-theme-blog/components/bio.js` will be rendered in place of `gatsby-theme-blog/src/components/bio.js`: -```js:title=src/gatsby-theme-blog/components/bio.js +```jsx:title=src/gatsby-theme-blog/components/bio.js import React from "react" export default () =>

My new bio component!

@@ -73,7 +73,7 @@ export default () =>

My new bio component!

With a successful shadow of the `Bio` component you'll result in the following directory tree: -``` +```text user-site └── src └── gatsby-theme-blog @@ -111,7 +111,7 @@ export default { You'll result in the following directory tree: -``` +```text user-site └── src └── gatsby-theme-blog @@ -142,5 +142,5 @@ Gatsby Themes and is currently being used in production. ## Further reading -- [Component Shadowing Documentation](/docs/themes/api-reference/#component-shadowing) +- [Component Shadowing Documentation](/docs/themes/shadowing/) - [Latent Component Shadowing](https://johno.com/latent-component-shadowing) diff --git a/docs/blog/2019-04-30-how-to-build-a-blog-with-wordpress-and-gatsby-part-2/index.md b/docs/blog/2019-04-30-how-to-build-a-blog-with-wordpress-and-gatsby-part-2/index.md index 8fdd9e7caaec1..ffb52f9968ed5 100644 --- a/docs/blog/2019-04-30-how-to-build-a-blog-with-wordpress-and-gatsby-part-2/index.md +++ b/docs/blog/2019-04-30-how-to-build-a-blog-with-wordpress-and-gatsby-part-2/index.md @@ -56,14 +56,13 @@ Now that you have your project created, let's take a look inside. You will see a - **README.md**: Markdown file with instructions for use - **gatsby-browser.js**: Gatsby Browser API stuff goes here. Global style calls go here too - **gatsby-config.js**: Configuration for your project including meta data and plugins -- **gatsby-node.js**: Where you tell gatsby to build pages from a template using provided data +- **gatsby-node.js**: Where you tell Gatsby to build pages from a template using provided data - **gatsby-ssr.js**: Gatsby Server Side Rendering APIs go here - **package.json**: File which holds custom scripts, dependency information, etc These files will be present in all Gatsby starters you use, so it's worth your time to have at least a basic level of understanding with each one. Let's take a look and see what dependencies and plugins you have by default. Open up the `package.json` file and scroll down to dependencies. This will tell you what packages you already have. Mine looks like this: -```json -// package.json +```json:title=package.json { "name": "gatsby-starter-default", "private": true, @@ -133,7 +132,7 @@ gatsby develop After running that command, you can visit [localhost:8000](http://localhost:8000) in the browser and you should see the site pictured below: -![Initial appearance of Gatsby.js starter](images/gatsby1.png) +![Initial appearance of Gatsby.js starter](./images/gatsby1.png) The site provides a navbar with a link going back to the homepage. There is also a bit of content with a link to page 2 which then provides a link back to page 1. It's a very simple site, but already you can see how fast Gatsby.js is. @@ -149,8 +148,7 @@ npm install gatsby-source-wordpress gatsby-plugin-sitemap Looking at your `package.json` file will reveal that each of these packages have been added to the project, but this isn't enough to start using the gatsby-plugin files. You first need to add them to the `gatsby-config.js` file. Luckily, the docs for these plugins are awesome and do a good job explaining all of this. I'd recommend you take a look at them to find out what each of the settings does, but I'll provide the code for the `gatsby-config.js` file after adding all of these plugins to your site: -```javascript -// gatsby-config.js +```javascript:title=gatsby-config.js module.exports = { siteMetadata: { title: `Gatsby Default Starter`, @@ -228,7 +226,7 @@ If the Gatsby site is currently running, you need to stop it and restart it so i Once you've restarted your server, you can visit [http://localhost:8000/\_\_\_graphql](http://localhost:8000/___graphql) to use the "graphical" playground. Here, you can use GraphQL to query your data for testing purposes. You should create opening and closing curly braces and then you can use shift+space (or ctrl+space on windows) to get suggestions. Once you have the data you want, you will be able to paste the query into your components, pages, and templates so you can use the information available. Here's what my query looks like for now: -![GraphQL query tests](images/gatsby2.png) +![GraphQL query tests](./images/gatsby2.png) You may notice that there are several drilldowns inside of the `acf` field. This is saying "hey, look for the ACF field called feat_img and get the local, optimized versions of these images so you can use them". Gatsby also provides fragments which means inside of your application you could just put `...GatsbyImageSharpSizes` instead of drilling down so far and Gatsby will know what to do with it. @@ -250,8 +248,7 @@ Unless there is some special functionality needed for blog posts, you can just [ Below is the code I'm using for the template starter. This is just to make sure things are working after you finish setting up your `gatsby-node.js` logic. Once you know the page is being created, you will update the template to display correctly. -```javascript -// src/templates/BlogPost.js +```jsx:title=src/templates/BlogPost.js import React from "react" import Layout from "../components/layout" @@ -279,9 +276,7 @@ The gatsby-node.js file allows you to pull in a template file, then query your d The code below pulls in the data for blog posts from WordPress and creates a page for each one using the createPage API provided by Gatsby. It is also much easier to pull in templates in this file using the path package, so I installed it using `npm install path`. -```javascript -// gatsby-node.js - +```javascript:title=gatsby-node.js /** * Implement Gatsby's Node APIs in this file. * @@ -331,14 +326,13 @@ Just like before, you will need to restart your development server to see these You can now see all of the pages available and clicking on one should take you to the blog post template you created earlier that just shows Hello World. If this is what you're seeing, congrats! You're ready to move to the next section. -![See a list of pages on the development 404 page](images/gatsby3.png) +![See a list of pages on the development 404 page](./images/gatsby3.png) ## Updating our blog post template Now that you have pages being created at the desired locations, you should update your blog post template to display the appropriate data. Although you need to make some changes, you will keep it as a stateless functional component. The code below will create your template. I would like to point out that you are using GraphQL to query the information which is then used as a prop called data. -```javascript -// src/templates/BlogPostTemplate.js +```jsx:title=src/templates/BlogPostTemplate.js import React from "react" import { graphql } from "gatsby" import Img from "gatsby-image" @@ -402,7 +396,7 @@ The SEO component allows you to pass in dynamic data such as title, description, Here's what your completed Blog Post looks like after you update the template: -![Completed Blog Post Page](images/gatsby4.png) +![Completed Blog Post Page](./images/gatsby4.png) ## Wrapping up blog posts diff --git a/docs/blog/2019-05-02-growing-housecall-pro-by-973-percent/index.md b/docs/blog/2019-05-02-growing-housecall-pro-by-973-percent/index.md index 419a71bc947a5..75db3bd10736a 100644 --- a/docs/blog/2019-05-02-growing-housecall-pro-by-973-percent/index.md +++ b/docs/blog/2019-05-02-growing-housecall-pro-by-973-percent/index.md @@ -54,7 +54,7 @@ With Gatsby, we can generate several hundred pages for all of the industries tha By providing data in the form of a JSON object, we can parse and iterate over each industry in which to generate a new page. Whether this JSON data comes from a file, or a CMS via an API call, or our own database, Gatsby provides the flexibility to build in any way we need. -This has dramatically decreased developer time and rocketed the speed of page creation. We went from building several pages a week using front-end developers, to building out dozens of pages a day with professional content creators. +This has dramatically decreased developer time and rocketed the speed of page creation. We went from building several pages a week using frontend developers, to building out dozens of pages a day with professional content creators. Below is an example of one of our live industry pages (in this case Heating/Air Conditioning). Each industry page follows the same template, and content authors can build out new industries, complete with whatever copy, icons, images, and animations they need to allow each to stand out as its own work of art. diff --git a/docs/blog/2019-05-02-how-to-build-a-blog-with-wordpress-and-gatsby-part-3/index.md b/docs/blog/2019-05-02-how-to-build-a-blog-with-wordpress-and-gatsby-part-3/index.md index 2c70ccbbf0399..26451a7246d5c 100644 --- a/docs/blog/2019-05-02-how-to-build-a-blog-with-wordpress-and-gatsby-part-3/index.md +++ b/docs/blog/2019-05-02-how-to-build-a-blog-with-wordpress-and-gatsby-part-3/index.md @@ -30,8 +30,7 @@ Just like with the blog post template, you can probably just use a [stateless fu I will go ahead and start off with a generic template again and then fill it out later with the appropriate data. The code below will get a simple template created for us to use for pages for now: -```javascript -// src/templates/Page.js +```jsx:title=src/templates/Page.js import React from "react" import Layout from "../components/layout" @@ -48,9 +47,7 @@ export default PageTemplate Awesome! Now that you have your page template created, you can add pages to the gatsby-node.js file. First, you will import the template just like you did for the BlogPostTemplate. Then you will add the allWordpressPage piece to the GraphQL query. Finally, you will use the `createPage` API to create pages based on the information retrieved from the GraphQL query and use the Page template to build the pages automatically. Below is the finished gatsby-node.js file. See if you can spot the things I mentioned for the pages. -```javascript -// gatsby-node.js - +```javascript:title=gatsby-node.js /** * Implement Gatsby's Node APIs in this file. * @@ -117,7 +114,7 @@ exports.createPages = async ({ graphql, actions, reporter }) => { Just like before, you can test this to make sure the pages were created as expected by starting your development server and visiting [localhost:8000/stuff](http://localhost:8000/stuff) to get a list of all of the available pages. Again, this is only available in a development environment since a live site will show a different 404 page. You should see an `/about` page and a `/sample-page` page in there. If so, your gatsby-node.js file worked and you can update the template to show the data you want. -![See a list of available pages](images/gatsby1.png) +![See a list of available pages](./images/gatsby1.png) ## Updating the page template @@ -125,8 +122,7 @@ Since you have your page routes set up, you can start adding to the template. Th The end result is a basic component as shown below: -```javascript -// src/templates/Page.js +```jsx:title=src/templates/Page.js import React from "react" import { graphql } from "gatsby" import Layout from "../components/layout.js" @@ -175,8 +171,7 @@ You can also see that the starter default comes with a few pages already in the Since you want your blog to show up on the homepage, you can edit the file called `index.js` to do this. Let's take a look at this file before you make any changes: -```javascript -// src/pages/index.js +```jsx:title=src/pages/index.js import React from "react" import { Link } from "gatsby" @@ -204,8 +199,7 @@ You are going to remove everything after the SEO tag but before the closing Layo To keep things basic, you'll just create a list of recent blog posts with an image, title, author, date, and excerpt. Each of the items in this list should link to the individual blog post for readers. Below is the code to create this layout. It's pretty straightforward and looks very similar to your blog post template with the exception of the map function which iterates over the items in an array. -```javascript -// src/pages/index.js +```jsx:title=src/pages/index.js import React from "react" import { graphql, Link } from "gatsby" import Img from "gatsby-image" @@ -279,7 +273,7 @@ export const query = graphql` And here's what it looks like when you visit the homepage of your blog: -![Finished blog home page](images/gatsby2.png) +![Finished blog home page](./images/gatsby2.png) It's looking pretty good so far. You're getting pretty close to being done, you just have a few more things to change and you're ready to start blogging! @@ -296,10 +290,9 @@ One of the first things I notice about the blog pictured above is the header. It ### In the gatsby-config.js file -In the gatsby-config.js file, you can see a piece at the top called `siteMetaData` with a title, description, and author. This is where some basic information is kept about the project for the SEO component, but also for the site name. +In the gatsby-config.js file, you can see a piece at the top called `siteMetadata` with a title, description, and author. This is where some basic information is kept about the project for the SEO component, but also for the site name. -```javascript -// gatsby-config.js +```javascript:title=gatsby-config.js module.exports = { siteMetadata: { title: `Gatsby Default Starter`, @@ -316,12 +309,11 @@ The title you're seeing in the header comes from the title listed here. You can Since you are building a blog using WordPress and want your users to have full control over the data, you should get your site name from WordPress so if it ever changes the user can update it. Fortunately, WordPress makes this available to us through the API, so you can query it in GraphQL like so: -![Graphql query to get siteName from WordPress](images/gatsby3.png) +![Graphql query to get siteName from WordPress](./images/gatsby3.png) Using queries works a bit differently inside of components. Rather than just writing a query which drops data into your page or template, you have to use a new component called `StaticQuery` which is designed specifically for using queries inside of components. -```javascript -// src/components/header.js +```jsx:title=src/components/header.js import { Link } from "gatsby" import PropTypes from "prop-types" import React from "react" @@ -368,8 +360,7 @@ export default Header If you take a quick look at the existing header component, you will see that a site-title is being passed in as a prop which is then used to display the site title from `gatsby-config.js` in the header. What you are going to do is use the `StaticQuery` component provided by Gatsby and use a query prop to run your query and then a render prop to actually render out your component like you normally would. You can see below how you do this in code: -```javascript -// src/components/header.js +```jsx:title=src/components/header.js import { StaticQuery, graphql, Link } from "gatsby" import React from "react" @@ -421,7 +412,7 @@ export default Header The header component above looks a little different than it originally did, but as you start to dig into it a bit more you can see it hasn't changed much. You essentially just wrapped your header in the StaticQuery component and then ran your query inside of that component to give the header the necessary data. -![Your Gatsby.js blog after updating the header component](images/gatsby4.png) +![Your Gatsby.js blog after updating the header component](./images/gatsby4.png) ### Adding a Menu to the Header @@ -429,8 +420,7 @@ Let's take it a step further and say your user wants a menu in the header that h When you were setting your gatsby-config.js file in the [second part of the series](/blog/2019-04-30-how-to-build-a-blog-with-wordpress-and-gatsby-part-2), you just stuck with the default routes provided in the gatsby-source-wordpress docs. The WP API Menus plugin creates a few new routes for those endpoints, so the first thing you need to do is add these endpoints to the gatsby-config.js file. -```javascript -// gatsby-config.js +```javascript:title=gatsby-config.js module.exports = { siteMetadata: { title: `Gatsby Default Starter`, @@ -505,12 +495,11 @@ module.exports = { If you look at the code above, you'll notice you have added two new routes to the gatsby-source-wordpress. These routes are created automatically by the plugin inside of WordPress without any additional configuration. Remember, after making changes to files outside of the src folder, you need to restart your development server by running `gatsby develop`. After restarting, you can visit [http://localhost:8000/\_\_\_graphql](http://localhost:8000/___graphql) and query for the menu information, which will look like the screenshot below. -![GraphiQL query to get menu items from WordPress](images/gatsby6.png) +![GraphiQL query to get menu items from WordPress](./images/gatsby6.png) The final step is to add this query into your static query and create the menu itself in the header component. You can just drop this in under the wordpressSiteMetadata piece. Once you have it added into the query, you can just use a `map()` function to iterate over the menu items and create it dynamically, allowing the user to update it through WordPress. Doing it this way does require us to specify which menu you want, so you need the name of the menu which is set in WordPress. In this case, your menu is called Main Menu so you will use that in your query. -```javascript -// src/components/header.js +```jsx:title=src/components/header.js import { StaticQuery, graphql, Link } from "gatsby" import React from "react" @@ -584,7 +573,7 @@ export default Header That's a good looking component! Let's see what it looks like when you visit the site: -![Blog after adding menu to header](images/gatsby7.png) +![Blog after adding menu to header](./images/gatsby7.png) ## Wrapping up diff --git a/docs/blog/2019-05-15-enterprise-gatsby-how-to-reduce-your-digital-total-cost-of-ownership-with-gatsby/index.md b/docs/blog/2019-05-15-enterprise-gatsby-how-to-reduce-your-digital-total-cost-of-ownership-with-gatsby/index.md index d1f813a9b9421..1eb44f8a2f7be 100644 --- a/docs/blog/2019-05-15-enterprise-gatsby-how-to-reduce-your-digital-total-cost-of-ownership-with-gatsby/index.md +++ b/docs/blog/2019-05-15-enterprise-gatsby-how-to-reduce-your-digital-total-cost-of-ownership-with-gatsby/index.md @@ -37,7 +37,7 @@ Enterprise users seeking a quick way to limit their TCO may look to hosting prod One of the most common complaints I hear from enterprise users of CMSs is the paucity of available affordable developers to build out the digital architecture of their dreams. While there has always been downward pressure on the number of available Adobe and Sitecore developers due to their proprietary nature, the decline in the prevalence of Drupal and WordPress developers has reflected a larger trend. -JavaScript is quickly winning out as the only language that can operate shared code across both client and server (in a paradigm known as [_universal_ or _isomorphic_ JavaScript](https://dri.es/a-history-of-javascript-across-the-stack)), and it has seen incredible growth in the web development community. In every year since 2014, JavaScript and Java have edged out other programming languages as the [most commonly used on GitHub](https://octoverse.github.com/projects#languages). Meanwhile, PHP fell from third to fourth, and other previously popular languages like Ruby are seeing even steeper declines. +JavaScript is quickly winning out as the only language that can operate shared code across both client and server (in a paradigm known as [_universal_ or _isomorphic_ JavaScript](https://dri.es/a-history-of-javascript-across-the-stack)), and it has seen incredible growth in the web development community. In every year since 2014, JavaScript and Java have edged out other programming languages as the [most commonly used on GitHub](https://octoverse.github.com/#top-languages). Meanwhile, PHP fell from third to fourth, and other previously popular languages like Ruby are seeing even steeper declines. As university programs and coding bootcamps continue to swap previously intermixed curricula with JavaScript-only pedagogies, JavaScript adoption has continued to widen. In Stack Overflow’s yearly Developer Survey, JavaScript has posted increases every year since 2016, when it was [voted most popular language](https://insights.stackoverflow.com/survey/2016#technology-most-popular-technologies) by 55.4% of respondents. In 2019, [that percentage was 67.8%](https://insights.stackoverflow.com/survey/2019#most-popular-technologies). While these data only paint part of the picture, it is clear that JavaScript has emerged as the runaway victor when it comes to languages that cross the server–client divide. @@ -47,7 +47,7 @@ For enterprise users, hiring more affordable developers with a flexible, more mo ## Performance: Optimization at every page interaction -Enterprises today expect fast performance at every stage of page interaction: first load, moving between pages, and dynamic updates and transitions that occur after page load. Traditional CMSs like Adobe, Drupal, Sitecore, and WordPress have long struggled with performance bottlenecks at each step of this process, whether it is due to an oversized server bootstrap, overly stale cache, a lack of prefetching across linked pages, or an unwieldy Ajax or JavaScript API for front-end interactions. As new users continue to acquire smartphones at a high rate in low-bandwidth network areas, these concerns become even more paramount. +Enterprises today expect fast performance at every stage of page interaction: first load, moving between pages, and dynamic updates and transitions that occur after page load. Traditional CMSs like Adobe, Drupal, Sitecore, and WordPress have long struggled with performance bottlenecks at each step of this process, whether it is due to an oversized server bootstrap, overly stale cache, a lack of prefetching across linked pages, or an unwieldy Ajax or JavaScript API for frontend interactions. As new users continue to acquire smartphones at a high rate in low-bandwidth network areas, these concerns become even more paramount. Gatsby solves all of these problems thanks to its focus on rendering server-side markup first and foremost before handing off all asynchronous rendering to a React application initialized client-side. With its prefetching, Gatsby users can rest assured that any link click will lead to an instantaneous render rather than a roundtrip back to the server. Moreover, because React controls all state after the page has loaded, the management of interactive functionality becomes a much simpler consideration. Our very own [Dustin Schau](https://dustinschau.com/) recently penned a deep dive into [what makes Gatsby’s performance so incredible](https://www.gatsbyjs.org/blog/2019-04-02-behind-the-scenes-what-makes-gatsby-great/). @@ -79,7 +79,7 @@ Fortunately, Gatsby is currently hard at work on supporting incremental builds f At Gatsby, we’ve heard many questions about whether Gatsby is truly ready for the enterprise. The short answer is yes or very soon, depending on your requirements. After all, Gatsby currently lacks many of the features that end-to-end CMSs routinely tout such as contextual editing and layout manipulation. At the moment it also doesn’t have some of the features needed to support compliance in the evolving digital landscape such as HIPAA, FEDRamp, and others, but they are on our radar. -Nonetheless, Gatsby makes up what it lacks at the moment in the administrative experience with benefits in other ways that make it a uniquely compelling choice for enterprises seeking an ambitious developer-first solution paired with sensible defaults for performance and security. If you are seeking a decoupled CMS solution that includes a fast-off-the-shelf front end and security benefits that stand up to any traditional CMS currently in vogue, Gatsby should be at the top of your list of considerations. +Nonetheless, Gatsby makes up what it lacks at the moment in the administrative experience with benefits in other ways that make it a uniquely compelling choice for enterprises seeking an ambitious developer-first solution paired with sensible defaults for performance and security. If you are seeking a decoupled CMS solution that includes a fast-off-the-shelf frontend and security benefits that stand up to any traditional CMS currently in vogue, Gatsby should be at the top of your list of considerations. We’re just getting started! In addition to our ongoing beta for [Gatsby Preview](https://gatsbyjs.com/preview), soon to be opened up to the general public in open beta ([join the waitlist](https://gatsbyjs.com/preview) today!), we’re hard at work on features we know will be relevant not only to Gatsby’s early adopters but also enterprise users who require fast deployment times in addition to live high-fidelity preview and quicker turnarounds in content production workflows. diff --git a/docs/blog/2019-05-17-improvements-to-schema-customization/index.md b/docs/blog/2019-05-17-improvements-to-schema-customization/index.md index b65974c93a60b..5abbd6be3b3bc 100644 --- a/docs/blog/2019-05-17-improvements-to-schema-customization/index.md +++ b/docs/blog/2019-05-17-improvements-to-schema-customization/index.md @@ -63,7 +63,7 @@ Here are suggested changes to your code if you are using schema customization al 1. Add resolver directives to fields 2. Add `@infer` or `@dontInfer` to your type if you don't have it already -```graphql:title=gatsby-node.js +```javascript:title=gatsby-node.js exports.sourceNodes = function sourceNodes({ actions }) { const { createTypes } = actions @@ -77,7 +77,7 @@ exports.sourceNodes = function sourceNodes({ actions }) { } ``` -```graphql:title=gatsby-node.js +```javascript:title=gatsby-node.js exports.sourceNodes = function sourceNodes({ actions }) { const { createTypes } = actions @@ -107,7 +107,7 @@ Add resolver and resolver options (such as arguments) to the given field. There characters that are invalid in GraphQL, `proxy` allows to explicitly proxy those properties to fields with valid field names. Takes a `from` arg. -```graphql:title=gatsby-node.js +```javascript:title=gatsby-node.js exports.sourceNodes = function sourceNodes({ actions }) { const { createTypes } = actions diff --git a/docs/blog/2019-05-22-setting-up-yarn-workspaces-for-theme-development/index.md b/docs/blog/2019-05-22-setting-up-yarn-workspaces-for-theme-development/index.md index b59ad5e929315..2c94141b1997e 100644 --- a/docs/blog/2019-05-22-setting-up-yarn-workspaces-for-theme-development/index.md +++ b/docs/blog/2019-05-22-setting-up-yarn-workspaces-for-theme-development/index.md @@ -39,7 +39,7 @@ This is currently a limitation of Gatsby theme shadowing, not Yarn workspaces. Your directory structure should now look like this: -``` +```text example/ package.json gatsby-theme-example-workspaces/ @@ -107,7 +107,7 @@ module.exports = { Add a `src/pages/` directory and add a _Hello, world_ page. -```js:title=example/src/pages/index.js +```jsx:title=example/src/pages/index.js import React from "react" export default props =>

Hello, world

@@ -173,7 +173,7 @@ module.exports = { Make a `src/pages` directory in the theme and add a demo page. -```js:title=gatsby-theme-example-workspaces/src/pages/theme-page.js +```jsx:title=gatsby-theme-example-workspaces/src/pages/theme-page.js import React from "react" export default props =>

Hello, from the theme!

diff --git a/docs/blog/2019-05-29-the-great-gatsby-gathering-nyc/index.md b/docs/blog/2019-05-29-the-great-gatsby-gathering-nyc/index.md index d356f60d31a65..21c4b0ff2eb1c 100644 --- a/docs/blog/2019-05-29-the-great-gatsby-gathering-nyc/index.md +++ b/docs/blog/2019-05-29-the-great-gatsby-gathering-nyc/index.md @@ -7,7 +7,7 @@ tags: - gatsby-inc --- -"You belong here" is a core tenet of both Gatsby, the open source project, and Gatsby, the enterprise. Involving the developer community in this adventure to the front end far horizon has been our prime directive ever since launch. In the past four years we have worked alongside a constellation of 1,900+ contributors helping to build Gatsbyjs and created a robust library of useful plugins. All along, Gatsby’s competitive advantage has been the strength of its community and ecosystem: we came this far this fast thanks to users who rolled up their sleeves and pitched in. +"You belong here" is a core tenet of both Gatsby, the open source project, and Gatsby, the enterprise. Involving the developer community in this adventure to the frontend far horizon has been our prime directive ever since launch. In the past four years we have worked alongside a constellation of 1,900+ contributors helping to build Gatsbyjs and created a robust library of useful plugins. All along, Gatsby’s competitive advantage has been the strength of its community and ecosystem: we came this far this fast thanks to users who rolled up their sleeves and pitched in. Gatsby Days is one of our ways to say thank you. ([Another is tasty swag for contributors)](https://www.gatsbyjs.org/contributing/contributor-swag/). This series of single-day conferences aims to connect the Gatsby community with Gatsby’s creators, core team and most of all each other. Our first event was held in San Francisco this past December, and our second Gatsby Days gathering just took place in New York on May 6th. diff --git a/docs/blog/2019-06-08-delicious-simplicity-case-study-part-1/index.md b/docs/blog/2019-06-08-delicious-simplicity-case-study-part-1/index.md index de434e83b1cf3..4f7596797988b 100644 --- a/docs/blog/2019-06-08-delicious-simplicity-case-study-part-1/index.md +++ b/docs/blog/2019-06-08-delicious-simplicity-case-study-part-1/index.md @@ -26,7 +26,7 @@ So Brian kept trying, and not finding, a better way to develop projects and mana ## Swiping Right for Gatsby -There was only one potential hurdle to true romance: convincing the Delicious Simplicity team. They were mainly front end developers used to working with HTML/CSS, maybe a little jQuery. Stepping across the divide into the backend to confront the complexities of a headless CMS was not in their comfort zone. But Brian was confident he could get them there. +There was only one potential hurdle to true romance: convincing the Delicious Simplicity team. They were mainly frontend developers used to working with HTML/CSS, maybe a little jQuery. Stepping across the divide into the backend to confront the complexities of a headless CMS was not in their comfort zone. But Brian was confident he could get them there. “Once I got hands on with Gatsby, I was shocked how quickly I managed to pick things up. The syntax was just so intuitive, which made it easy to digest,” he says. There were definitely some growing pains -- the team had little experience with React or Node, and some of the devs found the new component-based way of thinking overwhelming to grasp at first. But they eventually fell in love with Gatsby and now don’t want to work in anything else. diff --git a/docs/blog/2019-06-10-how-to-recognize-when-gatsby-is-a-good-fit-for-your-client/index.md b/docs/blog/2019-06-10-how-to-recognize-when-gatsby-is-a-good-fit-for-your-client/index.md index a62a238bd1247..a28735c4d1fa5 100644 --- a/docs/blog/2019-06-10-how-to-recognize-when-gatsby-is-a-good-fit-for-your-client/index.md +++ b/docs/blog/2019-06-10-how-to-recognize-when-gatsby-is-a-good-fit-for-your-client/index.md @@ -21,13 +21,13 @@ In November, I began a conversation with a mid-sized retail and digital commerce - First, the content editorial experience for staff was so poor that multiple team members had actually quit because of it (saying as much in their exit interview). - Second, development velocity was painfully slow because of the complex implementation. -Once I talked about the value of a microservices approach, the unbeatable fast speed of a React powered front end, preview, and the partial builds feature on the roadmap Gatsby (and was honest about the trade offs), the client enthusiastically wanted to know more, and they are likely proceeding with a Gatsby stack for their replatform. +Once I talked about the value of a microservices approach, the unbeatable fast speed of a React powered frontend, preview, and the partial builds feature on the roadmap Gatsby (and was honest about the trade offs), the client enthusiastically wanted to know more, and they are likely proceeding with a Gatsby stack for their replatform. Here are three smart points of entry to get the conversation focused on use cases. (To learn more about explaining the technicalities of Gatsby, check out Linda’s extensive article on [how to break down Gatsby in a way that will resonate](/blog/2019-03-07-sell-gatsby-to-clients/). ## #1 Developers are the bottleneck -One of the primary drawbacks of a monolithic CMS like WordPress or Drupal is that the front-end theming layer is tightly coupled with the backend data layer. That means that a developer working only in the theme layer must still be comfortable with PHP, a backend programming language. In a headless approach, using JavaScript at the render layer, a themer only needs to know HTML, CSS, and JavaScript, the languages already in their toolkit. +One of the primary drawbacks of a monolithic CMS like WordPress or Drupal is that the frontend theming layer is tightly coupled with the backend data layer. That means that a developer working only in the theme layer must still be comfortable with PHP, a backend programming language. In a headless approach, using JavaScript at the render layer, a themer only needs to know HTML, CSS, and JavaScript, the languages already in their toolkit. If the client is suffering from slow developer velocity, this benefit will resonate and provide value to their organization. @@ -45,7 +45,7 @@ Mobile websites that take [more than 3 seconds to load have a 53% bounce rate](h There is fast (which every site should be) and then there is Gatsby-fast. -Every site needs to be performant. There isn’t a site out there where slow response times won’t negatively impact user engagement, conversion, and often, the bottom line. But remember, there is fast (which every site should be) and then there is Gatsby-fast. Companies that migrate to Gatsby will find their site is [between three and 10 times faster](https://www.gatsbyjs.com/guides/why-are-gatsby-sites-fast/). Indeed, the speed of a Gatsby-powered front end resembles more of the instantaneous feel of native mobile apps. +Every site needs to be performant. There isn’t a site out there where slow response times won’t negatively impact user engagement, conversion, and often, the bottom line. But remember, there is fast (which every site should be) and then there is Gatsby-fast. Companies that migrate to Gatsby will find their site is [between three and 10 times faster](https://www.gatsbyjs.com/guides/why-are-gatsby-sites-fast/). Indeed, the speed of a Gatsby-powered frontend resembles more of the instantaneous feel of native mobile apps. --- diff --git a/docs/blog/2019-06-17-product-management-at-Gatsby/index.md b/docs/blog/2019-06-17-product-management-at-Gatsby/index.md index 7a3c35a4cdc82..c4f584e6c4c56 100644 --- a/docs/blog/2019-06-17-product-management-at-Gatsby/index.md +++ b/docs/blog/2019-06-17-product-management-at-Gatsby/index.md @@ -67,7 +67,7 @@ We’ve had working sessions where we will complete Wardley maps as a team aroun ### Intent mapping -Our Principal Product Manager, [Preston So](@prestonso) introduced us to intent mapping as a way to set priorities and dependencies for major pieces of product work over the next 3 - 6 months. It’s a way to let all the teams have one source of truth for what we want to focus on in the medium-term. +Our Principal Product Manager, [Preston So](https://twitter.com/prestonso) introduced us to intent mapping as a way to set priorities and dependencies for major pieces of product work over the next 3 - 6 months. It’s a way to let all the teams have one source of truth for what we want to focus on in the medium-term. Acceptance criteria listed in the intent maps helps explain what we are going to build and why. We don’t create anything without a reason, and always bring the team in to collaborate on acceptance criteria. diff --git a/docs/blog/2019-06-25-profitable-agency-wordpress/index.md b/docs/blog/2019-06-25-profitable-agency-wordpress/index.md index 6ff1730a504a0..44d2d78af4251 100644 --- a/docs/blog/2019-06-25-profitable-agency-wordpress/index.md +++ b/docs/blog/2019-06-25-profitable-agency-wordpress/index.md @@ -85,7 +85,7 @@ Gatsby is different. Consider this example: If your client needs ecommerce features on their site, Gatsby can pull in the product data and shopping cart functionality from two different services, if you so choose. Those two services are not produced by the same server, or writing to the same database. So a problem with one may not affect the other. -In theory, break-fix for Gatsby should be easier to diagnose and solve. An issue with the build has nothing to do with a problem with the front-end, and vice versa. Gatsby's lower technical maintenance may be the difference between you taking on 5 client sites or 15. +In theory, break-fix for Gatsby should be easier to diagnose and solve. An issue with the build has nothing to do with a problem with the frontend, and vice versa. Gatsby's lower technical maintenance may be the difference between you taking on 5 client sites or 15. Personally I keep forgetting about the static sites under my care because there's literally nothing to work on for them month-to-month. diff --git a/docs/blog/2019-06-26-live-preview-for-drupal/index.md b/docs/blog/2019-06-26-live-preview-for-drupal/index.md index f67a9ea70388f..3d48b5657d19d 100644 --- a/docs/blog/2019-06-26-live-preview-for-drupal/index.md +++ b/docs/blog/2019-06-26-live-preview-for-drupal/index.md @@ -35,7 +35,7 @@ Here's how it works: ## Getting started - +https://youtu.be/H72PY3wNMcI ### Step 1: Sign Up for Gatsby Preview Beta diff --git a/docs/blog/2019-06-28-component-driven-drupal-development/index.md b/docs/blog/2019-06-28-component-driven-drupal-development/index.md index 4a2f702cd6a1c..05b96b3c5b9e4 100644 --- a/docs/blog/2019-06-28-component-driven-drupal-development/index.md +++ b/docs/blog/2019-06-28-component-driven-drupal-development/index.md @@ -9,7 +9,7 @@ tags: - agencies --- -In our recent webinar, [Gatsby for Agencies and Teams: Better, Faster, Smarter](https://www.gatsbyjs.com/gatsby-for-agencies/), Ben Robertson talked with us about adopting Gatsby at Mediacurrent and how it transformed their development process. Ben is a front-end developer at Mediacurrent where he has established front-end development best practices and led Drupal development projects. +In our recent webinar, [Gatsby for Agencies and Teams: Better, Faster, Smarter](https://www.gatsbyjs.com/gatsby-for-agencies/), Ben Robertson talked with us about adopting Gatsby at Mediacurrent and how it transformed their development process. Ben is a frontend developer at Mediacurrent where he has established frontend development best practices and led Drupal development projects. ## About Mediacurrent @@ -21,9 +21,9 @@ One of the things that excited Ben about working at Mediacurrent was their compo “I thought this was an awesome workflow. It gave us a single source of truth - for each component. The same template was used by both front-end and back-end + for each component. The same template was used by both frontend and backend developers. We could reuse that same component anywhere it was needed, and it - let the front-enders focus more on front-end specific concerns like semantics + let the frontenders focus more on frontend specific concerns like semantics and richer interactivity and accessibility.” @@ -31,11 +31,11 @@ Or at least, that’s what the component-driven workflows were supposed to do… ## Trouble in the Integration Layer -Unfortunately, things were not so simple. In addition to the component templates themselves, the front-end team had to code the logic for integrating the component templates with the Drupal CMS data. Placing the logic in the template files made them overly complex and difficult to read, but placing the integration logic on the Drupal side meant writing PHP, which was outside the front-end team’s comfort zone. The front-end team also didn’t necessarily think about or understand all the particulars of how the CMS data is fed into the component templates when they were building them, which meant additional time had to be spent reconciling the templates with the data. +Unfortunately, things were not so simple. In addition to the component templates themselves, the frontend team had to code the logic for integrating the component templates with the Drupal CMS data. Placing the logic in the template files made them overly complex and difficult to read, but placing the integration logic on the Drupal side meant writing PHP, which was outside the frontend team’s comfort zone. The frontend team also didn’t necessarily think about or understand all the particulars of how the CMS data is fed into the component templates when they were building them, which meant additional time had to be spent reconciling the templates with the data. -Finally, they were running into performance issues. The typical complex Drupal site is always going to have a variety of performance issues that could originate in the server, hosting environment, instances of bad PHP, issues with file compilation or bundling, and many other spots. Troubleshooting these issues would then require advanced knowledge of Drupal that could only be found among the back-end team. +Finally, they were running into performance issues. The typical complex Drupal site is always going to have a variety of performance issues that could originate in the server, hosting environment, instances of bad PHP, issues with file compilation or bundling, and many other spots. Troubleshooting these issues would then require advanced knowledge of Drupal that could only be found among the backend team. -Despite their best efforts, their component-driven process was being undermined by the quirks and inefficiencies of having to stand up sites within the Drupal CMS. The front-end and back-end teams were frustrated with the amount of effort they had to put into making the integration work, it was pulling their focus away from the front-end and back-end work they were actually there to do, and it was costing the company money. +Despite their best efforts, their component-driven process was being undermined by the quirks and inefficiencies of having to stand up sites within the Drupal CMS. The frontend and backend teams were frustrated with the amount of effort they had to put into making the integration work, it was pulling their focus away from the frontend and backend work they were actually there to do, and it was costing the company money. ## Effortless Integration and Performance with Gatsby @@ -49,24 +49,24 @@ Performance also became a low-effort task, thanks to Gatsby. Because Gatsby site “It's incredible. Like incredibly fast and incredibly easy to set up.“ -The front-end and back-end teams experienced new levels of productivity. They no longer had to waste time passing integration problems back and forth or troubleshooting esoteric CMS issues. With Gatsby, the front-end team could focus on the front end and the back-end team could focus on the back end, and any new issues that appeared could be pretty clearly identified as belonging to one or the other. +The frontend and backend teams experienced new levels of productivity. They no longer had to waste time passing integration problems back and forth or troubleshooting esoteric CMS issues. With Gatsby, the frontend team could focus on the frontend and the backend team could focus on the back end, and any new issues that appeared could be pretty clearly identified as belonging to one or the other. - “With the Gatsby site, if something is running slow on the front-end, you know - that it's a front-end problem because, for the most part, everything is + “With the Gatsby site, if something is running slow on the frontend, you know + that it's a frontend problem because, for the most part, everything is rendered in real-time. You can't get away with saying, ‘Oh, the user shouldn't have uploaded that large of an image,’ or, ‘Drupal didn't concatenate my JavaScript in the right order.’ But on the flip side, if something is not - available in the API, you know for a fact it's a back-end issue. **The - separation lets back-enders do what they like and excel at it, and it lets - front-enders do what they like and excel at it.**” + available in the API, you know for a fact it's a backend issue. **The + separation lets backenders do what they like and excel at it, and it lets + frontenders do what they like and excel at it.**” ## Looking Ahead: New Opportunities for the Team, New Opportunities for the Agency -The clarity that Gatsby has brought to front-end and back-end responsibilities has empowered the front-end team to develop more advanced front-end skills. Gatsby offers a great new way for team members to start working with React, and, because it solves a lot of back-end integration issues, they’re seeing that more projects can be accomplished entirely by front-end developers. +The clarity that Gatsby has brought to frontend and backend responsibilities has empowered the frontend team to develop more advanced frontend skills. Gatsby offers a great new way for team members to start working with React, and, because it solves a lot of backend integration issues, they’re seeing that more projects can be accomplished entirely by frontend developers. -As Ben and the Mediacurrent wrap up their first successful Gatsby project, they’re already leveraging it in other ways. They recently integrated Gatsby into a new Drupal install profile called [RAIN](https://www.mediacurrent.com/?utm_source=gatsbyjs_cbd&utm_medium=blog&utm_campaign=partners2019&utm_content=rain), and they’re excited to see how much more efficient their processes are in current client projects. Their new level of efficiency makes it more practical and profitable for the agency to take on smaller, front-end focused projects; and every Gatsby build opens them up to more React projects in the future. +As Ben and the Mediacurrent wrap up their first successful Gatsby project, they’re already leveraging it in other ways. They recently integrated Gatsby into a new Drupal install profile called [RAIN](https://www.mediacurrent.com/?utm_source=gatsbyjs_cbd&utm_medium=blog&utm_campaign=partners2019&utm_content=rain), and they’re excited to see how much more efficient their processes are in current client projects. Their new level of efficiency makes it more practical and profitable for the agency to take on smaller, frontend focused projects; and every Gatsby build opens them up to more React projects in the future. Everyone is looking forward to new growth and bright future with Gatsby. diff --git a/docs/blog/2019-07-02-extending-components/index.md b/docs/blog/2019-07-02-extending-components/index.md index 0dca937876f64..61a388a6dbaef 100644 --- a/docs/blog/2019-07-02-extending-components/index.md +++ b/docs/blog/2019-07-02-extending-components/index.md @@ -23,7 +23,7 @@ Before component extending was added this meant you had to copy over the entire component implementation from the theme to wrap it with your Card. It might look something like: -```js:title=src/gatsby-theme-blog/components/author.js +```jsx:title=src/gatsby-theme-blog/components/author.js import React from "react" import { Avatar, MediaObject, Icon } from "gatsby-theme-blog" import Card from "../components/card" @@ -60,7 +60,7 @@ Author component and wrap it with your Card. Now, that component extending has been added you can do the following instead: -```js:title=src/gatsby-theme-blog/components/author.js +```jsx:title=src/gatsby-theme-blog/components/author.js import React from "react" import { Author } from "gatsby-theme-blog/src/components/author" import Card from "../components/card" @@ -91,7 +91,7 @@ the component. Below, `NewsletterButton` is re-exported and `variant="link"` is added in the shadowed file to override its default value. -```js:title=src/gatsby-theme-blog/components/newsletter/button.js +```jsx:title=src/gatsby-theme-blog/components/newsletter/button.js import { NewsletterButton } from "gatsby-theme-blog/src/components/newsletter" export default props => @@ -104,7 +104,7 @@ you might want to apply CSS using the [Emotion CSS prop](/docs/emotion). This will allow you to change the styling of a particular component without changing any of its functionality. -```js:title=src/gatsby-theme-blog/components/newsletter/button.js +```jsx:title=src/gatsby-theme-blog/components/newsletter/button.js import { NewsletterButton } from "gatsby-theme-blog/src/components/newsletter" export default props => ( diff --git a/docs/blog/2019-07-03-announcing-stable-release-gatsby-themes/index.md b/docs/blog/2019-07-03-announcing-stable-release-gatsby-themes/index.md index 68ddcf5c2f559..d6d8eedf7da63 100644 --- a/docs/blog/2019-07-03-announcing-stable-release-gatsby-themes/index.md +++ b/docs/blog/2019-07-03-announcing-stable-release-gatsby-themes/index.md @@ -38,7 +38,7 @@ Shadowing allows you to override specific components by creating a new file and Stability for shadowing means that creating a single file is all you need to start changing how your theme renders your site. Additionally, we've added the ability to import and extend the parent component, allowing the use of props for customizing features of any React component. -```js:title=my-site/src/my-theme/components/header.js +```jsx:title=my-site/src/my-theme/components/header.js import Header from "my-theme/src/components/header" export default props =>
diff --git a/docs/blog/2019-07-03-using-themes-for-distributed-docs/index.md b/docs/blog/2019-07-03-using-themes-for-distributed-docs/index.md index f1ca134a51ac5..bba096832ed21 100644 --- a/docs/blog/2019-07-03-using-themes-for-distributed-docs/index.md +++ b/docs/blog/2019-07-03-using-themes-for-distributed-docs/index.md @@ -49,7 +49,7 @@ Using [MDX](/docs/mdx/), we’re able to write rich documentation by including R ![Enhanced code blocks](./images/code-blocks.gif) -Lastly, MDX introduces the concept of composing pages from shared chunks of content. For example, we may want to document some commonly used steps to set up an Apollo project. Instead of copying and pasting that content into multiple pages, we can write it once as [an MDX file](https://github.com/apollographql/gatsby-theme-apollo/blob/master/packages/gatsby-theme-apollo-docs/mdx/project-config-panel.mdx), import it into other MDX files, and [render it like a React component](https://www.apollographql.com/docs/platform/schema-validation/#set-up-schema-validation). What’s more? Since we’re working with MDX, we can use interactive React elements within the shared content! +Lastly, MDX introduces the concept of composing pages from shared chunks of content. For example, we may want to document some commonly used steps to set up an Apollo project. Instead of copying and pasting that content into multiple pages, we can write it once as [an MDX file](https://github.com/apollographql/gatsby-theme-apollo/blob/master/packages/gatsby-theme-apollo-docs/shared/project-config-panel.mdx), import it into other MDX files, and [render it like a React component](https://www.apollographql.com/docs/platform/schema-validation/#set-up-schema-validation). What’s more? Since we’re working with MDX, we can use interactive React elements within the shared content! ![Creating shared content in MDX](./images/shared-content.png) diff --git a/docs/blog/2019-07-09-digital-display-drupal-gatsby/index.md b/docs/blog/2019-07-09-digital-display-drupal-gatsby/index.md index 9202c38203ea4..1440d92d4f781 100644 --- a/docs/blog/2019-07-09-digital-display-drupal-gatsby/index.md +++ b/docs/blog/2019-07-09-digital-display-drupal-gatsby/index.md @@ -28,9 +28,9 @@ Sandy Springs came to [Mediacurrent](https://www.mediacurrent.com/?utm_source=ga ## Mediacurrent’s Solution -A decoupled approach, where front end templating is separate from the content management system and database was required to achieve a unified system. Proven as a powerful decoupled CMS, Drupal replaced the city’s existing WordPress site. +A decoupled approach, where frontend templating is separate from the content management system and database was required to achieve a unified system. Proven as a powerful decoupled CMS, Drupal replaced the city’s existing WordPress site. -On the back end, a [Drupal 8](https://www.drupal.org/8) foundation manages content. On the front end, Gatsby presents content. With this approach, the Sandy Springs team can “create once, publish everywhere,” with a more efficient process for sharing information with the local community. +On the back end, a [Drupal 8](https://www.drupal.org/8) foundation manages content. On the frontend, Gatsby presents content. With this approach, the Sandy Springs team can “create once, publish everywhere,” with a more efficient process for sharing information with the local community. ![Drupal-powered large scale digital signage in a cafe](./images/CitySprings2.jpg "City Spring's large scale digital signage") @@ -45,7 +45,7 @@ In this [video presentation](https://www.youtube.com/watch?time_continue=3&v=Qio - **Stable**: With full control over the markup, the site build is fast. - **Scalable**: Gatsby makes it easier for the client to add additional sites in the future. -- **Speedy**: Gatsby bakes in a lot of performance optimization for the front end, ultimately delivering a faster site. +- **Speedy**: Gatsby bakes in a lot of performance optimization for the frontend, ultimately delivering a faster site. - **Hosting**: The Drupal site is never used by a non-editorial user, so fewer hosting resources are needed. ![Drupal-powered digital display kiosk promotes a theatre event](./images/CitySprings3.jpg "City Spring's digital signage kiosk") diff --git a/docs/blog/2019-07-11-user-testing-accessible-client-routing/index.md b/docs/blog/2019-07-11-user-testing-accessible-client-routing/index.md index 5bfd8bc4eb940..98b8f5777b168 100644 --- a/docs/blog/2019-07-11-user-testing-accessible-client-routing/index.md +++ b/docs/blog/2019-07-11-user-testing-accessible-client-routing/index.md @@ -54,7 +54,7 @@ By user testing a few variations of known routing techniques, we gained some val ## Working with Fable -We worked with [Fable Tech Labs](https://makeitfable.com) to conduct this research and found it to be a very productive process. I connected with Fable’s lead front end developer Perry Trinier at the CSUN accessibility conference in early 2019. Fable’s generous offer to pair with us on this initiative has been wonderful, and we’re grateful for the opportunity to see this through. +We worked with [Fable Tech Labs](https://makeitfable.com) to conduct this research and found it to be a very productive process. I connected with Fable’s lead frontend developer Perry Trinier at the CSUN accessibility conference in early 2019. Fable’s generous offer to pair with us on this initiative has been wonderful, and we’re grateful for the opportunity to see this through. The experience of testing with people with disabilities and the results that followed felt very important, and something product teams should seek out regularly. We’d highly recommend this process for anyone working on digital experiences; particularly if you can test prototypes to adapt to the findings early and often in design & development. User testing for accessibility can provide game-changing detail that you’ll be eternally grateful to have uncovered. Addressing accessibility issues sooner than later is both a [smart business investment](https://www.w3.org/WAI/business-case/) and can make your project more [inclusive](https://www.microsoft.com/design/inclusive/) from the start! @@ -170,8 +170,17 @@ The exact implementation(s) we integrate into Gatsby will likely evolve as we tr - Rendering an interactive UI control in each view that becomes visible when the user navigates through the app by keyboard. - Making it function as a tab stop in a content region for keyboard users and providing a way to skip back to navigation so it is actually operable: a skip link is the most natural choice for this. - Making the control small in width and height (like a link or icon button) so the focus outline and content aren’t cut off when zoomed way in. -- Putting an `aria-label` or `aria-labelledby` attribute with an indication of the nearby content (like a heading), and what action the control does. E.g. “Portfolio, skip back to navigation”. This would benefit from more user testing. - Focusing this skip link when a user completes an action that triggers a route change and updates the client-rendered view, both managing focus and notifying users of assistive technology. +- ~~Putting an `aria-label` or `aria-labelledby` attribute with an indication of the nearby content (like a heading), and what action the control does. E.g. “Portfolio, skip back to navigation”. This would benefit from more user testing.~~ + +**Note:** The advice for labeling a skip link component which also serves as a focus management target has evolved since this article was initially published. Rather than compose a label "with nearby content" to both indicate the link action _and_ the current page on focus, a better approach would be to decouple the two so when the skip link is focused with a screen reader without a route change, its purpose would be more clear: "skip to navigation". Including an ARIA Live Region to make an announcement on route change would notify screen reader users and keep skip link text clear. This would serve assistive technology users with the necessary page and element focus context, while also supporting sighted and low-vision keyboard users. + +The technique developed from this article was presented and tested again with Fable Tech Labs at the [Inclusive Design 24 virtual conference](https://www.youtube.com/watch?v=Tr21FqQQv-U) in October 2019. For an example of the most recent research in action, check out these [workshop materials](https://github.com/marcysutton/gatsby-a11y-workshop/blob/master/examples/client-side-routing/). + +The advice now looks like this: + +- Provide a skip link that takes focus on a route change within the site, with a label that indicates what the link will do when activated: e.g. "skip to main navigation". +- Include an [ARIA Live Region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) on page load. On a route change, append text to it indicating the current page, e.g. "Portfolio page". Part of the challenge with this work is what might be ideal for one user with a disability might not be for another. These recommendations are an attempt at weaving multiple perspectives into one usable pattern, with the historical knowledge of where teams run into conflicts over accessibility in design (e.g. turning off visible focus outlines on container elements). diff --git a/docs/blog/2019-07-15-theme-jam-contest/index.md b/docs/blog/2019-07-15-theme-jam-contest/index.md index 11580fb1b52bb..ceeb6e28b3ddb 100644 --- a/docs/blog/2019-07-15-theme-jam-contest/index.md +++ b/docs/blog/2019-07-15-theme-jam-contest/index.md @@ -15,11 +15,11 @@ To celebrate the [stable release of Gatsby Themes](/blog/2019-07-03-announcing-s Gatsby Themes are pre-built, installable packages for setting up a site’s default styling, components, plugins, and overall configuration that can be reused across multiple Gatsby sites. They’re a great way to simplify the early steps of configuring a new site; and, when it’s time to update your site’s styling or functionality, you only have to edit your theme or swap it out entirely with another compatible theme. You can find a more detailed explanation in the [Themes section of Gatsby’s documentation](/docs/themes/). -If you’d like to see an example, check out Gatsby’s official [blog theme](https://github.com/gatsbyjs/gatsby/tree/master/themes/gatsby-theme-blog) or [notes theme](https://github.com/gatsbyjs/gatsby/tree/master/themes/gatsby-theme-notes). +If you’d like to see an example, check out Gatsby’s official [blog theme](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-theme-blog) or [notes theme](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-theme-notes). ## How to build your Gatsby theme -If you’re planning to build a theme for the contest, you may want to start with this [Gatsby Theme Jam Submission Example repository](https://github.com/jlengstorf/gatsby-theme-jam-example). You can build a child theme of an existing Gatsby theme (e.g. the [blog theme](https://github.com/gatsbyjs/gatsby/tree/master/themes/gatsby-theme-blog) or [notes theme](https://github.com/gatsbyjs/gatsby/tree/master/themes/gatsby-theme-notes)) with updated styling or added functionality, for example, or it can be a completely new theme. +If you’re planning to build a theme for the contest, you may want to start with this [Gatsby Theme Jam Submission Example repository](https://github.com/jlengstorf/gatsby-theme-jam-example). You can build a child theme of an existing Gatsby theme (e.g. the [blog theme](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-theme-blog) or [notes theme](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-theme-notes)) with updated styling or added functionality, for example, or it can be a completely new theme. Here are some resources with detailed instructions on how to build a Gatsby theme: diff --git a/docs/blog/2019-07-23-google-sheets-gatsby-acroyoga-video-explorer/index.md b/docs/blog/2019-07-23-google-sheets-gatsby-acroyoga-video-explorer/index.md index 3fbedddf7ceea..ea64dafc29f37 100644 --- a/docs/blog/2019-07-23-google-sheets-gatsby-acroyoga-video-explorer/index.md +++ b/docs/blog/2019-07-23-google-sheets-gatsby-acroyoga-video-explorer/index.md @@ -336,7 +336,7 @@ This was such a clear and easy 'aha!' moment. I hadn't optimized my images and w I dug into my normal gatsby-image workflow but I quickly hit a snag. My previous use of Gatsby-image had been for local images whilst I was now trying to use remote images (cloud storage image links). Thankfully, with just a bit more searching, I found the right plugin to solve this: [gatsby-plugin-remote-images](/packages/gatsby-plugin-remote-images/). -Gatsby-plugin-remote-images fetches image URL links (e.g. http://super-image.png) and prepares them in a way that gatsby-image can use them. To make my cards load faster, I'd need to optimize both the video thumbnail as well as the small instructor image. It makes no sense at all to load a 300+ pixel image of an instructor when all you really need are maybe 40 pixels max. +Gatsby-plugin-remote-images fetches image URL links (e.g. `http://super-image.png`) and prepares them in a way that gatsby-image can use them. To make my cards load faster, I'd need to optimize both the video thumbnail as well as the small instructor image. It makes no sense at all to load a 300+ pixel image of an instructor when all you really need are maybe 40 pixels max. ![Acroyoga Card with Optimized Images](./images/word-image-4.png) diff --git a/docs/blog/2019-07-30-how-i-used-theme-ui-to-build-my-gatsby-themes-library/index.md b/docs/blog/2019-07-30-how-i-used-theme-ui-to-build-my-gatsby-themes-library/index.md index 9784e6f45ac21..190c16fb06cae 100644 --- a/docs/blog/2019-07-30-how-i-used-theme-ui-to-build-my-gatsby-themes-library/index.md +++ b/docs/blog/2019-07-30-how-i-used-theme-ui-to-build-my-gatsby-themes-library/index.md @@ -65,7 +65,7 @@ gradients: { You can access theme values with a function which I did in this case to be able to use my already defined colors in the gradients. So why did I set up the gradients variants? I wanted to use a **single** property in my "Shapes" component to define the color. I didn't just pass in the value in the component itself like `` backgroundImage:t=>`linear-gradient(135deg,${t.colors[colorProp][8]},${t.colors[colorProp][6]})` `` because then every shape would have had the same angle and the same spacing (value 8 and 6 here). Some colors need other values to look right so variants was the only logical choice here. The usage looks something like this: -```js +```jsx const Circle = ({ color, className }) => (
( While the shapes (circle, donut, grid) look really nice on bigger displays, for mobile and tablet views their initial size and position needs to be adjusted. I'm still a fan of "form follows function" so they shouldn't get in the way when reading things. When looking at the [source code](https://github.com/LekoArts/gatsby-themes/blob/569722297e73d05e0063e0333c284741c174cc2f/www/src/components/hero.tsx) for the hero section you'll see that it's very intuitive to define those properties: -```js +```jsx {themes.map((theme, index) => { const isEven = index % 2 === 0 diff --git a/docs/blog/2019-08-02-what-is-jsx-pragma/index.md b/docs/blog/2019-08-02-what-is-jsx-pragma/index.md index d5767460c18b2..c2be77c5247c0 100644 --- a/docs/blog/2019-08-02-what-is-jsx-pragma/index.md +++ b/docs/blog/2019-08-02-what-is-jsx-pragma/index.md @@ -10,14 +10,14 @@ tags: If you’re looking into using [Theme UI](https://theme-ui.com/) , you’ll come across some (potentially) unfamiliar looking syntax: -```javascript +```jsx /** @jsx jsx */ import { jsx } from "theme-ui" ``` This is a JSX pragma. What the heck is a JSX pragma? I had heard the phrase, but not thought too much about it until it came up with Gatsby theming -- and lots of other folks hadn't either: - +https://twitter.com/amber1ey/status/1153382680916049921 ## Striking a balance in documentation diff --git a/docs/blog/2019-08-07-gazette-august/index.md b/docs/blog/2019-08-07-gazette-august/index.md index 38b4b8e648ad1..999ab3df304f7 100644 --- a/docs/blog/2019-08-07-gazette-august/index.md +++ b/docs/blog/2019-08-07-gazette-august/index.md @@ -23,13 +23,13 @@ The past few weeks has been all about what we're calling the Snow Leopard releas First, an aside. -[Snow Leopard](https://en.wikipedia.org/wiki/Mac_OS_X_Snow_Leopard) was the seventh major release of macOS. Unlike those of previous versions, the goals of Snow Leopard were improved performance, greater efficiency and the reduction of its overall memory footprint. Addition of new end-user features was not a primary consideration: its name signified its goal to be a refinement of the previous OS X version, Leopard. +[Snow Leopard](https://en.wikipedia.org/wiki/Mac_OS_X_Snow_Leopard) was the seventh major release of macOS. Unlike those of previous versions, the goals of Snow Leopard were improved performance, greater efficiency and the reduction of its overall memory footprint. Addition of new end user features was not a primary consideration: its name signified its goal to be a refinement of the previous OS X version, Leopard. Similarly, earlier last month, we felt like we needed to take some time to slow down and clean up Gatsby after some of the big features that we've shipped recently: notably ([themes](https://www.gatsbyjs.org/blog/2019-07-03-announcing-stable-release-gatsby-themes/) and [per page manifest](https://www.gatsbyjs.org/blog/2019-06-12-performance-improvements-for-large-sites/)). Our goal was to take a step back, move a bit more slowly, and improve the overall code base, add tests, and overall ensure our house is in good order for more improvements in the future. We feel this went quite well, so we intend to keep doing this fairly regularly to keep Gatsby stable and ensure you have painless upgrades. Our goal is to always enable the experience [Brian Holt](https://twitter.com/holtbt) depicts below, specifically painless upgrades and all the while delivering real value and fixes in every version of Gatsby. - +https://twitter.com/holtbt/status/1158559782451609600 Check out the [project](https://github.com/gatsbyjs/gatsby/projects/13) on GitHub if you're interested. @@ -66,7 +66,7 @@ If you're curious about the implementation, [here](https://github.com/gatsbyjs/g [Native Lazy Loading](https://web.dev/native-lazy-loading) just launched in Chrome 76. We shipped support for this in `gatsby-image` back in May! So if you're using Gatsby, your site already does this out of the box. - +https://twitter.com/chatsidhartha/status/1129118956193640448 Check out the implementation on the [PR on GitHub](https://github.com/gatsbyjs/gatsby/pull/13217). @@ -101,7 +101,7 @@ Firstly, thank you for all your contributions, folks! Every single contribution Gatsby has always been a community effort. You make a _lot_ of contributions. In fact, we achieved a new record in merged PRs last month: - +https://twitter.com/chatsidhartha/status/1156334013247737856 ## Gatsby Site of the month diff --git a/docs/blog/2019-08-07-theme-jam/index.md b/docs/blog/2019-08-07-theme-jam/index.md index d6659cc5ddd33..89716387d3cd2 100644 --- a/docs/blog/2019-08-07-theme-jam/index.md +++ b/docs/blog/2019-08-07-theme-jam/index.md @@ -13,7 +13,7 @@ At the beginning of July, [Brent Jackson](https://twitter.com/jxnblk) joined _Le ## What is the Theme Jam? -![Theme Jam illustration by Maggie Appleton.](images/theme-jam.png) +![Theme Jam illustration by Maggie Appleton.](./images/theme-jam.png) In a nutshell, the Theme Jam was a way for Gatsby to give back to its community: everyone who published a theme and submitted it to the Theme Jam will receive exclusive swag designed by [Maggie Appleton](https://maggieappleton.com/). Two creators who published themes our team reviewed as exemplary are getting an all-expenses paid trip to [Gatsby Days](https://www.gatsbyjs.com/resources/gatsby-days/). (For more details, see the [rules](https://themejam.gatsbyjs.org/rules).) @@ -43,7 +43,7 @@ Of the 111 submissions, 52 passed the automated review. ### Part 2: Manual Review -Every theme that cleared the automated review was manually reviewed by [Jackson](https://twitter.com/jxnblk), [Amberley](https://twitter.com/amber1ey), [John](https://twitter.com/4lpine), [Kyle Gill](https://gill_kyle), [Chris](https://twitter.com/chrisbiscardi), [Flo](https://twitter.com/fk), and [me](https://twitter.com/jlengstorf). +Every theme that cleared the automated review was manually reviewed by [Jackson](https://twitter.com/jxnblk), [Amberley](https://twitter.com/amber1ey), [John](https://twitter.com/4lpine), [Kyle Gill](https://twitter.com/gill_kyle), [Chris](https://twitter.com/chrisbiscardi), [Flo](https://twitter.com/fk), and [me](https://twitter.com/jlengstorf). Amberley did a manual accessibility audit. Nearly all of the themes we reviewed have a few accessibility issues, so we will be opening issues with feedback and suggestions to improve that. @@ -61,7 +61,7 @@ Two of the themes we received stood out especially. As we reviewed, we all took ### Vojtěch’s Simplecast Gatsby Theme -![Demo of the Simplecast Gatsby theme.](images/gatsby-theme-simplecast.gif) +![Demo of the Simplecast Gatsby theme.](./images/gatsby-theme-simplecast.gif) Vojtěch combined data sourcing from [Simplecast](https://simplecast.com/)’s API, beautiful design, and an explorable UX to create this powerful theme for podcasters. @@ -69,7 +69,7 @@ Vojtěch combined data sourcing from [Simplecast](https://simplecast.com/)’s A ### Allan’s Prismic-Powered Legal Pages Theme -![Screenshot of the Gatsby Prismic Legals theme.](images/gatsby-theme-legals-prismic-mockup.jpg) +![Screenshot of the Gatsby Prismic Legals theme.](./images/gatsby-theme-legals-prismic-mockup.jpg) Allan turned something boring (required legal pages) into something beautiful by pulling common legal pages — such as a “terms & conditions” page — from [Prismic](https://prismic.io/) and putting them into a gorgeous UI. This theme highlights theme composability: combine this theme with others to quickly add required legal pages to any Gatsby site! diff --git a/docs/blog/2019-08-13-Localised-strings-from-Kentico-Cloud-GatsbyJS-GraphQL/index.md b/docs/blog/2019-08-13-Localised-strings-from-Kentico-Cloud-GatsbyJS-GraphQL/index.md index 1f4e2802c09f6..836c61f3c6272 100644 --- a/docs/blog/2019-08-13-Localised-strings-from-Kentico-Cloud-GatsbyJS-GraphQL/index.md +++ b/docs/blog/2019-08-13-Localised-strings-from-Kentico-Cloud-GatsbyJS-GraphQL/index.md @@ -22,7 +22,7 @@ The flexibility of Kentico Cloud means there are many ways to achieve the same g ## Identify your language -Our first step is to determine how we are going to identify cultures or languages from the front end of the site. As Kentico Cloud is purely a content hub, there’s not the same set of localization web parts and widgets that you might get from a product like Kentico EMS. We need an alternative to pick up that culture code. +Our first step is to determine how we are going to identify cultures or languages from the frontend of the site. As Kentico Cloud is purely a content hub, there’s not the same set of localization web parts and widgets that you might get from a product like Kentico EMS. We need an alternative to pick up that culture code. There are a few options here. You could be using a simple language switcher control on your site or application. Or, it might be as simple as deriving it from the URL e.g. _www.mysite.com/en-gb/about-us_ or _www.mysite.com/about-us?lang=en-gb_. @@ -34,11 +34,11 @@ If you want to look at building localized strings, the first step is to head to Here is a [Content Item](https://docs.kenticocloud.com/tutorials/write-and-collaborate/write-content/adding-content-items) derived from a '_localized String_' Content Type, which has a single field for the 'value'. -![An example of the localized content item](images/Localise-Content-Item.png) +![An example of the localized content item](./images/Localise-Content-Item.png) As I mentioned earlier, localized strings work in a pair of 'key' and 'value'. The good thing about Kentico Cloud is that the 'key' is something you could derive from the 'Code name' for the content item and it saves you creating additional fields for it. -![An example of the localized content item, showing the code name](images/Localise-Content-Item-Codename.png) +![An example of the localized content item, showing the code name](./images/Localise-Content-Item-Codename.png) You will most likely be utilizing the IDs for the content item, but it's useful to have the code name as well. @@ -47,7 +47,7 @@ You will most likely be utilizing the IDs for the content item, but it's useful With your content type set up, the next step is to get your content in – ensuring you add the content for all your languages (I’m assuming you’ve already set up your languages in the settings!). _(If you need to know how to switch the content from one culture to another have a look at the [switching languages](https://docs.kenticocloud.com/tutorials/write-and-collaborate/create-multilingual-content/switching-languages) section in the Kentico Cloud documentation.)_ -![An example of the localized content item in FR, showing the code name](images/Localise-Content-Item-FR.png) +![An example of the localized content item in FR, showing the code name](./images/Localise-Content-Item-FR.png) One thing to remember at this point is that if you want to use similar text (or simply give yourself a starting point) in the destination culture to your original culture, then you can use the [Copy from language](https://docs.kenticocloud.com/tutorials/write-and-collaborate/create-multilingual-content/translating-content-items#a-translating-a-content-item) option once you have switched over to the new culture. @@ -55,23 +55,23 @@ One thing to remember at this point is that if you want to use similar text (or Now we have the localized string Content Types and Content Items created in Kentico Cloud, the next step is to retrieve the content. I'm using the awesome and very popular static site generator [GatsbyJS](/) with [GraphQL](https://graphql.org/), a query language for your API. -_(Another assumption for you... We’re assuming you have GatsbyJS + GraphQL set up for your project. If not, you can find a starting point here, [GatsbyJS sourcing from Kentico Cloud](/docs/sourcing-from-kentico-cloud/).)_ +_(Another assumption for you... We’re assuming you have GatsbyJS + GraphQL set up for your project. If not, you can find a starting point here, [GatsbyJS sourcing from Kentico Cloud](/docs/sourcing-from-kentico-kontent/).)_ With your content items in Kentico Cloud, you should be able to see them when you conduct a GraphQL query. Here is an example of the GraphQL query you will use to retrieve the ID and CodeName for the Content Items from Kentico Cloud using GatsbyJS. Think of this as the 'key' you would need to retrieve the 'value'. You can see the 'codename' and 'id' as potential options that you could use in the below GraphQL query. -![A view of the GraphiQL preview of retrieving language nodes](images/GraphiQL-retrieve-lang-nodes.png) +![A view of the GraphiQL preview of retrieving language nodes](./images/GraphiQL-retrieve-lang-nodes.png) You can retrieve all localization strings using the following GraphQL query. -![Retrieving all language versions of the localized strings](images/GraphiQL-retrieve-lang-variants.png) +![Retrieving all language versions of the localized strings](./images/GraphiQL-retrieve-lang-variants.png) However, to retrieve the actual 'value', there’s a little more to do in your GraphQL query. Here is an example of a GraphQL query where I am using the 'CodeName'. -![GraphiQL retrieve language nodes localized strings condition code name](images/GraphiQL-retrieve-lang-variants-based-on-condition-codename.png) +![GraphiQL retrieve language nodes localized strings condition code name](./images/GraphiQL-retrieve-lang-variants-based-on-condition-codename.png) And, here is an example of a GraphQL query where I am using the ID. -![GraphiQL retrieve language nodes localized strings condition ID](images/GraphiQL-retrieve-lang-variants-based-on-condition-id.png) +![GraphiQL retrieve language nodes localized strings condition ID](./images/GraphiQL-retrieve-lang-variants-based-on-condition-id.png) As you can see, once you know which 'key' you need, then it's pretty simple to get the 'value' and also detect the language variant you need to retrieve in GatsbyJS using this GraphQL query format. diff --git a/docs/blog/2019-08-14-strivectin-case-study/index.md b/docs/blog/2019-08-14-strivectin-case-study/index.md index 53258c8513100..a548e0c34f4c3 100644 --- a/docs/blog/2019-08-14-strivectin-case-study/index.md +++ b/docs/blog/2019-08-14-strivectin-case-study/index.md @@ -51,7 +51,7 @@ Gatsby provides us with a superior DX and a fast site. This includes: Gatsby provides conveniences around data fetching. The “Content Mesh” is a mesh of different content sources stitched into a single data layer. You can query this layer using GraphQL. Our “Content Mesh” consists of Prismic, Shopify, and Yotpo. You can see how those data sources make up the Homepage below: -![Strivectin content mesh.](images/content-mesh.png) +![Strivectin content mesh.](./images/content-mesh.png) ### Leaving the server behind diff --git a/docs/blog/2019-08-27-roll-your-own-comment-system/index.md b/docs/blog/2019-08-27-roll-your-own-comment-system/index.md index 603637d5af13f..c58b5244690c7 100644 --- a/docs/blog/2019-08-27-roll-your-own-comment-system/index.md +++ b/docs/blog/2019-08-27-roll-your-own-comment-system/index.md @@ -47,7 +47,7 @@ The comments API consists of three parts: - [API Server](#api) - [Front End](#front-end) -The front end is written for React, but if you know how to make a form and an API call, it can be easily adjusted to whatever static system you're using. +The frontend is written for React, but if you know how to make a form and an API call, it can be easily adjusted to whatever static system you're using. ## Database @@ -241,7 +241,7 @@ app.delete("/comments/:id", deleteComment) ## Front End -Again, for the front end I'm using React as an example, but the concept is the same for any template system. In whatever your post template file is, use JavaScript to make a `fetch` or `axios` call to your comment API, and save the data in state somewhere. Once I retrieve the JSON response from the API server, which will be an array of comment objects, I can pass it to wherever I'm displaying the comments. +Again, for the frontend I'm using React as an example, but the concept is the same for any template system. In whatever your post template file is, use JavaScript to make a `fetch` or `axios` call to your comment API, and save the data in state somewhere. Once I retrieve the JSON response from the API server, which will be an array of comment objects, I can pass it to wherever I'm displaying the comments. > Sorry, I'm not using hooks yet. It's okay, deep breath. We'll get through this. diff --git a/docs/blog/2019-09-11-impossible-foods/index.md b/docs/blog/2019-09-11-impossible-foods/index.md index fd39c0db58a64..d280a781ff5e9 100644 --- a/docs/blog/2019-09-11-impossible-foods/index.md +++ b/docs/blog/2019-09-11-impossible-foods/index.md @@ -1,5 +1,5 @@ --- -title: Why Impossible Foods Chose Gatsby to Power Their Ecommerce Website Relaunch +title: Why Impossible Foods Chose Gatsby to Power Their e-commerce Website Relaunch date: 2019-09-16 author: Hashim Warren excerpt: "Impossible Foods needed a website with new functionality, that could withstand surges in traffic. These challenges and requirements led the Impossible Foods team to adopt a Content Mesh approach to their website architecture." @@ -16,14 +16,14 @@ The Impossible Burger is the breakout offering from the company, and it made a s The first version of the Impossible Foods website was adequate, but as the company grew several problems became evident. Designers and writers struggled with slow turn around times because the website could only be updated by a developer. The site’s pages and map section were both static, providing no experience to users other than the delivery of flat information. -Impossible Foods needed a website with new functionality, that could withstand surges in traffic as interest and demand for their innovative burgers grew around the world. And the website needed to offer a first-class experience to all stakeholders - from content editors and IT staff, to restaurants and consumers. These challenges and requirements led the Impossible Foods team to adopt a ["Content Mesh"](/blog/2018-10-04-journey-to-the-content-mesh) approach to their website architecture, with Contentful as a [headless CMS](/docs/headless-cms), Shopify for ecommerce, and Gatsby. +Impossible Foods needed a website with new functionality, that could withstand surges in traffic as interest and demand for their innovative burgers grew around the world. And the website needed to offer a first-class experience to all stakeholders - from content editors and IT staff, to restaurants and consumers. These challenges and requirements led the Impossible Foods team to adopt a ["Content Mesh"](/blog/2018-10-04-journey-to-the-content-mesh) approach to their website architecture, with Contentful as a [headless CMS](/docs/headless-cms), Shopify for e-commerce, and Gatsby. -## The Content Mesh Approach for Ecommerce +## The Content Mesh Approach for e-commerce The development team created reusable components in Gatsby and sourced content from “modules” created within Contentful. They also connected the site to Shopify to power the checkout experience, as well as display in-stock products, descriptions, and prices. Content producers were now free to create and update content on the site, simply by using the editing experience with Contentful and Shopify. This new workflow dramatically reduced the turnaround time for new announcements to be published on the website. The Impossible Foods team raved that their new architecture enables their content strategy to keep pace with the acceleration of their business. -## Learn More About Gatsby and Ecommerce +## Learn More About Gatsby and e-commerce -To watch the full case study, including a presentation from Gatsby’s co-founder Kyle Mathews on why Gatsby is a smart choice for ecommerce sites, register here: [Impossible Foods Webinar](https://www.gatsbyjs.com/impossible-foods-webinar/). +To watch the full case study, including a presentation from Gatsby’s co-founder Kyle Mathews on why Gatsby is a smart choice for e-commerce sites, register here: [Impossible Foods Webinar](https://www.gatsbyjs.com/impossible-foods-webinar/). diff --git a/docs/blog/2019-09-12-building-the-new-third-and-grove-website-in-gatsby/index.md b/docs/blog/2019-09-12-building-the-new-third-and-grove-website-in-gatsby/index.md index 0971e08cde637..370a78a56a795 100644 --- a/docs/blog/2019-09-12-building-the-new-third-and-grove-website-in-gatsby/index.md +++ b/docs/blog/2019-09-12-building-the-new-third-and-grove-website-in-gatsby/index.md @@ -13,11 +13,11 @@ canonicalLink: https://www.thirdandgrove.com/building-new-site-with-drupal-and-g This rebrand/replatform is a big leap forward for our brand, marking a milestone in who we want to be as a company. In this article, I’m going to focus on the tech behind the screen that makes it all happen. -## Why use a modern front end? +## Why use a modern frontend? -We’re a Drupal agency through and through. But since we saw the promise of front end tech like React, we’ve better equipped our team with people who can build modern digital experiences for our clients (including people like me!) Building our own site with a modern front end is foremost a way for us to eat our own dog food (good news is that we’re still really enjoying eating it). +We’re a Drupal agency through and through. But since we saw the promise of frontend tech like React, we’ve better equipped our team with people who can build modern digital experiences for our clients (including people like me!) Building our own site with a modern frontend is foremost a way for us to eat our own dog food (good news is that we’re still really enjoying eating it). -There are several reasons to modernize from an aging front end but these stick out to us. +There are several reasons to modernize from an aging frontend but these stick out to us. 1. **User Experience.** It’s possible to create an amazing user experience with dated technology (we’ve done it many a time). BUT it’s easier, cheaper, and faster to do with a modern set of solutions. 2. **Developer Velocity.** Leveraging Gatsby has improved the code quality and tooling. So development, while faster, can produce code that is more testable, has less duplication and is of higher quality. It also reduces the overhead for developers to know HTML, CSS, JavaScript, and PHP. This last part wasn’t of huge importance to us but for this can make a world of difference to our clients that don’t have as wide a skillset on their team. @@ -56,6 +56,6 @@ In our new site, we have content coming from multiple sources. Each source might ## More like TAGV5.1 -The beauty of building React projects is that they are highly flexible. This flexibility allows us to construct this front end in a way that it can grow with us. So instead of having to rebuild everything when we want a new look, we can change some of our wrapper components out, or add a new data source if we start a swag store. This gives us a layer of abstraction that is useful in the real world. Our data/content is separate from our views, and our views are abstracted from their structure. This is powerful for many reasons, foremost being that, instead of building a single entity that is our site, we are building modular pieces that when combined become an awesome thing, like a Megazord, or Captain Planet. This mentality of modular code isn't new and isn't unique to React. However, the JavaScript ecosystem and React in particular have taken this approach to heart. Gatsby takes it a step further with their plugin model. For example, adding a sitemap is as easy as adding a plugin. Once the plugin is installed it’s just another task added into the Gatsby build process using information that is already available. +The beauty of building React projects is that they are highly flexible. This flexibility allows us to construct this frontend in a way that it can grow with us. So instead of having to rebuild everything when we want a new look, we can change some of our wrapper components out, or add a new data source if we start a swag store. This gives us a layer of abstraction that is useful in the real world. Our data/content is separate from our views, and our views are abstracted from their structure. This is powerful for many reasons, foremost being that, instead of building a single entity that is our site, we are building modular pieces that when combined become an awesome thing, like a Megazord, or Captain Planet. This mentality of modular code isn't new and isn't unique to React. However, the JavaScript ecosystem and React in particular have taken this approach to heart. Gatsby takes it a step further with their plugin model. For example, adding a sitemap is as easy as adding a plugin. Once the plugin is installed it’s just another task added into the Gatsby build process using information that is already available. With this modular approach, we can add, refactor, and redesign at will. The TAG website is now a living breathing internet creature more than ever before. Now on to TAGV5.2. diff --git a/docs/blog/2019-10-15-free-headless-cms/index.md b/docs/blog/2019-10-15-free-headless-cms/index.md index 7d23e23e2714e..4d8fae9b7cb03 100644 --- a/docs/blog/2019-10-15-free-headless-cms/index.md +++ b/docs/blog/2019-10-15-free-headless-cms/index.md @@ -18,7 +18,7 @@ How do you know which headless CMS is right for your site? In this post, we’ll 2. This headless CMS has to be robust enough to grow with the site over time. -3. This headless CMS has to work with with front-end frameworks like Gatsby. +3. This headless CMS has to work with with frontend frameworks like Gatsby. The difficulty with these must-haves is that there are no _truly free_ options. There are open source projects that provide code for free, but you have to host it somewhere. Then, there are hosted headless CMS’s with generous free tiers. But most of them have prohibitive pricing once your project grows. @@ -42,13 +42,13 @@ Every writer or marketer who works on the Internet is familiar with WordPress, s Cheap hosting is easy to find - providers like Bluehost and Amazon Lightsail offer WordPress hosting for about \$4 dollars a month. Other popular hosts like GoDaddy can get you going for less than \$10 dollars a month. -If your website needed all-in-one WordPress, then these cheap, shared hosting packages wouldn’t be enough to handle a website that expects any sort of traffic. However, you’re just using headless WordPress, and all that you ask from the software is to organize your content, and send it to a front-end framework like Gatsby. +If your website needed all-in-one WordPress, then these cheap, shared hosting packages wouldn’t be enough to handle a website that expects any sort of traffic. However, you’re just using headless WordPress, and all that you ask from the software is to organize your content, and send it to a frontend framework like Gatsby. So, as long as the host is reputable, and the service is secure, you can buy the most cost-friendly hosting available. See Gatsby’s guide on getting started with [over a dozen headless CMS’s](https://www.gatsbyjs.org/docs/headless-cms/) ## Option #2. Netlify CMS -Netlify created a free headless CMS modeled after open source projects like WordPress and Drupal, so JAMstack sites would have options beyond SaaS CMS’s. [Netlify CMS](https://www.netlifycms.org/) cleverly uses cloud git services like GitHub and Gitlab as the backend for your content, and claims to work with almost any static site generator, including Gatsby. +Netlify created a free headless CMS modeled after open source projects like WordPress and Drupal, so JAMstack sites would have options beyond SaaS CMS’s. [Netlify CMS](https://www.netlifycms.org/) cleverly uses cloud git services like GitHub and GitLab as the backend for your content, and claims to work with almost any static site generator, including Gatsby. ### How “free” is it? diff --git a/docs/blog/2019-11-05-how-gatsby-can-power-your-site-offline-even-without-javascript/index.md b/docs/blog/2019-11-05-how-gatsby-can-power-your-site-offline-even-without-javascript/index.md new file mode 100644 index 0000000000000..3dbbbface2691 --- /dev/null +++ b/docs/blog/2019-11-05-how-gatsby-can-power-your-site-offline-even-without-javascript/index.md @@ -0,0 +1,31 @@ +--- +title: "How Gatsby can power your site offline - even without JavaScript" +date: 2019-11-05 +author: David Bailey +excerpt: "With Gatsby's offline plugin, network troubles are a thing of the past." +tags: + - plugins + - performance + - accessibility +--- + +You know the feeling: you saw a cool website or read an interesting article the other day, and you'd like to check back on it, or maybe you’re with some people that you’d like to share it with. But what’s this? You don’t have any phone signal, and the wi-fi connection is spotty at best – if there is one at all! You attempt to open the page, but try as you might, the loading spinner just keeps on spinning... + +With `gatsby-plugin-offline`, that's a thing of the past. Install the plugin in an existing Gatsby site using npm or Yarn, add it to your `gatsby-config.js`, and your site will instantly gain offline support without any additional configuration needed. (Read full instructions on how to [add offline support with a service worker +](/docs/add-offline-support-with-a-service-worker/).) Now, whenever someone visits a page on your site, that page will be available later without an internet connection, along with any other pages which have been preloaded in the background. + +Recently `gatsby-plugin-offline` version 3 was released, adding some exciting new features such as the ability to pre-cache a customized set of pages. It also introduced some under-the-hood changes, the most notable being a major version upgrade of [Workbox](https://developers.google.com/web/tools/workbox), the library which powers the core functionality of `gatsby-plugin-offline`. However, arguably the most interesting change is that the plugin will now keep working even if you disable JavaScript on a website which uses it. + +How does this work? Service workers and page-level JavaScript run in different contexts and don't have direct access to each other's context, although they can communicate with each other using a built-in message API - or even via data contained within a request, since requests can be intercepted by the service worker. More on that point later. + +`gatsby-plugin-offline` has a wrapper API which makes use of the message API, enabling the page-level JavaScript to transfer data to/from the service worker - for example, this can be used to specify which JavaScript and CSS resources are essential for a particular page. Its service worker also serves a lightweight "offline shell" for pages which are available from the cache (determined by checking for each of the essential resources) instead of the full pre-rendered HTML. + +When you (or someone accessing your website) disable JavaScript for a particular domain, contrary to what you might expect, any service workers installed on that domain keep running. This means the plugin will continue to intercept page requests and serve a shallow offline shell if it determines that all the resources are available - even though JavaScript is required to display the content of the page in this case (since the offline shell doesn't contain pre-rendered HTML). + +With `gatsby-plugin-offline` version 3, this is no longer the case. When the plugin detects that JavaScript is disabled, it automatically disables the offline shell and switches to full pre-rendered HTML, allowing the site to function again! This is a huge advantage for accessibility, since it allows people to toggle scripts even after they've initially visited a site, without causing it to stop working. + +So, how does the service worker detect that JS is disabled, given that the client can't use JS to communicate this to the worker? Back to an earlier point: we can also communicate to the service worker using data contained within a request, such as its URL. So, if we request a specially formatted URL, and "catch" this request from within the service worker, we can tell it that JS is disabled. + +How does this work in practice? Firstly, the service worker keeps track of which page was requested last. Within the offline shell, we include a `noscript` tag in the head, inside which is a `meta` tag that specifies an immediate redirect to the URL `/.gatsby-plugin-offline:api=disableOfflineShell&redirect=true`. The service worker then "catches" this request, disables the offline shell, and then sends a `Location` header in its response which sends the browser back to the initially requested page. + +If you want to try out this feature for yourself, [add the latest `gatsby-plugin-offline` to an existing site](/docs/add-offline-support-with-a-service-worker/), or use the [Gatsby CLI](/docs/gatsby-cli) to run `gatsby new my-blog gatsby-starter-blog` and create a new site which includes the plugin out-of-the-box. Find any problems? [Let us know!](/contributing/how-to-file-an-issue/) diff --git a/docs/blog/2019-11-13-getting-set-up-to-manually-test-web-accessibility/index.md b/docs/blog/2019-11-13-getting-set-up-to-manually-test-web-accessibility/index.md new file mode 100644 index 0000000000000..49b6824497e24 --- /dev/null +++ b/docs/blog/2019-11-13-getting-set-up-to-manually-test-web-accessibility/index.md @@ -0,0 +1,124 @@ +--- +title: "Getting Set Up to Manually Test Web Accessibility" +date: 2019-11-13 +author: Madalyn Parker +canonicalLink: https://dev.to/madalynrose/getting-set-up-to-manually-test-web-accessibility-3gon +excerpt: "Manual testing accessibility requires some setup and base knowledge. Get ready to fire up your screen reader." +tags: + - accessibility + - testing + - setup + - a11y +--- + +## The Basics + +When I sat down with my brand new work computer, I wanted to get set up to manually test accessibility using as many browsers as I could. This meant keeping in mind a few key things and going through some extra steps. These steps are for using free screen readers with a Mac development environment. + +I'm going to lay out: + +- Free Screen Readers +- Browser/Screen Reader combinations +- Extra configuration needed to test your project on different platforms + +While this post will focus solely on setup, later posts in this series will cover other parts of accessibility manual testing. + +Please reach out if there are other topics you'd like to hear about! + +## Screen Readers + +Windows + +- [Narrator](https://support.microsoft.com/en-us/help/22798/windows-10-complete-guide-to-narrator) (made by Microsoft, pre-installed) +- [NVDA](https://www.nvaccess.org/about-nvda/) (most popular free solution) + +OSX + +- [VoiceOver](https://help.apple.com/voiceover/mac/10.15/) (made by Apple, pre-installed) + +iOS + +- [VoiceOver](https://support.apple.com/guide/iphone/turn-on-and-practice-voiceover-iph3e2e415f/ios) (made by Apple, pre-installed) + +Android + +- [TalkBack](https://support.google.com/accessibility/android/answer/6007100?hl=en&ref_topic=3529932) (made by Google, pre-installed) + +## Browser/Screen Reader Besties + +When working on a11y at a previous company, I worked closely with a team at Microsoft. They recommended that I only test Internet Explorer with NVDA and Edge with Narrator. This notion of technology pairings is important for testing since some combinations do not play well together and some combinations aren't widely used. + +Below are pairings in order of usage (omitting paid screen readers) according to a September 2019 [survey](https://webaim.org/projects/screenreadersurvey8/) of screen reader users: + +- NVDA & Firefox +- NVDA & Chrome +- VoiceOver & Safari +- VoiceOver & Chrome +- NVDA & Internet Explorer + +Narrator & Edge is not explicitly in the survey but I think it's still worth testing as Edge's adoption increases. + +## Extra configuration + +### Browsers + +Safari requires an extra setting to allow keyboard navigation: + +1. Open up Preferences > Advanced in Safari +2. check "Press Tab to highlight each item on a webpage" under the "Accessibility" section + +![Safari's Preferences window with "press tab to highlight each item on a webpage checked"](https://thepracticaldev.s3.amazonaws.com/i/q87r4si3i1f4riat79b5.png) + +### Mobile Devices + +If you have an IRL mobile device you'd like to use to test out mobile screen readers and other assistive apps you can reach localhost there too! + +#### Android + +To access localhost from your Android device you'll need to do (more than) a few things: + +1. First off, make sure your phone has developer options. You can do this by navigating to `Settings > System > About Phone` and then tapping **Build number** (the very bottom entry) **seven** times. +2. Now there should be a new list of settings under `Settings > System > Advanced > Developer Options`. Go here and enable _USB Debugging_ +3. Connect your device to your development machine via USB. +4. From Chrome, access the remote devices panel in DevTools (under `More Tools > Remote Devices`). +5. You should see that there is a pending device at the top of the list of devices. Your phone should have a pop-up prompt asking you to accept remote debugging. Accept remote debugging from your phone. +6. Now you need to enable Port Forwarding from Settings in the Remote devices tab in DevTools. (Settings are at the very bottom of the list of devices so you may have to scroll down to find them) Check the box to enable it and then click the _Add Rule_ button to create a port for your phone to access what's in your browser. Type in the port you want to use on your phone on one side (e.g. `3000`) and the local address you want to access from your computer (e.g. `localhost:9000` for a served Gatsby site) +7. Boom! If you go to `localhost:3000` on your phone you'll see your site! + +#### iOS + +1. Make sure both your device and your computer are on the same WiFi network. +2. Make sure you specify the host as `0.0.0.0` when you run your server. (e.g. `gatsby serve --host=0.0.0.0`) +3. On your Mac, go to `Settings > Sharing`. You can find the address for your computer's localhost in fine print under where it says "Computer Name." It will be in the format of `computer-name.local`. You can edit this address by clicking the "Edit..." button. (e.g. I changed mine to `gatsby.local` so it would be easier to type on my device) +4. On your iOS device, navigate to the address determined in the previous step with your port specified. (e.g. `gatsby.local:9000`) + +NOTE: My device tried to fill in the URL by adding `www.` at the beginning. If you're having trouble reaching your localhost, make sure there is no `www.` in your address bar. + +### Virtual Environments + +#### VirtualBox + +I downloaded a Windows 10 virtual machine from the [Windows Dev Center](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines) + +You can access your host computer's localhost from `10.0.2.2`. + +#### Parallels + +Parallels is a paid product, but since it requires extra configuration to access localhost I figured I'd cover that here too. + +When serving your site, make sure you are hosting it on `0.0.0.0`. For example, if I am running a Gatsby site I'd do `gatsby serve --host=0.0.0.0` + +Then, from your Parallels machine you can access localhost from `10.211.55.2` + +## Up Next + +There will be more posts in this series to equip you to manually test the accessibility of websites. For now, topics and timing are still up for discussion. + +I hope to cover topics like: + +- Navigating the web using the keyboard +- Screen reader tips and shortcuts +- Testing techniques and methods +- Other assistive technologies + +What would you like to see? Do you have tips you'd like to share? diff --git a/docs/blog/2019-11-14-announcing-gatsby-cloud/cloud-quickstart.png b/docs/blog/2019-11-14-announcing-gatsby-cloud/cloud-quickstart.png new file mode 100644 index 0000000000000..c15222069806b Binary files /dev/null and b/docs/blog/2019-11-14-announcing-gatsby-cloud/cloud-quickstart.png differ diff --git a/docs/blog/2019-11-14-announcing-gatsby-cloud/index.md b/docs/blog/2019-11-14-announcing-gatsby-cloud/index.md new file mode 100644 index 0000000000000..21f3c09abcc65 --- /dev/null +++ b/docs/blog/2019-11-14-announcing-gatsby-cloud/index.md @@ -0,0 +1,106 @@ +--- +title: "Announcing Gatsby Cloud" +date: 2019-11-14 +author: "Kyle Mathews" +excerpt: "I'm excited to announce that we're launching our commercial platform, Gatsby Cloud, which will provide a growing suite of tools for web creators" +tags: ["gatsby-inc"] +--- + +We're excited to announce the launch of [Gatsby Cloud](https://www.gatsbyjs.com/): a commercial platform of stable, trusted tools that enable web creators to build better websites. + +Gatsby Cloud enhances our [content mesh platform](https://www.gatsbyjs.org/blog/2018-10-04-journey-to-the-content-mesh/) with interoperable, out-of-the-box solutions to launch websites faster, and drive business success. + +This is a significant step forward for our diverse and thriving open-source community, and we're really proud of it. + +## Features + +Gatsby Cloud features include: + +- **Cloud Quickstart** that empowers new and non-technical users to create projects in minutes with a CMS, sample content, and connected Gatsby starter. +- **Real-time Preview** to simplify content creation and collaboration. Preview offers a private playground for developers, designers, marketers, and content creators. You can view changes to your site immediately and in context. +- **CMS Integrations**—with [plugins available for 389 content management systems and APIs](https://www.gatsbyjs.org/plugins/?=gatsby-source), Gatsby offers unrivaled CMS-compatibility in the market. +- **Builds and Reports (Private Beta)**—a new CI/CD solution for Gatsby that will dramatically speed up your Gatsby builds and give you feedback on site performance—with Lighthouse—and common Gatsby errors. [Signup for the private beta](https://www.gatsbyjs.com/builds-beta/) to be one of the first to access Builds and Reports! + +We want Gatsby Cloud to be used by everyone. [Our pricing structure includes a free tier](https://www.gatsbyjs.com/pricing/) designed to comfortably support personal and small sites. We're excited to see how the Gatsby community adopts and grows with our new services. + +### Quotes from early customers + +Jay Hostan, a senior product developer at global coffeehouse chain [Costa Coffee](https://www.costacoffee.com/), told us: + + +Deciding to use Gatsby Preview as a paid feature of Gatsby Cloud was a no brainer and has added a lot of value to our workflow. Before, we were building staging pipelines by hand. Preview allows our team to see content changes immediately, creating a tighter feedback loop so we can launch faster. It's enabled us to shift a lot of our focus to strategic projects and feature development. + + +Brian Webster, co-founder of the graphic and web design firm [Delicious Simplicity](https://www.delicious-simplicity.com/) with several clients on Gatsby Cloud said: + + +I love how Gatsby makes it possible to harness the power of React components, headless CMS architecture, and that it's a much more delightful workflow for developers. Now that we can use Gatsby Cloud features like Preview, our content-creator clients get an equally powerful yet simple workflow. + + +## Why Gatsby Cloud? + +### How we build for the web is changing + +Let's step back and discuss why we're building Gatsby and how our new Cloud platform fits into our vision for the project. + +For most of the history of the web, the dominant web architecture has been the LAMP stack e.g., applications like WordPress. But the last decade has seen the rise of two enormous trends—cloud computing and JavaScript-rich web apps (driven by component frameworks like React). Gatsby was founded around the idea that web architectures are converging on these two ideas and will be foundational for decades to come. + +Gatsby provides the building blocks for a modern web site: + +- **JavaScript Component Library**. Gatsby sites are React apps, so you can create high-quality, dynamic web apps, from blogs to e-commerce sites to user dashboards. +- **Load Data From Anywhere**. Gatsby pulls in data from any data source, whether it's Markdown files, a headless CMS like Contentful or WordPress, or a REST or GraphQL API. Use source plugins to load your data, then develop using Gatsby's uniform GraphQL interface. +- **SEO**. Unlike React client-side apps, Gatsby serves HTML files and is fully crawlable by search engines and social networks. +- **Security**. Traditional CMS applications expose APIs and services—many outside of your control. All of these are at risk of attack and require continuous maintenance and patching. Gatsby sites are static files served by a CDN talking to isolated API microservices & 3rd party APIs, leaving you with a much-reduced attack surface. +- **Performance Is Baked In**. Ace your performance audits by default. Gatsby automates code-splitting, image optimization, inlining critical styles, lazy-loading, and prefetching resources, and more to ensure your site is fast—no manual tuning required. +- **Host at Scale for Pennies**. Gatsby sites don't require servers, so you can host your entire site on a CDN for a fraction of the cost of a server-rendered site. Many Gatsby sites can be hosted for free on services like GitHub Pages and Netlify. + +Gatsby meets the needs of the modern web and has become wildly popular with hundreds of thousands of users. + +## Gatsby Cloud solves everyday problems + +In our many conversations with Gatsby users & customers over the years, there are three common problems Gatsby users bring up: + +1. **Starting complex projects. **People love the flexibility of being able to bring your own backends, but choosing the right backends and configuring everything can be difficult. +2. **Consistent & reliable workflows.** Delivering great websites requires collaboration between many stakeholders. People keep telling us about friction in workflows on their Gatsby projects compared to traditional CMSs. +3. **Fast builds. **Gatsby sites have a build process to deploy new changes, and people wish incremental builds were faster. Ideally, there'd be no builds at all as they're confusing for non-technical collaborators who are used to seeing their changes go live immediately when they save with traditional CMSs. + +Today's launch of Gatsby Cloud addresses these concerns and lays the foundation for many exciting things to come. + +## Cloud quickstart wizard + +People love the flexibility and power of Gatsby but also wish for preconfigured starters to base projects on. + +You can now head to [gatsbyjs.com](https://www.gatsbyjs.com/) and within minutes, create a new project with a CMS, sample content, and connected Gatsby starter. + +![Screenshot showing Gatsby Starters to start projects on Gatsby Cloud for portfolios, blogs, and e-commerce sites](./cloud-quickstart.png) + +We'll be adding many more of these starters in the future. + +## Gatsby Real-Time Preview + +Preview offers a private playground for developers, designers, marketers, and content creators. You can view changes to your site immediately and in context with instant updates triggered by a CMS or webhooks. It's basically a _shareable_, hot-reloading preview. Preview is compatible with a growing number of CMSs, including Drupal, Contentful, Contentstack, Sanity, DatoCMS, and CosmicJS, with WordPress coming soon. + +Preview has been in beta since May, and we've welcomed over 1000 beta testers and are near our 100th customer. Thank you to everyone who's helped test and support Preview! We've learned a lot from our beta users and customers. + +https://youtu.be/AmkI2iH6c40 + +## Gatsby Cloud Builds (in Private Beta) + +We'll soon be shipping a fast build service that will dramatically speed up your Gatsby builds. It will provide feedback while you develop and deploy your code and content changes to your hosting platform. + +Gatsby Cloud Builds works in similar ways to build services like Heroku, Netlify, Zeit, and others that integrate with GitHub and other services to automatically build and deploy your site when you make changes. We integrate with a number of different CDNs such as Netlify, Fastly, and Firebase as well as the major cloud providers so you can host your site wherever you'd like. + +We're tackling this problem in our Gatsby Cloud Builds service through two strategies that take advantage of the special nature of cloud computing. + +- Parallelizing CPU/IO/Network bound tasks across cloud functions e.g., image processing +- Heavily caching build artifacts so incremental builds are much much faster + +I explicitly designed Gatsby so the build process could be decomposed and run many times faster in a cloud environment. All Gatsby site & plugin code will run the exact same way in Cloud Builds as they run locally—just now heavily parallelized and cached. + +We will have lots more to say about our distributed cloud build service as we approach its launch. We've been working towards this goal for years, and we're very excited to share it with you. + +In the meantime, we invite you to [sign up for the beta to get early access](https://gatsbyjs.com/builds-beta/) and help us test and refine the service! + +## Try out Gatsby Cloud today! + +Go to [gatsbyjs.com](https://www.gatsbyjs.com/) to start using Gatsby Cloud today! diff --git a/docs/blog/2019-11-20-gazette-october/gatsby-days.jpg b/docs/blog/2019-11-20-gazette-october/gatsby-days.jpg new file mode 100644 index 0000000000000..14adda09956c3 Binary files /dev/null and b/docs/blog/2019-11-20-gazette-october/gatsby-days.jpg differ diff --git a/docs/blog/2019-11-20-gazette-october/gatsby-theme-firebase.png b/docs/blog/2019-11-20-gazette-october/gatsby-theme-firebase.png new file mode 100644 index 0000000000000..25b3741eb9d5b Binary files /dev/null and b/docs/blog/2019-11-20-gazette-october/gatsby-theme-firebase.png differ diff --git a/docs/blog/2019-11-20-gazette-october/index.mdx b/docs/blog/2019-11-20-gazette-october/index.mdx new file mode 100644 index 0000000000000..cbe04e574f063 --- /dev/null +++ b/docs/blog/2019-11-20-gazette-october/index.mdx @@ -0,0 +1,124 @@ +--- +title: 'Gatsby Gazette: The "What happened to October?" Edition' +date: 2019-11-20 +author: Mike Allanson +excerpt: "It's November already. But what happened in October? Read on to find out more." +tags: + - gazette +--- + +October means halloween! For your spooky reading pleasure, the blog now has a dark mode. So dim the lights, pull up a comfy chair and let's begin. + +In September we posted our [Series A funding announcement](https://www.gatsbyjs.org/blog/2019-09-26-announcing-gatsby-15m-series-a-funding-round/), then headed to the UK for Gatsby Days, London. Fear not, if you missed all the action you can [catch up by watching the videos](https://www.youtube.com/watch?v=UvO7h_KwgpE&list=PLCU2qJekvcN2f9rgS50xy7-4QBpgwid4G). + +![Audience at Gatsby Days, London](./gatsby-days.jpg) + +Follow that YouTube playlist to find a plethora of goodies including a keynote from Kyle Mathews, info on building and selling Gatsby themes by [Horacio Herrera](https://twitter.com/hhg2288) and advice on writing accessible components from [Marcy Sutton](https://twitter.com/marcysutton). + +## Team Highlights + +On with some features and updates from the team. + +### Structured Logging + +First up is something we're calling _structured logging_. We've done some behind the scenes re-working of Gatsby's logging code. Gatsby now keeps an internal list of messages and activities, and can output those messages in different formats. As an example, run `gatsby build --json` to see the your build logs output as JSON instead of the usual log messages. + +In the future, this will enable things like a Gatsby desktop app. Have a nose at [the PR](https://github.com/gatsbyjs/gatsby/pull/14973) to see what went into this release. There have also been a few fixes and enhancements to the standard CLI output as a result of this work. + +### Is gatsbyjs.org translated yet? + +Following on from [an RFC](https://github.com/gatsbyjs/rfcs/pull/42) in September, there are now 10 in-progress translations for Gatsby's documentation. Want to get involved? Check out [the new Gatsby Docs Translation Guide](https://www.gatsbyjs.org/contributing/gatsby-docs-translation-guide/). Thanks to [Nat Alison](https://twitter.com/tesseralis) for driving this project! + +### The Gatsby Build Process + +Have you ever wondered what Gatsby _does_ when you run a build? There's now a new docs page that walks through the details. [Overview of the Gatsby Build Process](https://www.gatsbyjs.org/docs/overview-of-the-gatsby-build-process/) is the place to go. I particularly like [the diagram that explains the different layers of Gatsby](https://www.gatsbyjs.org/docs/overview-of-the-gatsby-build-process/#what-happens-when-you-run-gatsby-build). + +### Schema Customization Examples + +We're gradually moving our official plugins over to use the Schema Customization APIs we added earlier this year. See [the changes to `gatsby-transformer-sharp` for an example](https://github.com/gatsbyjs/gatsby/pull/18871). If you're interested in helping out with this, there's now a little known plugin that will write out the inferred schema to disk. See [gatsby-plugin-schema-snapshot](https://www.gatsbyjs.org/packages/gatsby-plugin-schema-snapshot/). + +### gatsby-plugin-offline + +[gatsby-plugin-offline](https://www.gatsbyjs.org/packages/gatsby-plugin-offline) has been updated to [handle more edge cases](https://github.com/gatsbyjs/gatsby/pull/17590). The plugin will now revert back to the network if a visitor disables JavaScript after the site has already been cached. + +Thanks to [David Bailey](https://twitter.com/davidbailey) for working on this! + +### Dark Mode + +Have you tried out the superbly stylish dark mode for gatsbyjs.org? + +Hit the "Activate Dark Mode" button in the site header to see it in action. You can see the [main PR for this](https://github.com/gatsbyjs/gatsby/pull/18348), along with a series of [follow up PRs to iron out kinks](https://github.com/gatsbyjs/gatsby/pulls?q=is%3Apr+dark+mode+is%3Aclosed) to learn more. + +### Grab Bag + +There are a few more bits and bobs that are also worth mentioning. + +Have you been working with Gatsby themes? Under the hood, a theme and a plugin are pretty similar. Until recently, creating a local theme in your `plugins` directory would have caused an error. A recent update fixes this, making the `plugins` directory work for local themes. Maybe you could use this for prototyping or one-off themes. See PR [#15856](https://github.com/gatsbyjs/gatsby/pull/15856) for the full lowdown. + +A persistent bug that was first reported back in 2017 [has _finally_ been squashed](https://github.com/gatsbyjs/gatsby/pull/19009). Good riddance! 🙂 + +And finally... [no-mouse-days](https://www.npmjs.com/package/no-mouse-days). I can't improve on the description so I'm going to copy and paste it right here: + +> Ever wanted a package that disables the mouse cursor one day a week so you can test keyboard accessibility as a team? No? Well here you go anyway. + +Grab it from https://www.npmjs.com/package/no-mouse-days. + +## Community Highlights + +Hacktoberfest Hacktoberfest Hacktoberfest. Yes, October means Hacktoberfest. A huge welcome to all our new and returning contributors! + +### Your Pull Requests + +There are way too many contributions to mention individually, but let's try to take a rocket powered tour through some highlights. + +- Wide improvements to all of Gatsby's documentation. Bringing docs in-line with the style guide proved to be a popular (and _very_ valuable) activity last month. +- Improvements to how [gatsby-plugin-offline handles custom link tags](https://github.com/gatsbyjs/gatsby/pull/16691) with the `rel=preconnect` attribute, thanks to [Espen Hovlandsdal](https://github.com/rexxars) +- A [fix for the `wrapPageElement` API while running `gatsby develop`](https://github.com/gatsbyjs/gatsby/pull/17111), courtesy of [Valeriy](https://github.com/ValeraS) +- [Performance improvements to querying](https://github.com/gatsbyjs/gatsby/pull/17682), adding a nice speed boost when building larger sites, thanks to [Matthew Miller](https://github.com/me4502) +- Thanks again to Matthew, [this PR improved Gatsby's type inference](https://github.com/gatsbyjs/gatsby/pull/18008), making it faster and less memory intensive +- A [fix for `gatsby-plugin-manifest`](https://github.com/gatsbyjs/gatsby/pull/17426) that ensures manifest links are updated after page navigation, thanks to [DK the Human](https://github.com/dkthehuman) +- An issue that happened when [creating a resolver using the `context.nodeModel` API was fixed](https://github.com/gatsbyjs/gatsby/pull/18650) by [Nicky Fahey](https://github.com/nickyfahey) +- [This PR](https://github.com/gatsbyjs/gatsby/pull/16686) reduces the number of files that are changed with each build. This should result in faster deploys on services like Netlify, particularly for larger sites. Huge thanks to [Alex Fenton](https://github.com/afenton90)! +- [Bailey Swartz](https://github.com/sever1an) fixed ordering when using matchpaths in [#18478](https://github.com/gatsbyjs/gatsby/pull/18478) + +## Site of the Month + +The site of the month for October is [IBM's Carbon Design System](https://www.carbondesignsystem.com/). What's it all about? + +> Carbon is IBM’s open-source design system for products and experiences. With the IBM Design Language as its foundation, the system consists of working code, design tools and resources, human interface guidelines, and a vibrant community of contributors. + +Seems like everyone is building design systems these days, and for good reason. There's a lot to like in here. It's based on guidelines to be _open_, _inclusive_, _modular_, and _consistent_. Components are available for React, Angular, Vue and Vanilla JS. + +Why is it our site of the month? + +- Design system with lots of well thought out components and clear guidelines +- Open source +- Used at scale at IBM + +## Theme of the Month + +![Screenshot of gatsby-theme-firebase's README](./gatsby-theme-firebase.png) + +[`gatsby-theme-firebase`](https://github.com/epilande/gatsby-theme-firebase) might be the quickest way to add full featured Auth to your site, and it's our theme of the month for October! + +Add the theme, add your Firebase credentials and off you go. Want to change anything? Use [component shadowing](https://www.gatsbyjs.org/blog/2019-04-29-component-shadowing/) to override whatever you like. + +## Gatsby Cloud + +Last but _certainly_ not the least, we launched [Gatsby Cloud](https://www.gatsbyjs.com/cloud/) last week! 💃 + +Here's an excerpt from [Kyle's announcement post](https://www.gatsbyjs.org/blog/2019-11-14-announcing-gatsby-cloud/): + +> We’re excited to announce the launch of Gatsby Cloud: a commercial platform of stable, trusted tools that enable web creators to build better websites. Gatsby Cloud enhances our content mesh platform with interoperable, out-of-the-box solutions to launch websites faster and drive business success. This is a significant step forward for our diverse and thriving open-source community, and we’re really proud of it. + +Gatsby Cloud features include a quickstart to create a CMS-powered site in seconds, real-time preview for your Gatsby sites, Lighthouse reports and superpowered Builds. + +Visit [gatsbyjs.com](https://www.gatsbyjs.com/) to start using Gatsby Cloud today! We can't wait to hear what you think. + +## Thank You and Good Night + +That's all, folks. + +As usual, if you have questions about any of this, feel free to tweet to us at [@gatsbyjs](https://twitter.com/gatsbyjs) or come hang out at our [Discord](https://gatsby.dev/discord). + +See you soon again! ❤️ diff --git a/docs/blog/2019-11-21-how-to-convert-an-existing-gatsby-blog-to-use-mdx/index.md b/docs/blog/2019-11-21-how-to-convert-an-existing-gatsby-blog-to-use-mdx/index.md new file mode 100644 index 0000000000000..4b2599b427a26 --- /dev/null +++ b/docs/blog/2019-11-21-how-to-convert-an-existing-gatsby-blog-to-use-mdx/index.md @@ -0,0 +1,224 @@ +--- +title: "How to convert an existing Gatsby blog to use MDX" +date: 2019-11-21 +author: Thomas Wang +excerpt: "It can be a big tricky to add MDX to an existing blog. This blog post covers how to install and configure MDX to Gatsby's blog starter" +tags: + - blogs + - mdx + - markdown +--- + +## What is MDX? + +MDX is a file format that lets you add JSX to Markdown files via a `.mdx` file! It was started by and is maintained by Gatsby's [John Otander](https://github.com/johno) and the [open source community on GitHub](https://github.com/mdx-js/mdx). + +With MDX, you can import React components and declare them alongside regular markdown syntax with JSX. This is useful to display specific component examples alongside the actual code, complex interactive components like charts, reusable components across multiple pages like sign-up forms, and more! + +## Adding MDX to Gatsby Starter Blog + +It can be a big tricky to add MDX to an existing blog. The following 5 steps will cover how to install and configure MDX to work with [Gatsby's blog starter](https://github.com/gatsbyjs/gatsby-starter-blog/tree/master), which as of [today's version](https://github.com/gatsbyjs/gatsby-starter-blog/tree/8852c1e51651b902f19706ff2ca9f60dabc25709), does not have MDX pre-installed. + +You can also see the [full changes in PR #19580](https://github.com/gatsbyjs/gatsby/pull/19580/files) for an overview of the changes you have to make to get MDX working. As stated above, this introduces changes to [Gatsby's blog starter](https://github.com/gatsbyjs/gatsby-starter-blog/tree/master), which you can install with Gatsby CLI. + +```bash +gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog +``` + +### Step 1 + +Install [gatsby-plugin-mdx](/packages/gatsby-plugin-mdx/), the official plugin for using MDX with Gatsby. Also install `gatsby-plugin-feed-mdx` for our RSS feeds. Finally, install `@mdx-js/mdx` and `@mdx-js/react`. + +```bash +npm install --save gatsby-plugin-mdx gatsby-plugin-feed-mdx @mdx-js/mdx @mdx-js/react +``` + +### Step 2 + +In `gatsby-config.js`, replace `gatsby-transformer-remark` with `gatsby-plugin-mdx`, along with the following changes: + +```diff:title=gatsby-config.js + { +- resolve: `gatsby-transformer-remark`, ++ resolve: `gatsby-plugin-mdx`, + options: { ++ extensions: [`.mdx`, `.md`], +- plugins: [ ++ gatsbyRemarkPlugins: [ + { + resolve: `gatsby-remark-images`, + options: { + maxWidth: 590, + }, + }, + { + resolve: `gatsby-remark-responsive-iframe`, + options: { + wrapperStyle: `margin-bottom: 1.0725rem`, + }, + }, + `gatsby-remark-prismjs`, + `gatsby-remark-copy-linked-files`, + `gatsby-remark-smartypants`, + ], + }, + }, +``` + +For reference, here's the full configuration for `gatsby-plugin-mdx`. + +```js:title=gatsby-config.js +{ + resolve: `gatsby-plugin-mdx`, + options: { + extensions: [".mdx", ".md"], + gatsbyRemarkPlugins: [ + { + resolve: `gatsby-remark-images`, + options: { + maxWidth: 590, + }, + }, + { + resolve: `gatsby-remark-responsive-iframe`, + options: { + wrapperStyle: `margin-bottom: 1.0725rem`, + }, + }, + `gatsby-remark-prismjs`, + `gatsby-remark-copy-linked-files`, + `gatsby-remark-smartypants`, + ], + }, +}, +``` + +Then, replace `gatsby-plugin-feed` with `gatsby-plugin-feed-mdx`. This will allow the the RSS feed of the site to parse MDX. + +```diff:title=gatsby-config.js +- `gatsby-plugin-feed`, ++ `gatsby-plugin-feed-mdx` +``` + +Now, since we're no longer using `gatsby-transformer-remark` and `gatsby-plugin-feed`, you can uninstall them. + +```bash +npm uninstall --save gatsby-transformer-remark gatsby-plugin-feed +``` + +### Step 3 + +In `gatsby-node.js`, replace `allMarkdownRemark` with `allMdx`. + +```diff:title=gatsby-node.js +# line 11 +- allMarkdownRemark( ++ allMdx( +``` + +```diff:title=gatsby-node.js +# line 35 +- const posts = result.data.allMarkdownRemark.edges ++ const posts = result.data.allMdx.edges +``` + +Next, replace `MarkdownRemark` with `Mdx`. + +```diff:title=gatsby-node.js +# line 56 +- if (node.internal.type === `MarkdownRemark`) { ++ if (node.internal.type === `Mdx`) { +``` + +### Step 4 + +In `src/pages/index.js`, replace `allMarkdownRemark` with `allMdx` in the `render()` method. + +```diff:title=src/pages/index.js +# line 13 +- const posts = data.allMarkdownRemark.edges ++ const posts = data.allMdx.edges +``` + +Also replace `allMarkdownRemark` with `allMdx` in the GraphQL query. + +```diff:title=src/pages/index.js +# line 59 +- allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { ++ allMdx(sort: { fields: [frontmatter___date], order: DESC }) { +``` + +### Step 5 + +In `src/templates/blog-post.js`, replace `markdownRemark` with `mdx` in the `render()` method. + +```diff:title=src/templates/blog-post.js +# line 11 +- const post = this.props.data.markdownRemark ++ const post = this.props.data.mdx +``` + +Also replace `markdownRemark` with `mdx` in the GraphQL query. + +```diff:title=src/templates/blog-post.js +# line 93 +- markdownRemark(fields: { slug: { eq: $slug } }) { ++ mdx(fields: { slug: { eq: $slug } }) { +``` + +Add an import statement for `MDXRenderer` from `gatsby-plugin-mdx`. + +```diff:title=src/templates/blog-post.js +# line 3 ++ import { MDXRenderer } from "gatsby-plugin-mdx" +``` + +We'll be using `body` instead of `html` in our GraphQL query. + +```diff:title=src/templates/blog-post.js +# line 96 +- html ++ body +``` + +Now we can replace the `
` element with the `dangerouslySetInnerHTML` attribute and instead use `` with `post.body`. + +```diff:title=src/templates/blog-post.js +# line 41 +-
++ {post.body} +``` + +And... that's it! After these changes, a Gatsby blog should be able to use MDX files to render JSX alongside markdown. To test that everything works, add a `.mdx` file to `[your-blog]/content/blog/` and write some JSX. Then, run `gatsby develop` and check `localhost:8000/blog/` for your new post. The JSX should rendered as an element on the new post page. + +For example, the following code should render a test button. Navigate to `localhost:8000/blog/example/` and you should see a clickable button in your blog post! + +````mdx:title=content/blog/example.mdx +--- +title: MDX! +date: "2019-10-22" +description: "A post showing MDX in action" +--- + +This is a post showing MDX in action. This starter now comes with MDX out-of-the-box! + +```js +// you can write JSX in your Markdown! + +``` + + + +## MDX + +MDX lets you write JSX embedded inside markdown, perfect for technical blogs. MDX works with Gatsby through [gatsby-plugin-mdx](https://www.gatsbyjs.org/packages/gatsby-plugin-mdx/). You can learn more about it in the Gatsby docs: [Getting Started with MDX](https://www.gatsbyjs.org/docs/mdx/getting-started/). +```` + +![example post mdx](./screenshot.png) + +If you're interested in spinning up a new personal blog with MDX, I've prepared [Gatsby personal blog starter](https://github.com/thomaswangio/gatsby-personal-starter-blog) for your usage! + +## Further Reading + +1. [Gatsby Reference Guide on MDX](/docs/mdx/) +2. [MDX Gatsby Documentation](https://mdxjs.com/getting-started/gatsby) diff --git a/docs/blog/2019-11-21-how-to-convert-an-existing-gatsby-blog-to-use-mdx/screenshot.png b/docs/blog/2019-11-21-how-to-convert-an-existing-gatsby-blog-to-use-mdx/screenshot.png new file mode 100644 index 0000000000000..5b1df9cc6c53c Binary files /dev/null and b/docs/blog/2019-11-21-how-to-convert-an-existing-gatsby-blog-to-use-mdx/screenshot.png differ diff --git a/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/final-state-comment.png b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/final-state-comment.png new file mode 100644 index 0000000000000..9704eefcf858a Binary files /dev/null and b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/final-state-comment.png differ diff --git a/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/final-state.png b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/final-state.png new file mode 100644 index 0000000000000..f9229a0e09224 Binary files /dev/null and b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/final-state.png differ diff --git a/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/first-phase.png b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/first-phase.png new file mode 100644 index 0000000000000..b11d8d0245baf Binary files /dev/null and b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/first-phase.png differ diff --git a/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/index.md b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/index.md new file mode 100644 index 0000000000000..5b1969f71be8f --- /dev/null +++ b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/index.md @@ -0,0 +1,91 @@ +--- +title: Making it easier to start with Gatsby Cloud for free +date: 2019-11-25 +author: Shannon Soper +tags: ["ux", "cloud", "cms"] +--- + +When you go to [our Quickstart page](https://www.gatsbyjs.com/get-started/) to try Gatsby Cloud, you’ll probably find yourself in one of two situations. + +Situation 1: you already have a Gatsby project +Situation 2: you don’t have a Gatsby project yet + +![A screenshot of the current Get Started page on gatsbyjs.com](final-state.png) + +Either way, Gatsby Cloud will work for you! Through the [Cloud Quickstart page](https://www.gatsbyjs.com/get-started/), you can integrate your site with its data source(s) to drive Preview and automate builds. And it’s no commitment and no credit card required. All you need is a GitHub account. + +Here’s the reason I’m writing this blogpost. We are making the [Cloud Quickstart page](https://www.gatsbyjs.com/get-started/) better and want to show you how it’s evolved over time and what the next steps are. + +## How are we making Gatsby Cloud better over time? + +### We’re learning about users + +We watched 8 React developers who had never heard of Gatsby before create an account on Gatsby Cloud. We took careful notes, implemented new designs, and ran the usability tests _again_. + +Here’s a few screenshots from earlier designs with some notes summarizing major feedback from users. + +### Earliest version + +Here's the earliest version we shipped. + +![A screenshot of an earlier onboarding design](first-phase.png) + +### Next phase + +Here's a screenshot of a Figma prototype we tested based on feedback on the first version. + +![A screenshot of a prototype that we tested next](middle-option.png) + +### We’re prioritizing what we build according to user needs + +From this process of testing prototypes, implementing changes, and testing again, we answered these questions: + +- What blocks people from onboarding onto Gatsby Cloud? +- What creates friction for people onboarding onto Gatsby Cloud? +- What creates value for people onboarding onto Gatsby Cloud? + +## What blocks people from onboarding onto Gatsby Cloud? + +Connecting with a GitHub organization is the most confusing step, for several reasons. First of all, it’s not obvious in the product that we only offer GitHub integrations at this time (GitLab and Bitbucket will come eventually), so many users click around, looking for a way to connect to GitLab and/or Bitbucket. + +We’re currently shipping some more improvements to the GitHub integration that I’ll blog about in a separate post soon! + +## What created friction for people onboarding onto Gatsby Cloud? + +Choosing a CMS was confusing for four of the eight testers. None of them had an opinion on which CMS to choose. Rather than force developers to integrate a CMS they aren't already using, we realized we should offer an alternative. We're creating an alternative starter where all content lives in the repository, alongside their code. We've opted for MDX, a powerful combination of Markdown and JSX. + +## What creates value for people onboarding onto Gatsby Cloud? + +Users found value in some aspects of our early onboarding designs and we wanted those good things to persist and grow, if possible. + +For example, choosing a starter was fun, and 3 of the users wanted more details about the starters. On starter cards, we added a link to their github repos or /starters/ page on .org + +### Product, design, and engineering are doing something about the feedback + +We’re tracking all feedback in GitHub and shipping improvements according to a prioritization system that relies on three metrics, thanks to [Step 3 of Barron Caster’s 3x Conversion Playbook](https://medium.com/hackernoon/the-3x-conversion-playbook-3a9b954b937d). + +- How confident are we that this problem is real? +- How much of an impact would fixing this problem have on major user workflows? +- How quickly can we fix this problem? + +Product, the design team and the Cloud engineering team are collaboratively designing solutions. And then...yep, you guessed. Shipping and testing again. + +## Current onboarding + +Here is a screenshot of the current onboarding experience and a brief overview of some planned improvements. + +![A screenshot of the current onboarding experience](final-state-comment.png) + +## Planned improvements to Gatsby Cloud + +We’ve shipped a ton of improvements already, and have a few more that are in progress as we speak! + +- Adding an MDX starter +- Clarifying the step in which users add a GitHub organization because using a starter vs using an existing Gatsby site require different flows +- Prioritizing the status of production builds in the product interface to make sure people can debug their most important branch + +## Feedback + +Hearing your feedback helps us make Gatsby better. Sign up to tell me about your experience with Gatsby Cloud by [booking time on my calendar!](https://calendly.com/shannon-soper/gatsby-cloud-usability) + +It’d also be valuable to hear which CMSs and/or other data sources you’d like to see integrations and starters for! [Take this survey to let us know](https://twitter.com/shannonb_ux/status/1199077543694893056). diff --git a/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/middle-option.png b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/middle-option.png new file mode 100644 index 0000000000000..d0796290907db Binary files /dev/null and b/docs/blog/2019-11-25-getting-started-with-gatsby-cloud/middle-option.png differ diff --git a/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/cosmic-js-gatsby-preview-screenshot.gif b/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/cosmic-js-gatsby-preview-screenshot.gif new file mode 100644 index 0000000000000..e37673c313771 Binary files /dev/null and b/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/cosmic-js-gatsby-preview-screenshot.gif differ diff --git a/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/cosmic-js-gatsby-preview-screenshot.jpg b/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/cosmic-js-gatsby-preview-screenshot.jpg new file mode 100644 index 0000000000000..b6bcc59b30a7d Binary files /dev/null and b/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/cosmic-js-gatsby-preview-screenshot.jpg differ diff --git a/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/index.md b/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/index.md new file mode 100644 index 0000000000000..e67ca1434a715 --- /dev/null +++ b/docs/blog/2019-11-25-introducing-gatsby-preview-for-cosmic-js/index.md @@ -0,0 +1,46 @@ +--- +title: "Introducing Gatsby Preview for Cosmic JS" +date: 2019-11-25 +author: Tony Spiro +excerpt: "We’re excited to announce the official release of Gatsby Preview for Cosmic JS that enables you to add powerful content preview functionality to your Cosmic JS Gatsby website." +tags: + - Cosmic JS + - Headless CMS + - Gatsby Preview +--- + +We’re excited to announce the official release of Gatsby Preview for [Cosmic JS](https://www.cosmicjs.com). This new integration enables you to add powerful content preview functionality to your Cosmic JS Gatsby website. + +## Getting Started + +1. First go to the [Gatsby Getting Started Page](https://www.gatsbyjs.com/get-started/) and follow the links for Cosmic JS. +2. Select the [Cosmic JS-powered Gatsby Blog](https://www.cosmicjs.com/apps/gatsby-blog) +3. You will then be asked for your GitHub and Cosmic JS authentication, so make sure you have both accounts set up ([sign up for Cosmic JS here](https://app.cosmicjs.com/signup)). +4. After onboarding, go to any Post in your Cosmic JS Bucket and find the big, beautiful, purple button to preview your content. + ![Cosmic JS Gatsby Preview Screenshot](./cosmic-js-gatsby-preview-screenshot.jpg) + +#### What happens? + +After clicking the “Open Preview” button, a new tab will open to instantly show you what the content looks like for this specific version on your Gatsby website. This simple one-click preview will greatly enhance your content team’s content-creation workflow. + +![Cosmic JS Gatsby Preview Screenshot](./cosmic-js-gatsby-preview-screenshot.gif) + +#### How did this integration happen? + +The Cosmic JS / Gatsby Preview integration is the result of close collaboration between both teams to make the integration as easy as possible. Both sides had to refactor a bit of existing functionality to make it seamless. And the feedback that came from the collaboration effort actually helped to improve both products. We’re happy to say this powerful feature can be integrated in just a few clicks. + +#### Why is this a big deal? + +Both Gatsby and Cosmic JS believe deeply in providing developers the best development experience possible. But it’s not just about developers. Content creation team members are crucial to building great web products. And one of the most requested features for content creators is preview, but this has been a challenge for developer teams pushing for highly-optimized JAMStack websites built on Gatsby. + +Gatsby Preview solves this problem by providing a simple button for content creators to experience an instant preview of content directly in the CMS dashboard. Gatsby preview with the [Cosmic JS headless CMS](https://www.cosmicjs.com/headless-cms), is a further extension to empower content creators to preview content quickly and easily, giving teams faster content marketing velocity. + +#### What’s next? + +We’re excited to continue to work closely with the Gatsby team to help create more value-added integrations between both services. It’s our goal to continue to provide the full spectrum of team members the best tools to be successful. + +Our users have been very helpful with letting us know ways to improve the Cosmic JS + Gatsby stack combo. So if you have any suggestions on ways we can improve, please let us know in the [Cosmic JS Slack channel](https://cosmicslack.herokuapp.com/) or on [our Twitter](https://twitter.com/cosmic_js). + +Happy building! + +— Tony and the Cosmic Team diff --git a/docs/blog/2019-12-10-gatsby-brings-speed-to-mediacurrent-com/index.md b/docs/blog/2019-12-10-gatsby-brings-speed-to-mediacurrent-com/index.md new file mode 100644 index 0000000000000..1447b01d2dac3 --- /dev/null +++ b/docs/blog/2019-12-10-gatsby-brings-speed-to-mediacurrent-com/index.md @@ -0,0 +1,72 @@ +--- +title: Gatsby Brings Speed and Simplicity to Mediacurrent.com +date: 2019-12-10 +author: Mark Casias +excerpt: "We believe Gatsby is a superior solution that can work for many organizations looking to leverage a fast, secure React-based front-end for their website." +tags: + - drupal + - case-studies +--- + +Back in 2016 we were planning the latest [Mediacurrent.com](https://www.mediacurrent.com) site redesign and were intrigued by the decoupled approach which was gaining popularity in the Drupal community. We liked the idea of breaking apart the front-end and back-end so that we could have more flexibility in how we executed redesigns (i.e. redesigns would not be tied to the Drupal upgrade lifecycle). + +We started this journey with Jekyll, but quickly switched to Gatsby. We're excited to have found the organizational agility we were looking for and now believe that Gatsby is a superior solution that can work for many organizations looking to leverage a fast, secure React-based front-end for their website. + +## Finding a Front End Framework + +While we were investigating the best decoupled approach for Mediacurrent.com, our team researched various options including Node.js frameworks like Express.js. We ran into a common problem -- the level of complexity required to integrate the various framework systems. We asked ourselves, “Was all of this necessary for a pretty typical corporate site?” + +### Take One: A Static Site Build With Drupal and Jekyll + +Along the way, we reviewed static generators that could solve some of the complexity problems and we liked the performance and security benefits Jekyll offered. At the time of our review, we expected to see more Jekyll/Drupal integrations in the wild than we found. Drupal could _simply_ publish content as markdown files that Jekyll could then consume. We did several POC’s and liked the overall approach. At first, Jekyll looked great, but it wasn’t long before Jekyll turned into “Mr. Hyde." + +For small blogging sites where content structure is simple and doesn’t require a myriad of 3rd party integrations, Jekyll shines. But when used as a static front-end for our Drupal 8 website, it soon became apparent that Jekyll wasn’t the best fit. We typically make daily content updates through our Drupal CMS which required Jekyll’s markdown files to constantly be updated with new content via source control. This added to the operational load of maintaining the site because there were often Git merge conflicts that had to be resolved. + +## Why Gatsby + +Luckily, our team had been researching and testing Gatsby as a potential solution for our site’s front-end woes. We realized Gatsby was an ideal fit for our front-end due to its ability to compile quickly and its component display flexibility. Other features of Gatsby that appealed to us included: + +- A robust plugin system that easily integrates with Drupal and other systems +- React and GraphQL-based +- Highly optimized for performance + +Additionally, Gatsby’s streamlined development workflow allowed us to make front-end design changes more quickly compared to working with a CSS-based templating system or Jekyll’s markdown files. + +## Migrating to Gatsby + +To replace Jekyll, we embarked on migrating our site’s front-end to Gatsby. We scoped the effort required which included converting Jekyll markdown files to Gatsby React components. The conversion process took less time than we estimated due to Gatsby’s clean, well-thought architecture. The back-end CMS configuration was minimal -- enable and configure Drupal’s JSON:API module. We had 7 content types on our site whose content would publish to Gatsby. Within each content type, we previously implemented Drupal’s Paragraphs module to allow structured content to be published to different devices. We found that in order to properly publish Paragraphs-based content, we needed to integrate it with GraphQL fragments. + +During the migration project, we ran into a series of unknowns that we hadn’t considered before starting development: + +- Build times + - The amount of content and assets were more than a usual Gatsby build. This caused our builds to time out in Netlify, our host. + - To resolve this, we started using a Jenkins build process which does the build, then pushes the build to Netlify. Since caching is still available on Jenkins, the build times have improved. + - More recently, we are working on leveraging [Gatsby Preview](https://www.gatsbyjs.com/preview/) which allows us to see changes _immediately_ on a preview site as well as the Gatsby Builds feature which cuts down our build times dramatically. +- Image processing + - Processing images was one of the build processes that increased the build time. Consequently, many published images caused the build to take longer than expected. We worked on reducing and unpublishing older content and redirecting it to new, fresh content. +- Body field processing. + - Images in the body field are not part of the regular processing and Drupal will render relative paths. Since these paths are not part of Gatsby, we needed to add logic that updates an image’s path to point to our Drupal instance URL. + - While we can access the images through the entity id, there was a second problem where the file would not transliterate the names and add the `%20` HTML character code where spaces are expected. At this time we are working on a patch for the gatsby-source-drupal, which changes the name of the file to replace `%20` with a dash to make it more browser friendly. This will be contributed back to the community. In the meantime, we are redirecting any images inside a body field to our publishing system. +- We found short codes for files from our Drupal 7 instance that were processed in the Jekyll build process. + - We band-aided this fix with our Jekyll module. We had to go back and re-publish this information correctly. +- Audio file information. + - This was patched through our Jekyll module, but we added a JSON:API field enhancer which added the necessary data to show audio files. +- External JS calls. (Acquia Lift, Pardot) + - Since Gatsby is ultimately a React application, the way to insert tracking cookies, and other 3rd Party scripts required workarounds. Fortunately, the gatsby-ssr API made this easy. We used the onRenderBody lifecycle to confirm which environment we were on, and inserted the required script tags accordingly. + +## Final Thoughts + +Ultimately, the decision to convert Mediacurrent.com to a Gatsby front-end was a wise move. Considering the issues we inherited by using a static-site generator that wasn’t intentionally built as a CMS front-end, Gatsby has been a welcome improvement. The benefits we’re experiencing with Gatsby are: + +- No wait time to apply Drupal module updates. The Gatsby front-end and Drupal back-end are completely decoupled. +- Simplified decoupled architecture with no middle-men. +- Front-end design updates can be deployed without concern for impact on back-end logic. +- [Gatsby Preview](https://www.gatsbyjs.com/preview/) allows us to view content updates in real-time prior to publishing to production. +- Build times are now much improved using Gatsby’s new Build feature (in beta). We are seeing builds come in at 4-8 minutes on average compared to Jekyll which took up to 15 minutes to compile. We also know that incremental builds are coming soon and will provide substantial improvements. + +We've written a bit more about our work with Gatsby elsewhere -- if you're curious, you can check out Ben Robertson’s [Gatsby Accessibility Starter](/starters/benjamingrobertson/gatsby-starter-accessibility/) and these additional resources: + +- [Digital Display With Decoupled Drupal 8 & Gatsby](/blog/2019-07-09-digital-display-drupal-gatsby/) - City of Sandy Springs Case Study +- [Move Fast, Don’t Break Things: Trends in Modern Web Dev with Mediacurrent](https://youtu.be/QiocnDGnKfs) - Gatsby Days presentation by Ben Robertson +- [Maximizing the Potential of Component-Driven Drupal Development with Gatsby](/blog/2019-06-28-component-driven-drupal-development/) - Blog post +- [Gatsby for Agencies and Teams: Better, Faster, Smarter](https://www.gatsbyjs.com/gatsby-for-agencies/) - Webinar diff --git a/docs/blog/2019-12-11-reducing-interaction-cloud/add-new-org-confusion.png b/docs/blog/2019-12-11-reducing-interaction-cloud/add-new-org-confusion.png new file mode 100644 index 0000000000000..a90b81a6d1298 Binary files /dev/null and b/docs/blog/2019-12-11-reducing-interaction-cloud/add-new-org-confusion.png differ diff --git a/docs/blog/2019-12-11-reducing-interaction-cloud/cloud-login-400.png b/docs/blog/2019-12-11-reducing-interaction-cloud/cloud-login-400.png new file mode 100644 index 0000000000000..f01883c1a903c Binary files /dev/null and b/docs/blog/2019-12-11-reducing-interaction-cloud/cloud-login-400.png differ diff --git a/docs/blog/2019-12-11-reducing-interaction-cloud/create-new-site.gif b/docs/blog/2019-12-11-reducing-interaction-cloud/create-new-site.gif new file mode 100644 index 0000000000000..0138b52f6d5d2 Binary files /dev/null and b/docs/blog/2019-12-11-reducing-interaction-cloud/create-new-site.gif differ diff --git a/docs/blog/2019-12-11-reducing-interaction-cloud/final-state.png b/docs/blog/2019-12-11-reducing-interaction-cloud/final-state.png new file mode 100644 index 0000000000000..f9229a0e09224 Binary files /dev/null and b/docs/blog/2019-12-11-reducing-interaction-cloud/final-state.png differ diff --git a/docs/blog/2019-12-11-reducing-interaction-cloud/index.md b/docs/blog/2019-12-11-reducing-interaction-cloud/index.md new file mode 100644 index 0000000000000..8a38a9142255f --- /dev/null +++ b/docs/blog/2019-12-11-reducing-interaction-cloud/index.md @@ -0,0 +1,96 @@ +--- +title: Reducing unnecessary user interaction in Gatsby Cloud +date: 2019-12-09 +author: Shannon Soper +tags: ["ux", "cloud"] +--- + +In my last blogpost, I introduced how we’re [making it easier to start with Gatsby Cloud for +free](https://www.gatsbyjs.org/blog/2019-11-25-getting-started-with-gatsby-cloud/) with starters. This blogpost introduces the next set of changes that we shipped to help users get started faster. How did we do it? Inferring from history to reduce unnecessary user interaction. Quite a mouthful and needs some explanation. + +## The problem + +So what problem did we learn about? + +When watching folks onboard onto Gatsby Cloud, there was a clear point of confusion. Please see the screenshot below and read the thought bubble which depicts _approximately_ what users said during usability tests. + +![This screenshot depicts step two of Gatsby Cloud onboarding, during which users select an organization from GitHub. I drew a speech bubble on top of the screenshot pointing out that users are confused by this screen. The speech bubble says: “Wait, I don't want to create a repository in my work's GitHub organization. Terminate mission!"](select-work-org-confusion.png) + +## What was the real problem? + +We knew users were confused, yet we didn’t know how to solve it quite yet. Here are some principles that helped us figure out the reason for the confusion and how to resolve it. + +## Interaction is negative + +I know, I know, this is a bit of a purposefully inflammatory and misleading statement. Interaction design is something I care about and do full-time along with many of you, so why would I say it’s negative? Well, the real phrase ought to read “_unnecessary_ interaction is negative.” So anything software can do to [_reduce_ the amount of unnecessary interaction](http://worrydream.com/MagicInk/#p145) it takes to reach a goal is good. + +So how do you reduce unnecessary interaction? + +## Reduce interaction by inferring from history and the environment + +To reduce interaction, you can infer “as much as possible from history and the environment.” See this full quote below: + +If the software properly infers as much as possible from history and the environment, it should be able to produce at least a reasonable starting point for the context model. Most of the user’s interaction will then consist of correcting (or confirming) the software’s predictions. This is generally less stressful than constructing the entire context from scratch. + +_Quote from Brett Victor, [“Magic Ink”](http://worrydream.com/MagicInk/#p173)_ + +The principle is to make the best guess we can of what the user wants and then let them _correct_ our best guess if it’s wrong. And the guess will be right most of the time, if we infer from history and the environment. + +So what could we infer from “history” and the “environment” to solve the problem we had in Gatsby Cloud, where everyone was confused and frustrated at needing to choose a GitHub organization? + +## Inferring from history + +The first step is simply to look at history; I’ll take you on a tour of what happened before users hit their point of confusion. + +### User selects starter + +In this first screenshot, the user selects a starter. +![Screenshot of the starter page](final-state.png) + +### User logs into GitHub and into Gatsby Cloud + +Next, the user logs into GitHub and give Gatsby Cloud permission to connect with their personal GitHub account. +![Screenshot of the Gatsby Cloud login page with a thought bubble the author drew on top of the screenshot. The thought bubble contains the text “Alright, I can sign in with Git Hub. I have an account!”](cloud-login-400.png) + +### Unecessary interaction: user adds new GitHub organization + +Then, this screen asks them to “add new organization.” This is where the software failed to learn from recent history. The user just gave the system access to their personal GitHub account, so that the last value they gave the system and we ought to stick with that value. + +![Screenshot of the landing page for first-time visitors who have logged into Gatsby Cloud with a thought bubble the author drew on top of the screenshot. The thought bubble contains the text “What organization? GitHub organization? If so, why would I need to connect to GitHub again?” and "Gatsby Cloud, you have left me with no choice...I must click this button" referring to the "Add New Organization" button](add-new-org-confusion.png) + +By the time the user adds an organization (and they don’t know why they have to add it), and sees this next screen below, of course they are confused about why they added an organization. They didn’t need to! + +![screenshot of step two of Gatsby Cloud onboarding, during which users select an organization from GitHub. I drew a speech bubble on top of the screenshot pointing out that users are confused by this screen. The speech bubble says: “Wait, I don't want to create a repository in my work's GitHub organization. Terminate mission!”](select-work-org-confusion.png) + +## Reducing interaction + +To reduce interaction by inferring from history, we assume the user wants to save their first site in their GitHub personal account, the last value they provided us with when they logged in. They can _correct_ this assumption if it’s wrong. + +### First-time visitor + +The assumption that user wants to save their first site in their personal GitHub account is reflected in the following GIF that shows the user does _not have to interact with the software to tell us where to save their site_, though they _can correct the default (their personal GitHub account) if it’s wrong_. + +![A GIF depicting a screen in which the user names their site and clicks “Next." There is text on the screen that reads: “we’ll create the repo under your personal GitHub account. Want to host it on a GitHub organization instead? Add it here!”](create-new-site.gif) + +### Returning user + +If there is a returning user that has already connected their personal account plus at least one more organization, their personal account will be the first item in a list and will always be pre-selected. This makes sure that, again, they _do not have to interact with the software_ except to correct it, if it’s wrong. + +![This GIF depicts the screen in which the user names their site and their personal account is at the top of a list of GitHub organizations and is pre-selected as the destination for the site.](return-visitor.gif) + +## What's next? + +Stay tuned for more blogposts about why we: + +- Added a free pricing tier, which lets you use Gatsby Cloud for free for blogs, portfolios, etc. +- Made it easy to connect existing sites to Cloud +- Shipped Gatsby Preview +- Offer customized assessments of your builds, including Lighthouse scores + +As a design team, we'll also keep blogging about what we’re working on. This includes: + +- Transferring the principle of inferring from history so users choosing "I already have an existing Gatsby site" get the benefits of that principle as well +- Adding more starters, including MDX, to do some of the work for you +- Adding more integrations to do some work for you +- Easy-to-read error messages that help you debug +- More customized assessments of your builds, including performance budgets, structured logging, etc. diff --git a/docs/blog/2019-12-11-reducing-interaction-cloud/return-visitor.gif b/docs/blog/2019-12-11-reducing-interaction-cloud/return-visitor.gif new file mode 100644 index 0000000000000..37d7e1f9ab9b1 Binary files /dev/null and b/docs/blog/2019-12-11-reducing-interaction-cloud/return-visitor.gif differ diff --git a/docs/blog/2019-12-11-reducing-interaction-cloud/select-work-org-confusion.png b/docs/blog/2019-12-11-reducing-interaction-cloud/select-work-org-confusion.png new file mode 100644 index 0000000000000..e606809067a59 Binary files /dev/null and b/docs/blog/2019-12-11-reducing-interaction-cloud/select-work-org-confusion.png differ diff --git a/docs/blog/2019-12-12-how-we-accidentally-launched-a-popular-gatsby-plugin/index.md b/docs/blog/2019-12-12-how-we-accidentally-launched-a-popular-gatsby-plugin/index.md new file mode 100644 index 0000000000000..affa0336da04e --- /dev/null +++ b/docs/blog/2019-12-12-how-we-accidentally-launched-a-popular-gatsby-plugin/index.md @@ -0,0 +1,104 @@ +--- +title: How we accidentally launched a popular Gatsby plugin +date: 2019-12-12 +author: Jari Zwarts +excerpt: "The story of how gatsby-plugin-s3 came to be." +tags: + - AWS + - S3 + - CloudFront + - plugin + - case-studies + - festival +--- + +It all started when we ([Oberon](https://www.oberon.nl/)) noticed a certain pattern among a subset of our clients — festivals. +Their sites tend to have lots of issues with server load and costs. + +They are, after all websites that remain largely unused for most of the year — until they’re not. And at those few yearly moments (such as at the start of a ticket sale), server loads can get really, really high. + +This makes most festival websites not _particularly good_ candidates for hosting on servers that are shared by multiple sites, because they can bring down all other sites during this brief period. +Additionally, clients are paying a fixed hosting fee for a server that mostly remains unused throughout the year. + +In the past we’ve ‘resolved’ these issues by adding an additional caching layer like [Squid](http://www.squid-cache.org/), [CloudFront](https://aws.amazon.com/cloudfront/), etc. +Adding these kinds of extra layers does make you think about why these sites are built as dynamic applications anyway. + +For example, festival programme items rarely change after their initial publication, and it’s not like most of the content on these type of sites is particularly ‘realtime’ anyway. + +What if we could just keep the entire site static, only updating it if changes were made in one of the data sources? +We could then put it on a pay-per-request static file hosting service (like [AWS S3](https://aws.amazon.com/s3/)), where we can basically scale to infinity if need be, while keeping the costs low during the down periods. + +When our company was approached by a [new client](https://www.oerol.nl/en/) (that had sadly earned a reputation for its website failing during peak hours), it felt like the stars were aligned, and we decided to go* full [JAMStack](https://jamstack.wtf/)*. + +## Enter Gatsby + +Gatsby is a static site generator, based on React. +You can connect Gatsby up to a variety of sources, and query all of it through GraphQL. +Source data can come from anywhere: a REST API, CSV file, database, you name it. It doesn’t need to originate from a GQL source. + +In addition to generating everything as static assets, Gatsby also does some additional magic (mainly prefetching and codesplitting) to make your site even better. + +They explain this all [much better on their site](/). + +We have been using React for about 4 years now, and we’ve largely pivoted to using GraphQL for most of our API’s, so Gatsby was an instant fit, and barely required our frontend devs to learn anything new. + +## Deployment + +Whilst the transition to Gatsby itself was a breeze, this part is where things got a little tricky. + +Because we were already hosting our image assets on S3, it seemed only logical to put the rest of the site on there as well. +At the time however, [AWS Amplify](https://aws.amazon.com/amplify/faqs/) was the only way to go if you wanted to use Gatsby in combination with AWS. + +AWS Amplify is a suite of services and tools including continuous integration, code hosting, and [much, MUCH more.](https://aws.amazon.com/amplify/faqs/) + +I noticed there were some more downsides to Amplify: + +- [Gatsby’s redirect functionality](/docs/actions/#createRedirect) did not work, at all. + Our client absolutely needed redirects that they could control from the CMS, and in turn, we wanted to control them with the same data source that was already present in Gatsby, not having to write an additional script that would add a lot of overhead. + +- [Gatsby’s recommended caching headers](/docs/caching/) were not applied — not very good for your lighthouse scores, and one of the primary reasons we chose Gatsby in the first place. + +- Gatsby allows you to have [routes that only exist on the client side](/docs/building-apps-with-gatsby/#client-only-routes--user-authentication). + +- Essentially, you declare a starting point — say for example: /users/, and anything past that starting point will get picked up by the client side. Once the client navigates to /users/1, it will dynamically fetch that user from some sort of API. This is great and allows for very hybrid, partially static, partially dynamic applications. However, when people directly navigate to /users/1 , they will get a 404 because it simply does not exist on the serverside, which is kind of an issue. + +- We already had a CI service ourselves, and weren’t really interested in learning all these Amplify-specific things that we already had working ourselves just fine. + +- Being able to add additional metadata (such as different headers for certain files) was absent. + +So, I decided to experiment a bit and a week later, launched a plugin that fixed all of the afore mentioned problems: + +- Gatsby redirects now work just like they do on other hosting providers, and can be configured to be permanently or temporarily. + +- It applies the recommended caching headers by default which can also be fully customised. + +- If a client route is requested from the server side, it redirects them back to the starting point of the client route. (aka /users/1 now redirects to /users/ instead of 404'ing). Preferably we’d rewrite the url completely, but this is not possible with S3 and [gatsby-plugin-netlify](https://www.npmjs.com/package/gatsby-plugin-netlify) does exactly the same. + +- Unlike Amplify, it can be ran from your own infrastructure (or an EC2 instance — in which case it won’t need any configuration because it uses the AWS SDK which can automatically resolve the needed credentials!) + +- You can now set additional metadata on objects, meaning you can (for example) specify [a custom content type for your objects](https://github.com/jariz/gatsby-plugin-s3/blob/master/recipes/custom-content-type.md). + +You can get it here: +[gatsbyjs.org/packages/gatsby-plugin-s3](/packages/gatsby-plugin-s3/?=plugin-s3) + +## The result + +We launched a beautiful, fast website that was cheap to host and didn’t even flinch whilst serving a million requests during our peak day. Outside of the festival period, costs were minimal. We completely proved that this stack is great for this type of project. + +[Check it out here.](https://www.oerol.nl/en/) + +Building the plugin allowed us to scale it as far as we needed it without a hitch, with the need for redirects and custom headers showing up fairly quickly as the project went on. + +![The final end result, viewable at oerol.nl](oerol.png) + +The plugin is now the de facto way of [using Gatsby in combination with S3](/docs/deploying-to-s3-cloudfront/), and the OSS community has mostly picked it up since it’s humble beginnings, adding a lot of stability and cool new ideas: + +- Supporting prefixed deploys. (adding the possibility to have [atomic deployments](https://buddy.works/blog/introducing-atomic-deployments#what-are-atomic-deployments)) + +- Being able to swap out AWS for a different S3-compliant endpoint such as [Yandex](https://cloud.yandex.com/docs/storage/s3/) or [DigitalOcean](https://developers.digitalocean.com/documentation/spaces/). + +- Supporting both S3 redirect objects and routing rules. (due to a [50 redirects limit in the latter](https://github.com/jariz/gatsby-plugin-s3#aws-s3-routing-rules-limit)) + +- Being able to upload really large files. (which to my surprise, [was a pretty hard issue to tackle](https://github.com/jariz/gatsby-plugin-s3/pull/58)) + +It’s [still a few features away from 1.0](https://github.com/jariz/gatsby-plugin-s3/issues?q=is%3Aopen+is%3Aissue+milestone%3A1.0), but it’s really cool to have seen what started out as a byproduct of a solution to a real world problem, turn into something that is greatly used and appreciated by the Gatsby community. diff --git a/docs/blog/2019-12-12-how-we-accidentally-launched-a-popular-gatsby-plugin/oerol.png b/docs/blog/2019-12-12-how-we-accidentally-launched-a-popular-gatsby-plugin/oerol.png new file mode 100644 index 0000000000000..74c4d0c83ccfe Binary files /dev/null and b/docs/blog/2019-12-12-how-we-accidentally-launched-a-popular-gatsby-plugin/oerol.png differ diff --git a/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/index.md b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/index.md new file mode 100644 index 0000000000000..d4aff685875d7 --- /dev/null +++ b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/index.md @@ -0,0 +1,277 @@ +--- +title: Integrate TinaCMS With Your Gatsby Website +date: "2019-12-20T00:00:00.000Z" +author: Scott Byrne +tags: ["gatsby-cloud", "cloud", "cms", "markdown"] +--- + +[TinaCMS](https://tinacms.org/) is a toolkit of JavaScript components. You can use these components to build content editing functionality into your site. + +Right now, Tina uses a Git backend to track content changes. When detected, changes are immediately written back to source files. Saving pushes those changes to your repo. While Git backed for now, the Tina Team has built inherent flexibility into the CMS. Adding support for alternate backends, such as posting to a database, is on the [Tina roadmap](https://github.com/tinacms/tinacms/blob/master/ROADMAP.md). + +In this article, we will walk through how to add TinaCMS to an existing Gatsby website. We will cover installing and configuring the Tina [sidebar](https://tinacms.org/docs/concepts/sidebar). Learn how to create a content editing [form](https://tinacms.org/docs/concepts/forms) for markdown. Touch on customizing the form with Tina [field](https://tinacms.org/docs/concepts/fields) components. Set-up [inline (aka on-page) editing](https://tinacms.org/docs/gatsby/inline-editing). And then we'll configure a [`content-creator`](https://tinacms.org/docs/gatsby/creating-new-files) plugin that will allow us to add new files to the site. Let's use the classic [Gatsby’s Starter Blog 💜](https://github.com/gatsbyjs/gatsby-starter-blog) as our example. + +> Follow along by referencing [a fork of the Gatsby starter blog](https://github.com/tinacms/gatsby-tinacms-blog-post-reference) that makes the same changes outlined in this post. + +Want to see a more advanced example of TinaCMS integrated with a Gatsby website? Checkout [Tina Grande](https://github.com/tinacms/tina-starter-grande), a gatsby starter with first-class TinaCMS integration. + +## Prerequisites + +- A Gatsby project that sources local `markdown` content. Use Gatsby's [Starter Blog](https://github.com/gatsbyjs/gatsby-starter-blog) if you don't have an existing website. +- [Gatsby Development Environment](/tutorial/part-zero/) + +## Setup + +First we need to get a local development environment set up for the site. Please reference the Gatsby Starter Blog [README](https://github.com/gatsbyjs/gatsby-starter-blog/#readme) for extra notes on this. + +```bash +gatsby new tina-tutorial https://github.com/gatsbyjs/gatsby-starter-blog +cd tina-tutorial +``` + +## Install and Configure Tina + +As usual when setting up a new tool, we need to install a few packages. We will install `gatsby-plugin-tinacms`, which sets up the core Tina functionality. Along with that, we'll need the peer-dependency, `styled-components`, to keep the sidebar pretty. Since this site uses markdown, we'll install `gatsby-tinacms-remark`. And `gatsby-tinacms-git` will setup our Git API. + +```bash +yarn add gatsby-plugin-tinacms gatsby-tinacms-remark gatsby-tinacms-git styled-components +``` + +After installing those packages, add `gatsby-plugin-tinacms` to the list of plugins in `gatsby-config.js`. We'll also pass options to tell Tina what plugins to use and when to hide the sidebar: + +```javascript +module.exports = { + // ... + plugins: [ + { + resolve: "gatsby-plugin-tinacms", + options: { + sidebar: { + hidden: process.env.NODE_ENV === "production", + position: "displace", + }, + plugins: ["gatsby-tinacms-git", "gatsby-tinacms-remark"], + }, + }, + // ... + ], +} +``` + +Now we're all set to start setting up content editing with Tina. If you want to test it out, run `gatsby develop` and take a look. You should see an edit icon in the lower left-hand corner, open it to find an empty Tina sidebar. This [sidebar](https://tinacms.org/docs/concepts/sidebar) is the main interface for using Tina to edit and manage content. + +![Empty Tina Sidebar](./step-one_empty-sidebar.jpg) + +## Add a Form + +To make content editable, we need to register a [form](https://tinacms.org/docs/concepts/forms) with Tina. Forms live in the sidebar, displaying fields where you can edit content. + +You can add a form to the sidebar from any component. When that component is rendered, the form displays in the sidebar. To add a form for the individual blog post, we’ll need to make three changes to `templates/blog-post.js`: + +1. Import `remarkForm` + + ```javascript + import { remarkForm } from "gatsby-tinacms-remark" + ``` + +2. Wrap the default export with `remarkForm`. This is a [higher-order component](https://reactjs.org/docs/higher-order-components.html) that modifies the data to be editable by Tina as it’s passed to the component. In production, the unaltered component renders as normal. + + ```javascript + export default remarkForm(BlogPostTemplate) + ``` + +3. Add `...TinaRemark` to the GraphQL query inside the `markdownRemark` node. This is a GraphQL fragment that adds additional fields used by `gatsby-tinacms-remark`. + + ```javascript + export const pageQuery = graphql` + query BlogPostBySlug($slug: String!) { + site { + siteMetadata { + title + } + } + markdownRemark(fields: { slug: { eq: $slug } }) { + id + excerpt(pruneLength: 160) + html + frontmatter { + title + date(formatString: "MMMM DD, YYYY") + description + } + + ...TinaRemark + } + } + ` + ``` + +Now spin up the development server (`gatsby develop`) and see what the default form looks like. + +![Default Form](./step-two_default-form.jpg) + +We should have access to all the fields passed into the component via GraphQL. Without specifying how the form should display, default labels and values are rendered. + +Try editing the content and see what happens; you should see your changes updating live on the site 🥳. Look at the source file for this particular post, you’ll notice the edits you made are also reflected there. Tina is writing to disk as you are editing content in the sidebar. Gatsby picks this up and rebuilds the site to reflect the changes in "real time." + +## Customize The Editing Form + +We can customize the form by defining a form options object. This provides control over the form fields and their functionality. Check out all the [fields](https://tinacms.org/docs/concepts/fields) provided by Tina, or read more on creating your own [custom fields here](https://tinacms.org/docs/fields/custom-fields). + +1. Define the form options. Here's a simple form that exposes the `Title` and `Description`: + + ```javascript + const BlogPostForm = { + fields: [ + { + label: "Title", + name: "frontmatter.title", + description: "Enter the title of the post here", + component: "text", + }, + { + label: "Description", + name: "frontmatter.description", + description: "Enter the post description", + component: "textarea", + }, + ], + } + ``` + +2. Pass the form options to `remarkForm`: + + ```javascript + export default remarkForm(BlogPostTemplate, BlogPostForm) + ``` + +Now instead of the default form, open up the sidebar to see the custom `BlogPostForm`. + +![Custom Form](./step-three_custom-form.jpg) + +## Add In-Page Editing + +Editing in the sidebar works fine for many types of content. Yet, long-form content is easier to edit right on the page. We can build this ‘inline-editing’ functionality into our site with Tina. + +1. Import `liveRemarkForm` instead of `remarkForm`, and add three new imports: + + ```javascript + import { liveRemarkForm } from "gatsby-tinacms-remark" + import { Wysiwyg } from "@tinacms/fields" + import { TinaField } from "tinacms" + import { Button as TinaButton } from "@tinacms/styles" + ``` + +2. Replace `remarkForm` with `liveRemarkForm` in the export: + + ```javascript + export default liveRemarkForm(BlogPostTemplate, BlogPostForm) + ``` + +3. Wrap `TinaField` around the element rendering content you want to edit inline. Pass in the `Wysiwyg` component to `TinaField`: + + ```jsx + +
+ + ``` + +4. Add a button anywhere on your page to toggle ‘edit’ mode. This button also serves as a flag to signal inline content editing. You'll only want this to display in production, so here you can see one way of rendering it conditionally. + + ```jsx + const { isEditing, setIsEditing } = this.props + + { + process.env.NODE_ENV != "production" && ( + setIsEditing(p => !p)}> + {isEditing ? "Preview" : "Edit"} + + ) + } + ``` + +The `liveRemarkForm` HOC is similar to `remarkForm`, they both return components where Tina can edit the data that they render. With `RemarkForm`, this data is edited in the sidebar. With `liveRemarkForm`, the data is edited on the page. The difference is, `liveRemarkForm` returns a component wrapped in a `TinaForm`. In 'edit-mode', the form displays on the page itself. + +Within the template component, we can wrap child elements in a `TinaField` component. `TinaField` allows us to render a field on the page, such as a wysiwyg editor. The `Component` prop tells Tina which field component to render in edit-mode. In non-edit-mode (_and in production_), `TinaField` will pass the child elements that it wraps. + +To trigger edit-mode, `liveRemarkForm` provides a state variable and hook: `isEditing` and `setIsEditing`. These are passed as props to the template component. In the example above, `TinaButton` toggles this state. You could create your own button to handle this. Or, you can import the same `Button` (as `TinaButton`) used in the sidebar. + +![Inline Editing](./step-four_inline-editing.jpg) + +## Add Create Post Button + +So now we have a nice little editor set up for the blog. One thing we'll definitely want, is the ability to create new posts. We can do this with a `content-creator` plugin. When creating new markdown files, we'll use `RemarkCreatorPlugin` for this. + +We will register the `content-creator` plugin in a component on the site. When that component is actively rendered, we’ll have the ability to add new content. If editors should always be able to create new posts, we'll want to register the plugin on a component that is always rendered. Some common components used for this are `Layout`, `Index`, or `Root`. + +> If you add the plugin in `src/components/layout.js`, it will be rendered on every page. + +1. Import `withPlugin` and `RemarkCreatorPlugin`. + + ```javascript + import { withPlugin } from "tinacms" + import { RemarkCreatorPlugin } from "gatsby-tinacms-remark" + ``` + +2. Instantiate `RemarkCreatorPlugin`. + + - Provide a label for the button + - Provide a filename that will calculate the path to the new file. _You can reference data submitted by the form._ + - Define the fields that will render in the 'creator' modal form. + + ```javascript + const CreateBlogPlugin = new RemarkCreatorPlugin({ + label: "New Blog Post", + filename: form => { + return form.filename + }, + fields: [ + { + name: "filename", + component: "text", + label: "Filename", + placeholder: "content/blog/hello-world/index.md", + description: + "The full path to the new markdown file, relative to the repository root.", + }, + ], + }) + ``` + +3. Export the component and plugin using `withPlugin()`. + + ```javascript + export default withPlugin(Layout, CreateBlogPlugin) + ``` + +The 'create-content' button shows up in the top right-hand corner of the sidebar menu. It looks like a plus ➕ icon. Click it and add a new blog post to the site! + +We now have a way to add new posts from the Tina sidebar. The location of the new files will be based on the return value from the `filename` property. There's lots of ways to configure this return value, please reference the [documentation](https://tinacms.org/docs/gatsby/creating-new-files#4-formatting-the-filename--path) for more info. + +![Create Content](./step-five_create-content.jpg) + +## Access Tina In The Cloud + +Since Tina makes edits using the Gatsby development server, we need to create an environment for the development server to run in the cloud. This way non-technical editors can visit that cloud-hosted environment to manage content. We'll set it up with [Gatsby Cloud](https://www.gatsbyjs.com/cloud/), which is a hosted service for building and maintaining Gatsby websites. + +When it's time to allow your editors to edit a site with Tina on a hosted server, you will need to be extra careful around safeguarding against run-time errors. Does your site blow up if an array is empty? or if an image isn't defined? You'll want to account for these edge cases which your editors may run into while editing. + +To get Tina working in Gatsby Cloud, you'll need to configure the following environment variables in your `Site Settings`: + +``` +GIT_AUTHOR_EMAIL +GIT_AUTHOR_NAME +SSH_KEY +``` + +The `SSH_KEY` is a private key that allows write access to your git repo. You'll need to add the public key to your repo under `Deploy Keys` in `Settings` and enable `write access`. The `SSH_KEY` needs to be Base64 encoded before adding to Gatsby Cloud; you can encode this locally by running `cat ./.ssh/id_rsa | base64`. + +Since these values will be set at the environment level, all edits made using Tina will use these values when pushing changes to git. + +Getting a development server running in the cloud solves the issue of accessing Tina from anywhere, but there are a number of other challenges that require attention. The team behind TinaCMS is currently nearing the initial beta release of [**Tina Teams**](https://tinacms.org/teams), a custom live editing environment for you and your team. Tina Teams handles user authentication with individual user commits to provide the best possible editing experience for your team. Stay tuned! + +## Summary + +These are just some simple steps to get up and running with Tina, the possibilities don't end here. Make sure to check out [Tina Starter Grande](https://github.com/tinacms/tina-starter-grande) to see a more advacned implementation of Tina on a Gatsby website. + +Hopefully you've found this introduction to TinaCMS useful. Feel free to tweet at [Tina 🦙](https://twitter.com/tina_cms) with feedback or questions. If you want to learn more, checkout the [documentation](https://tinacms.org/docs/getting-started/introduction). TinaCMS is open source; feel free to dig into the [source code](https://github.com/tinacms/tinacms). If you're interested in getting involved with the project, join our [community slack](https://join.slack.com/t/tinacms/shared_invite/enQtNzgxNDY1OTA3ODI3LTNkNWEwYjQyYTA2ZDZjZGQ2YmI5Y2ZlOWVmMjlkYmYxMzVmNjM0YTk2MWM2MTIzMmMxMDg3NWIxN2EzOWQ0NDM). If you get stuck, don't hesitate to ask questions on the [Tina Forum](https://community.tinacms.org/). diff --git a/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-five_create-content.jpg b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-five_create-content.jpg new file mode 100644 index 0000000000000..acbc7c27b39e5 Binary files /dev/null and b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-five_create-content.jpg differ diff --git a/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-four_inline-editing.jpg b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-four_inline-editing.jpg new file mode 100644 index 0000000000000..13c70dcdd246d Binary files /dev/null and b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-four_inline-editing.jpg differ diff --git a/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-one_empty-sidebar.jpg b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-one_empty-sidebar.jpg new file mode 100644 index 0000000000000..a833c6b9272ec Binary files /dev/null and b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-one_empty-sidebar.jpg differ diff --git a/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-three_custom-form.jpg b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-three_custom-form.jpg new file mode 100644 index 0000000000000..dea345da983cf Binary files /dev/null and b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-three_custom-form.jpg differ diff --git a/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-two_default-form.jpg b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-two_default-form.jpg new file mode 100644 index 0000000000000..52318203588ff Binary files /dev/null and b/docs/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/step-two_default-form.jpg differ diff --git a/docs/blog/2020-01-15-website-uptime/index.md b/docs/blog/2020-01-15-website-uptime/index.md new file mode 100644 index 0000000000000..bc87faf08d59c --- /dev/null +++ b/docs/blog/2020-01-15-website-uptime/index.md @@ -0,0 +1,80 @@ +--- +title: "Why Teams Using Gatsby Sleep Better At Night" +date: 2020-01-15 +author: Sam Bhagwat +excerpt: "Learn how a Gatsby-powered architecture increases the reliability and scalabity of your website." +tags: ["cdn", "developer-experience", "performance"] +--- + +What's the least fun part of software development? Probably: pager duty. + +2am wakeups. Alerts while at a bar with friends. False alarms. Worse, false _non_-alarms. + +Preventing pages (and downtime!) is a top goal of any high-quality eng org. But it's hard. There's usually no silver bullet. Luckily, for websites, there is. + +## Getting infinite scalability + +True alerts have two potential causes: bugs, and scaling. + +Bugs, or regressions, tend to be introduced in response to code pushes. Scaling or infrastructure issues, on the other hand, occur when a service you depend on goes down or when your app is experiencing levels or patterns of traffic that cause partial or total failures. Perhaps high traffic overwhelms your database and causes drastically higher load times or timeouts. + +### Bugs are much easier to deal with than scaling issues. + +When a bug goes into production and is flagged, it's usually the result of a code push, often during working hours. It can usually be solved by git bisect to identify the offending code commit, some careful analysis to find the specific incorrect lines of code, and either reverting to a "known good" state, or adding a 2-line fix. While this is never fun to do under the gun, it's usually fairly straightforward. + +When your app is experiencing scaling issues, on the other hand, it usually instigates a whodunnit across the entirety of the infrastructure. Databases, caches, load balancers, proxies, routing and edge configurations, cloud infrastructure like AWS or Azure your team utilizes, third party scripts, plugins, and services -- everything comes under suspicion and is therefore guilty until proven innocent. + +Meanwhile your entire engineering organization grinds to a halt as everyone who could potentially find the key bottleneck starts looking for it, and everyone else starts rubbernecking because the unfolding drama is _way more interesting_ than whatever else they were working on. + +If you're building a website, Gatsby puts an end to traffic-spike-induced downtime. + +Gatsby sites are simply files that can be pushed to a CDN like Cloudflare or Netlify or AWS Cloudfront. And CDNs are much less likely to go down. + +## A site that's always ready for your guests + +Brian Webster, co-founder of the LA-based Delicious Simplicity, compares how Gatsby builds the site ahead-of-time to being a good party host. + +"We think of websites as a big event or party and visitors as our guests," says Webster. "So not pre-building and assembling web pages at request time would be the equivalent of setting up your party when the guests arrive. Why would we do that on their time?" + +"As site owners, it's becoming more and more our responsibility to ask, 'Hey, how much can we get done before our guests get here?' Especially when we know what they might look at. In many cases, we may prebuild the entire website." + +In a world where website visitors are a source of revenue or donations, Webster points out, time is money, and traffic spikes from publicity, email newsletter blasts, should be taken advantage of rather than worried about. + +Webster again: +"We never want our best day to be our worst day - the site going down, or becoming slow," he says. "But with [Gatsby], everything's prebuilt. Scale is cheap, easy. If we're expecting 10 people at our party and 10 thousand show up, we're well equipped. + +## No more clearing caches and hoping for the best + +Brad Redding, co-founder from digital agency and analytics provider Elevar, has been building e-commerce sites for over a decade. + +"We've had clients who aren't technical, who aren't skilled in HTML or CSS," Redding says. + +"If they actually update content, banners, or images, clicking the save or "clear cache" button could potentially take the site down. Because if you clear cache, a problem that hadn't surfaced yet, that comes to fruition and all of a sudden, checkout is broken or you could have a very funky UX error." + +That creates an atmosphere of fear for clients, he says. "Our ultimate goal is to remove that stress and that fear where you can't make updates to your site without having to live in fear of bringing down the site, breaking something, or impacting the user experience." + +Elevar's VP Engineering Thomas Slade agrees. "I came from an agency that builds a lot of Magento sites," Slade says. "I'm used to being in an environment where you're thinking about how to cache, you're thinking about servers, you're getting called late at night because the site is slow." + +## Stress-free launch days + +When lead developer Kennedy Rose took responsibility for Escalade Sports' web stack, the first challenges he confronted were stability issues. + +"When I started, all of our sites were on Drupal," said Rose. "The problem was that it wasn't stable. The sites all shared a core, and when the core went down, everything went down." + +Successful marketing efforts created traffic spikes — but the technology stack couldn't keep up with demand. + +"Whenever we had a trade show, our sites would just go down," Rose said, "We had to put a load balancer in front of multiple servers in order to keep it up. It just wasn't working—and when that happens after a trade show, you're just not getting your ROI." + +As Webster put it, their best day had became their worst day. + +The e-commerce razor brand Harry's sister brand ShopFlamingo picked Gatsby for a new product launch for exactly this reason. + +Tim Brown, senior software engineer at Harry's explained. "We've had thousands of concurrent users on the site at once with no scaling concerns and zero performance impact." + +It's even allowed them to onboard teammates to pagerduty rotation, and made that task much less of a chore. + +"We were able to allow newer teammates to be part of the on-call for the launch because Gatsby made it so easy to maintain," Brown says. + +So when Webster, Brown, Slade, Redding, and Rose moved their commercial projects over to Gatsby, they didn't just get business results. They got sites that never went down -- and slept better at night. + +_Brian Webster discussed more about his agency's journey on the webinar_ [_"How to Equip Your Marketing Team for Success with Gatsby and Contentful"_](https://www.gatsbyjs.com/starlight-webinar/)_. Kennedy Rose shared his story on our blog at "_[_Escalade Sports: From $5000 to $5/month in Hosting With Gatsby"_](/blog/2018-06-14-escalade-sports-from-5000-to-5-in-hosting/). _Tim Brown shared Harry's story on the webinar_ [_"Behind the Scenes: What makes Gatsby Great"_](https://www.gatsbyjs.com/behind-the-scenes/). _Brad Redding and Thomas Slade shared Elevar and Strivectin's story on the webinar_ [_"Optimizing E-commerce with Gatsby."_](https://www.gatsbyjs.com/optimizing-ecommerce-webinar/) diff --git a/docs/blog/2020-01-23-why-typescript-chose-gatsby/index.md b/docs/blog/2020-01-23-why-typescript-chose-gatsby/index.md new file mode 100644 index 0000000000000..6f379f1014aad --- /dev/null +++ b/docs/blog/2020-01-23-why-typescript-chose-gatsby/index.md @@ -0,0 +1,189 @@ +--- +title: "Why the TypeScript team is using Gatsby for its new website" +date: 2020-01-23 +author: Orta Therox +excerpt: "Discover why the TypeScript team uses Gatsby, and what constraints they use to make it work for their team" +tags: ["typescript", "developer-experience", "story"] +--- + +## Why are we using Gatsby for TypeScript's new Website? + +The TypeScript v1 site is a [Jekyll](https://jekyllrb.com/) website, and Jekyll packs a lot of power into a small tool. Jekyll is really great way to build static websites, but it's built to work for small-medium sized websites of around 1-20 pages. + +You can feel the scope by how they treat templating ([liquid](https://shopify.github.io/liquid/), which is a sandbox'd logic-less templating engine), how they treat the data modelling for your site (there are only really two data types: [Posts](https://jekyllrb.com/docs/posts/) & [Pages](https://jekyllrb.com/docs/pages/)) and how the tool is set up to work better with a specific folder structure. + +At [Artsy](https://artsy.github.io), where I worked at before TypeScript, we had started to hit the limits of [working within Jekyll](https://artsy.github.io/blog/2019/01/30/why-we-run-our-blog/) at around 200 blog posts and a lot of custom pages. It was taking a long time to see any changes live, and the way in which we built new features into the site tended to multiply the build times. We took some time to explore different tools to use as a writing environment for our blog. In the process I looked deeply into Gatsby, and concluded that it was the right abstraction for building static sites. + +A few months later, I joined the TypeScript team and one of my goals was to provide better foundations for our documentation and reference tools. Right now, the TypeScript v1 website is about 60 pages, but if it was going to expand to handle internationalization (a multiplier on pages) and support all the wild ideas I have to make TypeScript easier to learn, we would need an abstraction aimed at handling larger sites but it had to stay statically deployed. + +It would also help to have a tool where we can use TypeScript. Our v1 website is currently a Ruby project wrapped by some JavaScript script files and Gulp. Consolidating that on JavaScript everywhere would be a good win. + +### What Makes Gatsby Unique + +When I was evaluating static site generators, what makes Gatsby stand out is this one idea which adds an extra step to the build process. In a normal static site generator, you would more or less directly map files to their output: + +```ts +const files = fs.getDirSync() +const htmlFiles = files.map(makePage) +htmlFiles.forEach(html => { + fs.writeFileSync(filename, html) +}) +``` + +Gatsby on the other hand does something a bit more like this: + +```ts +const setupData = () => { + const files = fs.getDirSync() + const data = files.map(makePage) + graphQLServer.add(data) +} + +const createSite = () => { + const pages = graphQLServer.query("{ pages { title, text } }") + const htmls = pages.map(renderComponent) + htmls.forEach(html => { + fs.writeFileSync(filename, html) + }) +} + +setupData() +createSite() +``` + +Gatsby adds a GraphQL API which sits in-between the setup of the data and the generation of files in your static site. This abstraction provides a very strong separation of "setting up the site" vs "representation on the file system" which provides more places to introspect what is going on internally. + +What does this look like in practice? The server-side generation starts at [`gatsby-node.js`](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/gatsby-node.js) but an interesting example is how a TSConfig Reference page is set up: + +- In the Gatsby config file, [we request a plugin](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/gatsby-config.js#L52-L58) to look for markdown files in a particular folder and to mark them as `tsconfig-reference`. +- Then in `onCreatePages` in `gatsby-node.js` we make a [GraphQL query to get all these files](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/lib/bootup/ingestion/createTSConfigReference.ts#L12-L26) via the name `"tsconfig-reference"`. + These files are then used to create Pages inside Gatsby (e.g. `en.md` => `/en/tsconfig`, `pt.md` => `/pt/tsconfig`) and we link the React component used to render them. +- Once all of the pages are set up, Gatsby runs through each page. +- For the TSConfig it would load [this template](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/src/templates/tsconfigReference.tsx), run [this query](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/src/templates/tsconfigReference.tsx#L94-L120),and pass the results as the initial argument to [this function](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/src/templates/tsconfigReference.tsx#L9) - it does this per language. + +It's a few more steps then `mv ../tsconfig/en.html en/tsconfig.html` - yep, but once you grok the larger idea, then each step is a well composed, isolated and easily tested part of a larger system. That's what makes Gatsby a great abstraction. + +### Types For Tools + +The TypeScript support in Gatsby is good, and improving as they start to port their own codebase to TypeScript. When I first started, I shipped [a few `d.ts`](https://github.com/gatsbyjs/gatsby/pull/13619) file improvements and welcome ANY pings from their team with questions when it changes. In the last 2-3 months, I've been running in a fully typed codebase which has been a breeze. + +If you're familiar with React, and clicked through into the [TSConfig Template](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/src/templates/tsconfigReference.tsx#L9) - you might have been a bit surprised by the somewhat unorthodox usage of React. + +I'm using React as a templating language, and not as a reactive UI framework. The site never uses a `setState`-like API in React. Effectively meaning that React runs once when the site is generated, and then never used again. + +My goal is that the TypeScript v2 website can be understood with the least amount of abstractions possible. It should not be too surprising, but vast majority of the TypeScript compiler team have a compiler background, and don't really do web development. To ensure that they can contribute, and understand the codebase I'm aiming to use Gatsby and React to get as close to vanilla HTML + CSS + TypeScript (heh) as possible. + +One way to do that, is to separate the generation of HTML + CSS from any additional JavaScript which happens at runtime. This means almost every component in the site conforms to this general pattern: + +```tsx +// JS imports +import React, { useEffect } from "react" +import { Layout } from "../components/layout" + +// Style +import "./tsconfig.scss" + +// The main React component +const TSConfigReferenceTemplateComponent = (props: PropTypes) => { + useEffect(() => { + // code which happens when the page has finished loading + }) + + // creation of static HTML via React + JSX + const post = props.data.markdownRemark + return ( + +
+
+

TSConfig Reference

+
+ + + +
+
+
+
+ + ) +} + +export default TSConfigReferenceTemplateComponent + +// The optional GraphQL query to get info for that page +export const pageQuery = graphql` + query TSConfigReferenceTemplate($path: String, $tsconfigMDPath: String!) { + sitePage(path: { eq: $path }) { + id + } + markdownRemark(fileAbsolutePath: { eq: $tsconfigMDPath }) { + html + } + } +` +``` + +I like this, because the rest of the team don't need to _learn_ React - just JSX which acts as a proxy for HTML. + +In the meanwhile, anyone working on the code stills get the advantages in tooling, because all of this is supported by the TypeScript compiler: + +- I can still make custom React components like `Layout` above to encapsulate complexity,and TypeScript still has the props verified +- JSX support with TypeScript is dreamy, and I love it +- The 'runtime' code inside `useEffect` will be transpiled and verified to be correct by TypeScript +- The 'runtime' code can re-use the same libraries as the server-side rendering, but have strong guarantees about only being optionally available + +By not using any of the React `setState`-ish APIs, I can guarantee there is no "runtime" React rendering happening on a user's browser either. This means the HTML in the built file is exactly what someone will see whether they have JavaScript enabled or not. One advantage of this, has been that I can reliably run [`BackstopJS`](https://garris.github.io/BackstopJS/) to take screenshots of these static files to keep track of visual regressions as the site grows and others start to contribute. + +Would I recommend this constraint to people making Gatsby websites? Probably not - it's going against the grain (React is a really good tool) of how you're expected to use Gatsby. But the trade-off is worth it for me, and it lowers the barrier if a compiler engineer wants to contribute. + +### Speed + +I'm blown away by how fast Gatsby is for a user. + +The founder of Gatsby, Kyle Mathews [gave a great talk in 2017 on the ways in which Gatsby is fast](https://youtu.be/Gtd-Ht-D0sg?t=961) and [here more recently](https://www.youtube.com/watch?v=HQEotVfTXwk), in rough: + +- Pre-fetching of related links +- Clever splitting of code +- Shrinking of assets +- Offline support +- Native lazy loading + +His long term vision is to think of Gatsby as a compiler which takes a set of input source files, and will keep trying to make a static output which is faster and faster for users. Another great resource for understanding the mechanics about why Gatsby is fast is this talk by [Nicolas Goutay at GOTO 2019](https://www.youtube.com/watch?v=p14g-Sep7HY). + +### Ecosystem Wins + +Gatsby has a massive community, and a lot of the time I'm able to just re-use someone elses work. The TypeScript team only has a few [unique](https://github.com/microsoft/TypeScript-Website/blob/v2/packages/gatsby-remark-shiki/README.md) [needs](https://github.com/microsoft/TypeScript-Website/tree/v2/packages/typescript-vfs) in [our code samples](http://www.typescriptlang.org/v2/dev/twoslash/) but other than that, it's a pretty vanilla website. + +It's been great to just add a single line into the [`gatsby-config.js`](https://github.com/microsoft/TypeScript-Website/blob/v2/packages/typescriptlang-org/gatsby-config.js), run `yarn add gatsby-plugin-something` and suddenly a whole new set of features are set up. Plugins tend to be small and easy to audit, I've used a few. + +### TypeScript Support + +While not "out-of-the-box", with a little elbow grease (as of early 2020) to get comprehensive TypeScript support: + +- Add [`ts-node`](https://www.npmjs.com/package/ts-node) to your `devDependencies`, and create a [`tsconfig.json`](https://github.com/microsoft/TypeScript-Website/blob/0afd526969d98c321787ab1962f72f9361ab54bd/packages/typescriptlang-org/tsconfig.json) in the root of your site +- Add set up the plugin [`gatsby-plugin-typescript`](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-typescript) +- At the top of both `gatsby-config.js` and `gatsby-node.js` add: + ```ts + require("ts-node").register({ files: true }) + ``` + From these files, you can import `.ts` or .`tsx` files. +- To generate types for your GraphQL queries, use the plugin [gatsby-plugin-codegen](https://www.npmjs.com/package/gatsby-plugin-codegen) (I [.gitignored](https://github.com/microsoft/TypeScript-website/blob/0df8f249d812acb37541c9f0aa39f4c35dafe8b6/packages/typescriptlang-org/.gitignore#L71-L74) some of its output) + +If you're not gonna go all-in on TypeScript, (which is totally reasonable!) you can get a lot of tooling wins in VS Code by using JSDoc to annotate functions in your `gatsby-node.js`: + +```js +/** @type { import("gatsby").GatsbyNode["createPages"] } */ +const createPages = (args, _opts) => { + args. // You'll get auto-complete on args now +} + +module.export.createPages = createPages +``` + +Follow [this issue](https://github.com/gatsbyjs/gatsby/issues/18983) if you want to stay on top of the best way to use TypeScript with Gatsby. + +With that plug sorted, I just want to say thanks to the Gatsby team and everyone improving the gatsby ecosystem for providing a solid way to build really fast websites! You make all our lives a little bit better. diff --git a/docs/blog/author.yaml b/docs/blog/author.yaml index 4da58d5a428b2..b84aa3c90af8e 100644 --- a/docs/blog/author.yaml +++ b/docs/blog/author.yaml @@ -53,7 +53,6 @@ - id: Fernando Poumian bio: Full-Stack Web Developer - https://www.halfelectronic.com avatar: avatars/fernando-poumian.jpeg - twitter: "@fernandopoumian" - id: Josh Weaver bio: Developer at By the Book, Inc. Enjoys technology, writing and playing music. Can't turn down a decent board game. avatar: avatars/josh-weaver.jpg @@ -126,7 +125,7 @@ avatar: avatars/dan-kass.jpg twitter: "@JustFixNYC" - id: Gatsby Central - bio: The community for gatsby developers + bio: The community for Gatsby developers avatar: avatars/gatsby-central.jpg twitter: "@GatsbyCentral" - id: Ray Gesualdo @@ -245,7 +244,7 @@ - id: Katie Fujihara bio: Lover of making beautiful UI. Portland tech community organizer. avatar: avatars/katie-fujihara.jpg - twitter: "@katieofcode" + twitter: "@KatieFujihara" - id: Sidhartha Chatterjee bio: Core team @ GatsbyJS. Full-Stack Developer. Scuba diver. avatar: avatars/sidhartha-chatterjee.jpg @@ -317,7 +316,7 @@ avatar: avatars/benjamin-lannon.jpg twitter: "@lannonbr" - id: Thomas Wang - bio: Founder @ DormDev. A social developer on the JAMStack. + bio: A social developer on the JAMStack. avatar: avatars/thomas-wang.jpeg twitter: "@thomaswangio" - id: Hashim Warren @@ -357,3 +356,27 @@ bio: Creates tools that make designers & developers better at what they do. Polypane.rocks and Superposition.design | @kilianvalkhof | https://kilianvalkhof.com/ avatar: avatars/kilian-valkhof.jpg twitter: "@kilianvalkhof" +- id: David Bailey + bio: I build things for the web! ✧ Also interested in music, photography and language learning + avatar: avatars/david-bailey.jpg + twitter: "@davidbailey00" +- id: Madalyn Parker + bio: Working to make the web a better place. Mental health advocate, passionate about a11y, requires strong coffee. + avatar: avatars/madalyn-parker.jpg + twitter: "@madalynrose" +- id: Mark Casias + bio: Sr. Software Engineer for Mediacurrent. Bass player. + avatar: avatars/mark-casias.png + twitter: "@teampoop" +- id: Jari Zwarts + bio: Frontend @ Oberon. Maker of things. https://jari.io + avatar: avatars/jari-zwarts.png + twitter: "@JariZwarts" +- id: Scott Byrne + bio: Product Designer at Forestry.io & TinaCMS Team Member + avatar: avatars/scott-byrne.jpg + twitter: "@scottpbyrne" +- id: Orta Therox + bio: Engineer on TypeScript at Microsoft + avatar: avatars/orta-therox.jpg + twitter: "@orta" diff --git a/docs/blog/avatars/david-bailey.jpg b/docs/blog/avatars/david-bailey.jpg new file mode 100755 index 0000000000000..a205a790347ec Binary files /dev/null and b/docs/blog/avatars/david-bailey.jpg differ diff --git a/docs/blog/avatars/jari-zwarts.png b/docs/blog/avatars/jari-zwarts.png new file mode 100644 index 0000000000000..c537277785f0a Binary files /dev/null and b/docs/blog/avatars/jari-zwarts.png differ diff --git a/docs/blog/avatars/madalyn-parker.jpg b/docs/blog/avatars/madalyn-parker.jpg new file mode 100644 index 0000000000000..cdd4e708ba5f6 Binary files /dev/null and b/docs/blog/avatars/madalyn-parker.jpg differ diff --git a/docs/blog/avatars/mark-casias.png b/docs/blog/avatars/mark-casias.png new file mode 100644 index 0000000000000..a833b2b570757 Binary files /dev/null and b/docs/blog/avatars/mark-casias.png differ diff --git a/docs/blog/avatars/orta-therox.jpg b/docs/blog/avatars/orta-therox.jpg new file mode 100644 index 0000000000000..f82ed03896b6f Binary files /dev/null and b/docs/blog/avatars/orta-therox.jpg differ diff --git a/docs/blog/avatars/scott-byrne.jpg b/docs/blog/avatars/scott-byrne.jpg new file mode 100644 index 0000000000000..159895a6937fa Binary files /dev/null and b/docs/blog/avatars/scott-byrne.jpg differ diff --git a/docs/blog/gatsby-first-beta-release.md b/docs/blog/gatsby-first-beta-release.md index 518fbeb138856..b56107720d961 100644 --- a/docs/blog/gatsby-first-beta-release.md +++ b/docs/blog/gatsby-first-beta-release.md @@ -46,7 +46,7 @@ individuals and companies. - [Jason Quense](https://github.com/jquense) - [Fabien Bernard](https://github.com/fabien0102) - [Scotty Eckenthal](https://github.com/scottyeck) -- [Nicholas Young](https://github.com/nicholaswyoung) +- [Nicholas Young](https://github.com/secretfader) - [Florian Kissling](https://github.com/fk) - [Jacob Bolda](https://github.com/jbolda) - [Noah Lange](https://github.com/noahlange) diff --git a/docs/blog/gatsby-v1.md b/docs/blog/gatsby-v1.md index e5f2b2e91ab40..f1276f849d73a 100644 --- a/docs/blog/gatsby-v1.md +++ b/docs/blog/gatsby-v1.md @@ -22,11 +22,11 @@ code splitting, service workers, offline support, and more. Gatsby means no more compromising between developers, designers, and authors. - +https://twitter.com/krist/status/882953204119556097 - +https://twitter.com/charlotte_dann/status/882596284116480000 - +https://twitter.com/SachaGreif/status/841058065856192512 ## Gatsby is growing like crazy @@ -48,7 +48,7 @@ In the last year, Gatsby community and usage have exploded. Milestones reached: - JavaScript consultancy [Formidable built their website on Gatsby](https://formidable.com/) -![screenshots of above sites](images/site-screenshots.png) +![screenshots of above sites](./images/site-screenshots.png) And you're on of course a Gatsby website 😛 diff --git a/docs/blog/gatsbygram-case-study/index.md b/docs/blog/gatsbygram-case-study/index.md index 8ea7de5eb9935..845dc9dc6f4c4 100644 --- a/docs/blog/gatsbygram-case-study/index.md +++ b/docs/blog/gatsbygram-case-study/index.md @@ -122,7 +122,7 @@ your site. Typically, you define the output file structure (and thus URL structure) of your site by way of the input structure. For example the input structure: -``` +```text my-site/ index.md blogs/ @@ -131,7 +131,7 @@ my-site/ ...would be transformed to: -``` +```text my-site/ index.html blogs/ @@ -148,7 +148,7 @@ Here is how we define pages from our JSON data for Gatsbygram at build time in the site's [`gatsby-node.js` file](https://github.com/gatsbyjs/gatsby/blob/master/examples/gatsbygram/gatsby-node.js): -```javascript +```javascript:title=gatsby-node.js const path = require(`path`) const slug = require(`slug`) const slash = require(`slash`) @@ -229,7 +229,7 @@ query. For the we pass the id to the post. Below we use that id to query our `GraphQL` schema and return a fully formed page: -```jsx +```jsx:title=src/templates/post-page.js import React from "react" import PostDetail from "../components/post-detail" @@ -293,7 +293,7 @@ In addition to creating pages for our Instagram photos, we want to make an index page for browsing all photos. To build this index page, Gatsby lets us create pages using React.js components. -``` +```text pages/ index.js about.js @@ -383,7 +383,7 @@ powered by plugins. Plugins are added to a site in its `gatsby-config.js`. Here's what Gatsbygram's config file looks like: -```javascript +```javascript:title=gatsby-config.js module.exports = { siteMetadata: { title: `Gatsbygram`, diff --git a/docs/categories.yml b/docs/categories.yml index 8eae604b90c00..48ed1cf40289e 100644 --- a/docs/categories.yml +++ b/docs/categories.yml @@ -15,6 +15,7 @@ starter: - CMS:WordPress - CMS:sanity.io - CMS:Strapi + - CMS:Kontent - CMS:Forestry.io - CMS:Other - Disqus @@ -86,6 +87,7 @@ site: - Gallery - Government - Healthcare + - Human Resources - JavaScript - Law - Landing Page diff --git a/docs/contributing/blog-and-website-contributions.md b/docs/contributing/blog-and-website-contributions.md index acf00c3bdc507..74c43aabf0dd0 100644 --- a/docs/contributing/blog-and-website-contributions.md +++ b/docs/contributing/blog-and-website-contributions.md @@ -12,49 +12,41 @@ Here are some things to keep in mind when deciding where to contribute to Gatsby ## Contributing to the blog -Note: Before adding a blog post, ensure you have approval from a member of the Gatsby team. You can do this by [opening an issue](https://github.com/gatsbyjs/gatsby/issues/new/choose) or contacting [@gatsbyjs on Twitter](https://twitter.com/gatsbyjs). - -To add a new blog post to the gatsbyjs.org blog: - -- Clone [the Gatsby repo](https://github.com/gatsbyjs/gatsby/) and navigate to `/www`. -- Run `yarn` to install all of the website's dependencies. ([Why Yarn?](/contributing/setting-up-your-local-dev-environment#using-yarn)) -- Run `npm run develop` to preview the blog at `http://localhost:8000/blog`. -- The content for the blog lives in the `/docs/blog` folder. Make additions or modifications here. -- Add your avatar image to `/docs/blog/avatars`. -- Add your name to `/docs/blog/author.yaml`. -- Add a new folder following the pattern `/docs/blog/yyyy-mm-dd-title`. Within this newly created folder, add an `index.md` file. -- Add `title`, `date`, `author`, `excerpt`, and `tags` to the frontmatter of your `index.md`. You can [view existing tags](/blog/tags/), or [add a new one](https://github.com/gatsbyjs/gatsby/blob/master/www/src/data/tags-docs.js) if you feel your tag merits being its own tag, though we encourage you to use existing tags. -- If you are cross posting your post, you can add `canonicalLink` for SEO benefits. You can check the other blog posts in `/docs/blog` for examples. -- If your blog post contains images, add them to your blog post folder and reference them in your post's `index.md`. -- Ensure any links to gatsbyjs.org are relative links - `/contributing/how-to-contribute/` instead of `https://gatsbyjs.org/contributing/how-to-contribute`. -- Follow the [Style Guide](/contributing/gatsby-style-guide/#word-choice) to make sure you're using the appropriate wording. -- Double check your grammar and capitalize correctly. -- Commit and push to your fork. -- Create a pull request from your branch. - - We recommend using a prefix of `docs`, e.g. `docs/your-change` or `docs-your-change`. ([PR example](https://github.com/gatsbyjs/gatsby/commit/9c21394add7906974dcfd22ad5dc1351a99d7ceb#diff-bf544fce773d8a5381f64c37d48d9f12)) - -### Blog post format - -The following format can help you in creating your new blog content. At the top is "frontmatter": a fancy name for metadata in Markdown. The frontmatter for your post should include a title, date, singular author name (for now, we would welcome issues/PRs for this), and one or more tags. Your content will follow after the second set of dashes (`---`). - -```md ---- -title: "Your Great Blog Post" -date: YYYY-MM-DD -author: Jamie Doe -excerpt: "Here is a helpful excerpt or brief description of this blog post." -tags: - - awesome - - post ---- +If you'd like to contribute a post to the Gatsby blog, please review the process and guidelines outlined below and submit your +idea for the post to our [Gatsby blog proposal form](https://airtable.com/shr3449954866i3iF) + +### Blog proposal submission process + +1. Complete and submit the [Gatsby blog proposal form](https://airtable.com/shr3449954866i3iF). +2. A Gatsby team member will review your proposal and let you know if the proposal has been accepted within the next week or so. + - **If the post is accepted:** A Gatsby team member will work with you on a timeline for submitting and reviewing a draft of your blog post and set a tentative publishing date. + - **If the post is not accepted:** We’ll let you know if there are any alternative offers we can make (e.g. offer to retweet if you publish the piece elsewhere, suggest submitting it as an addition to a Gatsby doc, etc.). We’ll also do our best to explain why your proposal was not accepted and encourage you to revise your proposal based on that feedback and resubmit. Please don’t be discouraged from submitting another post in the future! + +If you have any questions about the process or your submission, please email [marketing@gatsbyjs.com](mailto:marketing@gatsbyjs.com). + +### Content guidelines for submitting a blog post proposal + +As a Gatsby community member, you have unique insight into the ins and outs of learning Gatsby, building with Gatsby, and contributing to Gatsby’s open source community. Contributing to the Gatsby blog is a great way to share your experiences and insights. Here are some guidelines for what kind of content is and isn’t a good fit for the Gatsby blog. + +Things we’re looking for in Gatsby blog content: + +- Information to help others overcome challenges you’ve faced while working with Gatsby +- Stories about how Gatsby helped you overcome different challenges on work and personal projects +- Gatsby case studies +- Showcasing a tool, fix, or other content you or someone else have contributed to Gatsby’s open source community +- Showcasing a tool, fix, or other content someone else has contributed to Gatsby’s open source community +- Clear and thoughtful explanations of technical details or complex concepts related to React, GraphQL, web and application development, open-source contribution, Gatsby core, and other Gatsby-adjacent subject matter +- Guidance and resources for learning React, GraphQL, HTML/CSS, web development, best practices, accessibility, SEO, Gatsby, different tool and CMS integrations, and other Gatsby-adjacent subject matter. +- Other topics that you think would be valuable to people learning about or working with Gatsby -Your next great blog post awaits! +Things we’d like to avoid on the Gatsby blog: -Include images by creating a folder for your post and including -Markdown and image files for easy linking. +- **Docs content.** Some content is better found in the Gatsby docs guides and tutorials, as it can be found in a section for related content and not buried under pages of other paginated blog posts. +- **Promotional content.** Please don’t submit content to the Gatsby blog solely for the purpose of promoting a product, yourself, or link-building. + - **Here’s what you can do instead:** If you have a product or project you want to share on the Gatsby blog, focus on practical information, and make sure there’s a clear relationship with Gatsby or Gatsby-adjacent topics. You could write a step by step guide to using your product with Gatsby. You could write a case study highlighting the direct impact Gatsby had on your awesome project and offer helpful tips for others to recreate your success. +- **Content that doesn’t seem to have a clear benefit for Gatsby users and/or the Gatsby community.** For example, if you’re writing about a use-case or integration that’s extremely niche or unique to specific conditions that are really uncommon outside of your organization, the Gatsby blog might not be the best place for your content. Likewise, if your blog post doesn’t seem to have any direct relationship with Gatsby (or an interesting indirect relationship with Gatsby), then it may be more appropriate for a personal blog or another community blog. -![awesome example](./image.jpg) -``` +**Please note** that these are guidelines, not rules. If you think your blog post belongs on the Gatsby blog, we absolutely encourage you to submit it. While we reserve the right to decide what is and isn’t appropriate for the Gatsby blog, we also value and encourage your creativity and your contributions. ## Making changes to the website diff --git a/docs/contributing/code-contributions.md b/docs/contributing/code-contributions.md index b968ce0ae7805..952cb2de2d844 100644 --- a/docs/contributing/code-contributions.md +++ b/docs/contributing/code-contributions.md @@ -59,8 +59,8 @@ With all of the possible Gatsby integrations, it might help to spin up a Docker To install WordPress to use with Gatsby, this `docker-compose.yml` file will come in handy: -``` -version: '2' +```yaml:title=docker-compose.yml +version: "2" services: db: @@ -91,22 +91,22 @@ services: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_PASSWORD: wordpress volumes: - - ./wp-content:/var/www/html/wp-content - - ./wp-app:/var/www/html + - ./wp-content:/var/www/html/wp-content + - ./wp-app:/var/www/html phpmyadmin: - image: phpmyadmin/phpmyadmin - container_name: sessions_phpmyadmin - environment: - - PMA_ARBITRARY=1 - - PMA_HOST=sessions_db - - PMA_USER=wordpress - - PMA_PASSWORD=wordpress - restart: always - ports: - - 8080:80 - volumes: - - /sessions + image: phpmyadmin/phpmyadmin + container_name: sessions_phpmyadmin + environment: + - PMA_ARBITRARY=1 + - PMA_HOST=sessions_db + - PMA_USER=wordpress + - PMA_PASSWORD=wordpress + restart: always + ports: + - 8080:80 + volumes: + - /sessions ``` Use the above file contents when following the Docker WordPress install instructions: https://docs.docker.com/compose/wordpress/ @@ -121,4 +121,4 @@ Check [Debugging the build process](/docs/debugging-the-build-process/) page to ## Feedback -At any point during the contributing process, the Gatsby Core team would love to help! We hold a weekly [Core Maintainer's meeting](/contributing/community#core-maintainers-meeting) where you can share your creation(s) and receive advice and feedback directly from the team! +At any point during the contributing process the Gatsby team would love to help! For help with a specific problem you can [open an issue on GitHub](/contributing/how-to-file-an-issue/). Or drop in to [our Discord server](https://gatsby.dev/discord) for general community discussion and support. diff --git a/docs/contributing/code-of-conduct.md b/docs/contributing/code-of-conduct.md index 6c5875bc0daa5..ce74e3c5eb8fd 100644 --- a/docs/contributing/code-of-conduct.md +++ b/docs/contributing/code-of-conduct.md @@ -4,17 +4,11 @@ title: Gatsby Contributor Covenant Code of Conduct ## Our Pledge -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of -experience, nationality, personal appearance, race, religion, or sexual identity -and orientation. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards -Examples of behavior that contributes to creating a positive environment -include: +Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences @@ -24,49 +18,29 @@ include: Examples of unacceptable behavior by participants include: -- The use of sexualized language or imagery and unwelcome sexual attention or - advances +- The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment -- Publishing others' private information, such as a physical or electronic - address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. -Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned with this code of conduct, or to ban temporarily or permanently any -contributor for other behaviors that they deem inappropriate, threatening, -offensive, or harmful. +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this code of conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, divisive, threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at -[conduct@gatsbyjs.com](mailto:conduct@gatsbyjs.com). All complaints will be -reviewed and investigated and will result in a response that is deemed necessary -and appropriate to the circumstances. The project team is obligated to maintain -confidentiality with regard to the reporter of an incident. Further details of -specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [conduct@gatsbyjs.com](mailto:conduct@gatsbyjs.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +When faced with repeated bad faith comments or harassment after an earnest attempt to mediate an issue, the Gatsby team reserves the right to remove someone from the GitHub repository and/or block them on social media. This decision will always be made with consensus from more than one team member. ## Attribution diff --git a/docs/contributing/community.md b/docs/contributing/community.md index 26c58cf7f161e..f661b9475e6e3 100644 --- a/docs/contributing/community.md +++ b/docs/contributing/community.md @@ -2,7 +2,7 @@ title: Community --- -As of September 2019, the Gatsby community is comprised of over 2,400 contributors and tens of thousands of developers building both personal and commercial websites on Gatsby. +As of December 2019, the Gatsby community is comprised of over 2,800 contributors and tens of thousands of developers building both personal and commercial websites on Gatsby. Open source doesn’t always have the best reputation for being friendly and welcoming, and that makes us sad. **Everyone belongs in open source, and Gatsby is dedicated to making you feel welcome.** @@ -45,14 +45,6 @@ Sign up for the Gatsby newsletter to keep up with the latest from the Gatsby com For the latest news about Gatsby, [follow **@gatsbyjs** on Twitter](https://twitter.com/gatsbyjs). -### Community Maintainers Meeting - -The Gatsby Core team (official Gatsby employees who are working on Gatsby open-source) holds a weekly meeting where we encourage community members to share their projects, struggles, and successes directly with the Gatsby Core team. Additionally the Core team shares pertinent info and plans that are applicable to the community! - -This event is held on a recurring basis, every Wednesday at 8:30 AM Pacific Standard Time (PST). - -[Add the recurring calendar invite here](https://gatsby.dev/core-maintainers) - ## Where to get support ### Stack Overflow diff --git a/docs/contributing/docs-and-website-components.md b/docs/contributing/docs-and-website-components.md new file mode 100644 index 0000000000000..9e878dd542b79 --- /dev/null +++ b/docs/contributing/docs-and-website-components.md @@ -0,0 +1,464 @@ +--- +title: Docs and Website Components +tableOfContentsDepth: 2 +--- + +import Breadcrumb from "../../www/src/components/docs-breadcrumb" +import { itemListContributing } from "../../www/src/utils/sidebar/item-list" +import TableOfContents from "../../www/src/components/docs-table-of-contents" + +The Gatsbyjs.org site has a handful of components that have been developed to facilitate writing new content for the blog and the docs. There are also components that help organize and lay out content in various pages across the website. + +This guide documents what components are available and explains how to use them. You can also refer to the [code for this page on GitHub](https://github.com/gatsbyjs/gatsby/blob/master/docs/contributing/docs-and-website-components.md) to see to how each component can be used, because they are all embedded here! + +Information about authoring in Markdown and styling components on the site is also listed. + +## Globally available components + +A variety of components have been written to help with formatting code and content across the blog and the docs and don't need to be imported. + +--- + +### Guide List + +The `` is a component that renders an h2 heading and a list of links to child docs nested below the current doc in the site's information architecture. It is often used on overview pages like the [Headless CMS](/docs/headless-cms/) guide where many other pages are nested below it to show what a docs section contains. + +#### Usage + +The Guide List component takes one prop: + +- `slug` (required) - the value of which is already available on every page's context on Gatsbyjs.org by default + +The slug is used to find a matching value in one of the `yaml` files that sets up the hierarchical structure for how the guides in the [docs](https://github.com/gatsbyjs/gatsby/blob/master/www/src/data/sidebars/doc-links.yaml), [tutorial](https://github.com/gatsbyjs/gatsby/blob/master/www/src/data/sidebars/tutorial-links.yaml), and [contributing](https://github.com/gatsbyjs/gatsby/blob/master/www/src/data/sidebars/contributing-links.yaml) section are organized. It finds the matching entry in the hierarchy and renders the pages that are children of it in a list. + +The component can be used like this: + +```markdown:title=docs/headless-cms +--- +title: Headless CMS +--- + +Overview information about headless CMSs... + + // highlight-line +``` + +#### Sample + +When rendered in a page, the Guide List looks like this: + + + +_This example has the prop `slug="/docs/headless-cms/"` set, and can be seen on the doc for [Headless CMS](/docs/headless-cms/)_ + +--- + +### Egghead Embed + +To embed video content from [Egghead](https://egghead.io) on the site, there is an `` component that adds an iframe with the video inline with other content. + +#### Usage + +The Egghead Embed component takes two props: + +- `lessonLink` - the URL of the lesson from Egghead +- `lessonTitle` - the name of the lesson that is used to add more information to the embedded iframe. + +It can be used like this: + +```markdown:title=docs/using-gatsby-image +--- +title: Using Gatsby Image +--- + +This is how you use `gatsby-image`... + + + + + + +``` + +#### Sample + +Rendered, it looks like this: + + + +--- + +### Pull Quote + +The `` component is used to call out a quote in the blog. It applies borders and styles that make a section of the content pop out to readers. + +#### Usage + +The Pull Quote component takes two optional props, and uses the children it wraps to populate its inner content: + +- `citation` - the reference of the person or entity that made the quoted statement +- `narrow` - styles the pull quote by removing the left and right negative margins, keeping it inside the parent container. This prop is not used in the blog to help the quote stand out, but could be used in docs where it's necessary to keep content from overlapping with other sections of the layout, such as the Table of Contents. + +It is used like this: + +```markdown:title=blog/new-announcement.md +--- +title: Big News! +author: Jay Gatsby +--- + + + + To improve is to change, so to be perfect is to have changed often. + + +``` + +#### Sample + +Rendered, the component looks like this: + + + To improve is to change, so to be perfect is to have changed often. + + +### Layer Model + +The `` was made to help explain concepts of how Gatsby works at a high level. It conceptually breaks Gatsby into different layers and shows how data is pulled, aggregated, and eventually rendered as an app. It's used on docs pages to help explain how Gatsby works at different levels. + +#### Usage + +The Layer Model component takes one prop: + +- `initialLayer` - defaults to `Content`, can be one of `Content`, `Build`, `Data`, `View`, `App` that correspond to the different layers + +```markdown +--- +title: GraphQL Concepts in Gatsby +--- + +import LayerModel from "../../www/src/components/layer-model" + +To help understand how GraphQL works in Gatsby... + + +``` + +#### Sample + +When used, it looks like this: + + + +### Horizontal Navigation List + +The `` was made for the [Glossary](/docs/glossary/), and renders a list of links to alphabetical subheadings on the page in a horizontal format. + +#### Usage + +The Horizontal Nav List component takes two props: + +- `slug` - which is provided in the props of the page by default +- `items` - an array of strings for items to render and wrap with a `` to subheadings + +The docs on Gatsbyjs.org use the [gatsby-remark-autolink-headers](/packages/gatsby-remark-autolink-headers/) plugin to automatically apply hover links to heading tags across docs pages. Because it automatically creates links to subheadings on pages like the glossary, the Horizontal Nav List can supply matching links (like `"guide-list"` which would align with the automatically created link at `/docs/docs-and-website-components#guide-list`). + + +```markdown +--- +title: Glossary +--- + +import HorizontalNavList from "../../www/src/components/horizontal-nav-list.js" + +The glossary defines key vocabulary... + +--- + + +``` + +#### Sample + +Rendered, it looks like this: + + + +--- + +## Other available components + +Other less commonly used components aren't globally available, but can imported at the top of a Markdown file and used in other docs. + +--- + +### Breadcrumb + +The `` component is used in layout files to display the hierarchy of pages a user is currently browsing on. + +#### Usage + +The Breadcrumb component takes one prop: + +- `location` - an object provided in the props of page templates by default +- `itemList` - an object comprised of the docs hierarchical structure + + +```jsx +import Breadcrumb from "../../www/src/components/docs-breadcrumb" + + +``` + +_You can also refer to [an example of usage of the Breadcrumb in the Gatsbyjs.org source code](https://github.com/gatsbyjs/gatsby/blob/1d65ce051967dda5c4a89da920fc34692524e237/www/src/templates/template-docs-markdown.js#L82)_ + +#### Optional `breadcrumbTitle` entries in sidebar files + +To alter the title of a doc that is displayed in the Breadcrumb component, a `breadcrumbTitle` is supported as a key in the [sidebar YAML files](https://github.com/gatsbyjs/gatsby/tree/master/www/src/data/sidebars). It is commonly used to provide an abbreviated version of a doc's title when displayed next to its parent page title, e.g. shortening "Adding a Custom webpack Config" to "webpack Config". + +#### Sample + +Rendered, it looks like this: + + + +--- + +### Table of Contents + +The `` component is used to render a list of subheaders from a docs page and automatically provide deep links to them. + +#### Usage + +The component takes 2 props: + +- `location` - an object provided in the props of page templates by default +- `page` - an object with data passed in from the sites `gatsby-node.js` that contains information from the MDX plugin about the structure of headings + + +```jsx +import TableOfContents from "../../www/src/components/docs-table-of-contents" + + +``` + +_You can also refer to [an example of usage of the Table of Contents in the Gatsbyjs.org source code](https://github.com/gatsbyjs/gatsby/blob/1d65ce051967dda5c4a89da920fc34692524e237/www/src/templates/template-docs-markdown.js#L121)_ + +The Table of Contents component also has some optional configurations that can be set in the frontmatter of a doc's markdown. + +In docs where the Table of Contents isn't required and should be disabled, a key in the frontmatter called `disableTableOfContents` can be set to `true` like this: + +```markdown +--- +title: Glossary +disableTableOfContents: true +--- + +When you're new to Gatsby there can be a lot of words to learn... +``` + +In other docs where the Table of Contents is extremely long it can make sense to only show headers from the doc up to a certain level, rather than all subheadings. You can set the `tableOfContentsDepth` key to a number that will limit the subheadings shown in the table of contents to that "depth". If it is set to 2, `

`/`##`, and `

`/`###` headers will be listed, if set to 3, `

`/`##`, `

`/`###`, and `

`/`####` will all be shown. It is set like this: + +```markdown +--- +title: Glossary +tableOfContentsDepth: 2 +--- + +When you're new to Gatsby there can be a lot of words to learn... +``` + +#### Sample + +The Table of Contents looks like this when rendered (and is also displayed on the right hand side of the page): + + + +--- + +## Writing content in Markdown + +New docs and blog posts are added to the [docs](https://github.com/gatsbyjs/gatsby/tree/master/docs/) folder inside the Gatsby repository. They are stored as `.md` (Markdown) or `.mdx` (MDX) files and can be written using Markdown, or using inline JSX thanks to MDX. Writing in Markdown will output tags that are styled according to [Gatsby's design guidelines](/guidelines/color/). + +You can read more about writing in Markdown in the [Markdown syntax guide](/docs/mdx/markdown-syntax). + +### Code blocks + +Code can be formatted using regular Markdown syntax, but the docs site has additional enhancements that can be used thanks to various Gatsby plugins that aren't all native Markdown. + +#### Usage + +Code blocks are wrapped in 3 backticks. A language can be added immediately after the first set of back ticks to provide syntax highlighting for the language. A `title` of the file can be added after the language. Line highlighting can be included in the code block by commenting `highlight-line`, or `highlight-start` followed by a `highlight-end`. + + +```` +```javascript:title=gatsby-config.js +// In your gatsby-config.js +plugins: [ + { + resolve: `gatsby-transformer-remark`, + options: { + plugins: [ + `gatsby-remark-prismjs` + ], + }, + }, +] +``` +```` + +In order to demonstrate how to use code blocks in a doc without your triple backticks being styled and formatted automatically (just like the example above), you can wrap a set of triple backticks in quadruple backticks like this: + +````` +```` +```javascript:title=gatsby-config.js +// In your gatsby-config.js +plugins: [ + { + resolve: `gatsby-transformer-remark`, + options: { + plugins: [ + `gatsby-remark-prismjs` + ], + }, + }, +] +``` +```` +````` + +#### Sample + +The above code block is rendered like this: + + +```javascript:title=gatsby-config.js +// In your gatsby-config.js +plugins: [ + { + resolve: `gatsby-transformer-remark`, + options: { + plugins: [ + `gatsby-remark-prismjs` + ], + }, + }, +] +``` + +Line numbers and line highlighting can be added to code blocks as well, and is explained in detail in the [`gatsby-remark-prismjs` README](/packages/gatsby-remark-prismjs/?=remark#optional-add-line-highlighting-styles). + +## Styling components on Gatsbyjs.org with Theme-UI + +Styles on the site are applied using [Theme-UI](https://theme-ui.com/), which allows for theming across the site based on design tokens (also called variables). + +### Design tokens + +Design tokens are used to consolidate the number of colors and style attributes that are applied to components throughout the site. By limiting the styles that can be applied, the site stays consistent with the guidelines for color, typography, spacing, etc. + +Tables listing design tokens that are used on the site can be found in the [design guidelines](/guidelines/design-tokens/). + +### The `sx` prop + +The [`sx` prop](https://theme-ui.com/sx-prop) from Theme-UI allows you to access theme values to style elements and components, it should be used wherever possible. The prop is "enabled" by adding `theme-ui`'s [JSX pragma](https://theme-ui.com/jsx-pragma) at the top of a `js` file. + +It is still okay to directly import tokens, e.g. `mediaQueries` or `colors` directly from [`www/src/gatsby-plugin-theme-ui`](https://github.com/gatsbyjs/gatsby/blob/master/www/src/gatsby-plugin-theme-ui/index.js) if it helps your specific use case — for example when global CSS is required, when passing theme values to other libraries or plugins, when authoring complex responsive styles, etc. diff --git a/docs/contributing/docs-contributions.md b/docs/contributing/docs-contributions.md index 2d91c39ad7a65..d3e48c8260417 100644 --- a/docs/contributing/docs-contributions.md +++ b/docs/contributing/docs-contributions.md @@ -84,30 +84,36 @@ If you wrote a new document that was [previously a stub](/contributing/how-to-wr After going through the [development setup instructions](/contributing/setting-up-your-local-dev-environment/), there are a few additional things that are helpful to know when setting up the [Gatsby.js docs site](/docs/), which mostly lives in the [www](https://github.com/gatsbyjs/gatsby/tree/master/www) and [docs](https://github.com/gatsbyjs/gatsby/tree/master/docs) directories. There are also some [examples](https://github.com/gatsbyjs/gatsby/tree/master/examples) in the repo that are referenced in docs. +- Prerequisites: install Node.js and Yarn. See [development setup instructions](/contributing/setting-up-your-local-dev-environment/). - [Fork and clone the Gatsby repo](/contributing/setting-up-your-local-dev-environment/#gatsby-repo-install-instructions). - For docs-only changes, consider using `git checkout -b docs/some-change` or `git checkout -b docs-some-change`, as this will short circuit the CI process and only run linting tasks. - Change directories into the docs site folder: `cd www` - Install dependencies with Yarn: `yarn install` - Add the following env variable to an `.env.development` file inside the `www` directory to [enable image placeholders](https://github.com/gatsbyjs/gatsby/tree/master/www#running-slow-build-screenshots-placeholder): `GATSBY_SCREENSHOT_PLACEHOLDER=true`. This will speed up building the docs site significantly! +- Make sure you have the Gatsby CLI installed with `gatsby -v`, if not run `yarn global add gatsby-cli` - Start a build of `www` with `gatsby develop`. - Edit Markdown files in the [docs](https://github.com/gatsbyjs/gatsby/tree/master/docs) and [contributing](https://github.com/gatsbyjs/gatsby/tree/master/docs/contributing) folders, as well as the [YAML sidebar files](https://github.com/gatsbyjs/gatsby/tree/master/www/src/data/sidebars). - View the changes in your browser at `http://localhost:8000`. - Commit your changes and [submit a pull request](/contributing/how-to-open-a-pull-request/)! +## Changing headers + +It can be necessary to change a heading within the docs. It's important to note that headers automatically generate links with a corresponding URL that can be deep-linked from elsewhere on the site. When changing a header, be sure to point all corresponding links to the new URL. Here are some workflow tips: + +- Determine the URL you're looking for. `Changing headers` is linked with a URL ending in `changing-headers`, `Docs renaming instructions` becomes `docs-renaming-instructions`, etc. +- Update all instances of the old URL to your new one. [Find and replace](https://code.visualstudio.com/docs/editor/codebasics#_search-across-files) in VS Code can help. Check that the context of the original link reference still makes sense with the new one. + ## Docs renaming instructions Sometimes it makes sense to move or rename a file as part of docs restructuring or for content clarification. While we recommend keeping URLs consistent as often as possible, here are some tips to minimize errors and keep the docs in a good state: - Run proposed structure changes by the Gatsby docs team in [a GitHub issue](/contributing/how-to-file-an-issue/) to ensure your change is accepted. - Update all instances of the old URL to your new one. [Find and replace](https://code.visualstudio.com/docs/editor/codebasics#_search-across-files) in VS Code can help. Check that the context of the original link reference still makes sense with the new one. -- For SEO purposes, add a redirect to the `createPages` function in [`www/gatsby-node.js`](https://github.com/gatsbyjs/gatsby/tree/master/www/gatsby-node.js). Here's an example: - -```js:title=www/gatsby-node.js -createRedirect({ - fromPath: `/docs/source-plugin-tutorial/`, - toPath: `/docs/pixabay-source-plugin-tutorial/`, - isPermanent: true, -}) +- For SEO purposes, add a redirect to [`www/redirects.yaml`](https://github.com/gatsbyjs/gatsby/tree/master/www/redirects.yaml). Here's an example: + +```yaml:title=www/redirects.yaml +- fromPath: /docs/source-plugin-tutorial/ + toPath: /docs/pixabay-source-plugin-tutorial/ ``` ## Claim your swag diff --git a/docs/contributing/docs-templates.md b/docs/contributing/docs-templates.md index bfa87f25a740a..40ff0bf3135b7 100644 --- a/docs/contributing/docs-templates.md +++ b/docs/contributing/docs-templates.md @@ -8,6 +8,7 @@ Here are some things to keep in mind when deciding where to contribute to Gatsby - [Blog posts](/contributing/docs-contributions#contributing-to-the-blog) are primarily made for case studies and time-sensitive storytelling. - [Reference guides](#reference-guides), in contrast, are evergreen -- or continually relevant -- and discoverable documentation articles that go beyond any one case study or situation. + - [Other guides](#other-types-of-guide-articles) add documentation for specific purposes like the API reference, Conceptual Guide, Gatsby Internals, and more. - [Recipes](#recipes) add concise, discoverable, and easy-to-follow instructions for common Gatsby tasks. They are smaller units than tutorials. - [Tutorials](#tutorials) should provide step-by-step guidance for Gatsby workflows, listing all pre-requisites and not assuming knowledge or skipping steps. @@ -21,7 +22,19 @@ Here are templates (models) to follow when contributing to Gatsby docs to ensure Reference guide articles cover discrete topics as documentation with links to other resources. A reference guide explains a Gatsby concept or technique without the step-by-step context provided by a tutorial or recipe. -Reference guide sections provide canonical information on how and why to build things with Gatsby for a variety of scenarios. +Reference guide sections provide canonical information on how and why to build things with Gatsby for a variety of scenarios. Reference material should list text headings for each section of a guide, rather than "steps 1-5" like a tutorial. + +#### Other types of guide articles + +The Gatsby docs include multiple types of guides. They mostly follow the same format, but some docs will have a slightly different purpose and/or audience. + +- [Reference Guides](/docs/guides/): explanations of Gatsby site development techniques and common workflows. These should be written for all skill-levels. +- [API Reference](/docs/api-reference/): technical docs on API methods and options, common files, and links to additional resources and explanations. +- [Releases & Migration](/docs/releases-and-migration/): release notes and guides on how to upgrade Gatsby and third-party packages. +- [Conceptual Guides](/docs/conceptual-guide/): high-level docs to explain important Gatsby concepts and philosophies. + - As an example, "Plugins, Themes, and Starters" would be an overarching concept article, with individual reference guide sections for Plugin, Theme, and Starter docs. +- [Gatsby Internals](/docs/gatsby-internals/): previously titled Behind the Scenes, these docs go in depth into how Gatsby works under the hood. +- [Using Gatsby Professionally](/docs/using-gatsby-professionally/): articles on winning over stakeholders, working in larger organizations, and building a career as a Gatsby developer. ### What should a reference guide be about? @@ -179,7 +192,7 @@ Assume the reader has basic programming knowledge such as the command line, code ## Recipes -[Docs Recipes](/docs/recipes/) should act as discoverable, concise instructions for completing common Gatsby tasks without having to navigate elsewhere. They live on the [Recipes page](/docs/recipes/) in the docs, the source of which can be found in [`docs/docs/recipes.md`](https://github.com/gatsbyjs/gatsby/blob/master/docs/docs/recipes.md) in the GitHub repo. +[Docs Recipes](/docs/recipes/) should act as discoverable, concise instructions for completing common Gatsby tasks without having to navigate elsewhere. They live in the [Recipes section](/docs/recipes/) in the docs, the source of which can be found in the [`docs/docs/recipes.md` landing page](https://github.com/gatsbyjs/gatsby/blob/master/docs/docs/recipes.md) and [`docs/docs/recipes/*` folder](https://github.com/gatsbyjs/gatsby/blob/master/docs/docs/recipes/) in the GitHub repo. A recipe should list requirements and include a few short instructions to complete a task. It should omit boilerplate and list only directly related, actionable instructions inline. Recipes are smaller units than tutorials, each limited to a single feature or task. Multiple recipes could be linked from a reference guide or tutorial, however the content should be consolidated in the Recipes section for discoverability. If a recipe is recorded as a video, it should be less than five or ten minutes long. @@ -196,6 +209,8 @@ Recipes should be short. This is accomplished by limiting steps to what is uniqu If you're finding a recipe is becoming too long to fit on the Docs Recipes page due to including many prerequisites or steps, consider writing a tutorial instead. +> Note: If you add a new recipe to the existing sections, be sure to add it to the list on the [`recipes.md` landing page](https://github.com/gatsbyjs/gatsby/blob/master/docs/docs/recipes.md)! + ### Recipe categories Grouping recipes by topic will allow users to navigate and learn by subject matter. As recipes following the new format are introduced, you might find a section needs an h2 heading added for the group. The older-style recipes should be gradually replaced with actionable recipes following the template below. @@ -399,6 +414,8 @@ them at the bottom in an "Other Resources" section. You can also mention here an Include a summary of what this plugin accomplishes. Is there a demo site that shows how this plugin operates? If so, include a link to the deployed demo site and/or its source code here. +Themes are considered plugins in the Gatsby ecosystem and should follow this README as well. Note that themes include multiple READMEs. One inside the theme directory with configuration instructions, one inside the example project directory, and one in the root of the repository which will follow this guide. + ### Dependencies (optional) Are there any plugins that must be installed in order to make this plugin work? If so, please include a list of those plugins and links to their pages here. @@ -411,6 +428,10 @@ If there are other tutorials, docs, and learning resources that are necessary or Please include installation instructions here. +Gatsby documentation uses `npm` for installation. This is the recommended approach for plugins as well. + +If the plugin is a theme that needs to use `yarn`, please point to [the documentation for switching package managers](/docs/gatsby-cli/#how-to-change-your-default-package-manager-for-your-next-project) in addition to the `yarn`-based instructions. + ## Available options (if any) ## When do I use this plugin? @@ -431,6 +452,8 @@ This section could also include before-and-after examples of data when the plugi If this is a source plugin README, source plugins ought to allow people to query for data within their Gatsby site. Please include code examples to show how to query for data using your source plugin. +If this is a theme that requires data in a specific format in order to match an existing query, include those examples here. + ## How to run tests ## How to develop locally diff --git a/docs/contributing/gatsby-docs-translation-guide.md b/docs/contributing/gatsby-docs-translation-guide.md index ef3b52df3ac1d..f69f1db798909 100644 --- a/docs/contributing/gatsby-docs-translation-guide.md +++ b/docs/contributing/gatsby-docs-translation-guide.md @@ -8,7 +8,7 @@ If you're a fluent speaker of a language other than English and you're intereste ## The general process -Each translation has its own repository in the [gatsbyjs](https://github.com/gatsbyjs/) organization on GitHub, with designated codeowners to review and approve changes. Each repo will include all pages needing translations (with some prioritized over others), and a bot to notify of changes in the main repo to keep everything up to date. +Each translation has its own repository in the [gatsbyjs](https://github.com/gatsbyjs/) organization on GitHub, with designated codeowners to review and approve changes. Each repo will include all pages needing translations (with some prioritized over others), and a bot to notify of changes in the main repo to keep everything up-to-date. This doc will outline how to request a new language repository with its own team, what decisions each team can make, and suggestions for how you can work together. @@ -20,7 +20,7 @@ The Gatsby learning team is in charge of determining priorities for which docs s ### Use English as the source -The [gatsbyjs.org](https://gatsbyjs.org) website is written first in English and should be considered the source material for all translations (as opposed to starting from another translation). When a repository is created, it will provide a copy of the docs to be translated which you can then update through [pull requests](/contributing/how-to-open-a-pull-request/) against them in the relevant language. A bot will +The [gatsbyjs.org](https://gatsbyjs.org) website is written first in English and should be considered the source material for all translations (as opposed to starting from another translation). When a repository is created, it will provide a copy of the docs to be translated which you can then update through [pull requests](/contributing/how-to-open-a-pull-request/) against them in the relevant language. Changes to the meaning of a text or code example should be done in the main [English repo](https://github.com/gatsbyjs/gatsby/), and then translated afterwards to keep the content aligned across languages. @@ -28,13 +28,33 @@ Changes to the meaning of a text or code example should be done in the main [Eng The first step for starting a new translation is to check what exists. So far, there are repositories for the following languages: +- [Arabic](https://github.com/gatsbyjs/gatsby-ar) +- [Bengali](https://github.com/gatsbyjs/gatsby-bn) +- [German](https://github.com/gatsbyjs/gatsby-de) - [Spanish](https://github.com/gatsbyjs/gatsby-es) +- [French](https://github.com/gatsbyjs/gatsby-fr) +- [Gujarati](https://github.com/gatsbyjs/gatsby-gu) +- [Hindi](https://github.com/gatsbyjs/gatsby-hi) +- [Indonesian](https://github.com/gatsbyjs/gatsby-id) +- [Italian](https://github.com/gatsbyjs/gatsby-it) +- [Japanese](https://github.com/gatsbyjs/gatsby-ja) +- [Korean](https://github.com/gatsbyjs/gatsby-ko) +- [Mongolian](https://github.com/gatsbyjs/gatsby-mn) +- [Dutch](https://github.com/gatsbyjs/gatsby-nl) +- [Polish](https://github.com/gatsbyjs/gatsby-pl) +- [Brazilian Portuguese](https://github.com/gatsbyjs/gatsby-pt-BR) - [Russian](https://github.com/gatsbyjs/gatsby-ru) - -You can find the list of all translation requests here: https://github.com/gatsbyjs/gatsby/issues?utf8=%E2%9C%93&q=is%3Aissue+%22New+Translation+Request%22+ +- [Turkish](https://github.com/gatsbyjs/gatsby-tr) +- [Vietnamese](https://github.com/gatsbyjs/gatsby-vi) +- [Simplified Chinese](https://github.com/gatsbyjs/gatsby-zh-Hans) +- [Traditional Chinese](https://github.com/gatsbyjs/gatsby-zh-Hant) > Note: Once a new translation repository is created, feel free to add it here in a PR! +If your language is not listed above, check the list of [open translation requests](https://github.com/gatsbyjs/gatsby/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+%22New+Translation+Request%22). + +If you don't see the language among the issues listed, feel free to create a new [translation request issue](https://github.com/gatsbyjs/gatsby/issues/new?template=new_translation.md) for it and follow the instructions. + ### Finding codeowners For a new translation, open an issue with information about your intended language. If you already have co-contributors to act as fellow [code owners](https://help.github.com/en/articles/about-code-owners) and provide checks and balances for PR reviews and quality assurance, that would be very helpful! Otherwise, you can check out other [translation request issues](https://github.com/gatsbyjs/gatsby/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+%22New+Translation+Request%22) people have made and offer to join, or [get in touch with us](/contributing/how-to-contribute/#not-sure-how-to-start-contributing) at Gatsby for help in building your translation team. @@ -51,38 +71,78 @@ Maintainers of a translation are expected to review translations for quality, fr Translation contributions must be opened as pull requests to provide time for review and comments. If actionable feedback is given on a PR review, the author must acknowledge the review and make changes with their discretion. Ignoring review feedback completely is not allowed (see response templates below for help with this). -### Maintainer responsibilities +## Maintainer responsibilities As repo maintainers and members of the Gatsby community, your responsibilities are as follows: -- Keep issues up to date as people volunteer to translate pages. +- Keep issues up-to-date as people volunteer to translate pages. - Review pull requests made by contributors promptly. -- Review pull requests generated by gatsbybot in order to make sure translations remain up to date with the source repo. (details to come) +- Review pull requests generated by gatsbybot in order to make sure translations remain up-to-date with the source repo. (details to come) - Act as point of contact for your language and answer questions from both contributors to your language and the core Gatsby team. - Set up a process in order to get your translation published. (details to come) As a maintainer, you are welcome to add a contributing doc written in your language to assist with the process. You can find an example in the [gatsby-es repo](https://github.com/gatsbyjs/gatsby-es/blob/master/CONTRIBUTING.MD). Translating [this page](https://github.com/gatsbyjs/gatsby/blob/master/docs/contributing/gatsby-docs-translation-guide.md) and copying it into a `contributing.md` file would be an option as well. -Additional tips: +### Keeping translations up-to-date + +Periodically, gatsbybot will create pull requests to keep translations repos up-to-date with the original English source. Make sure to review these PRs to ensure that your translation remains accurate. + +> Note: the bot doesn't work yet but will come soon. Until then, see the next section to learn how to manually sync your repo. + +#### Manually syncing translation repos + +If for whatever reason you'd like to manually sync your translation repo, you can do so by running these commands: + +```shell +git remote add source https://github.com/gatsbyjs/gatsby-i18n-source.git +git pull source master +``` + +Fix all [merge conflicts](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/resolving-a-merge-conflict-using-the-command-line) and create a pull request to finish the merge. + +### Additional tips + +#### Set up a style guide and glossary + +Your language repo comes with a template [style guide](https://github.com/gatsbyjs/gatsby-i18n-source/blob/master/style-guide.md) that you can use to put in style rules specific to your language. Refer to the [translation style guide](#translation-style-guide) section for more information. + +#### Collaborate on difficult pages + +Some pages are very long and difficult to translate for a single contributor. Feel free to split these pages up into sections and work on them together! + +In addition, sometimes a contributor cannot continue a PR for whatever reason. It may help to ask them if they need assistance and to bring someone else on to complete the work in a timely fashion. -- Make a glossary and translation style guide. Here are some [examples from the React translation project](https://github.com/reactjs/reactjs.org-translation/blob/master/maintainer-guide.md#make-a-glossary-and-style-guide). -- Collaborate on large or challenging pages. More than one person can contribute to a long tutorial or reference guide! -- Set up a review process -- Ask for help +#### Set up a review process -#### When a maintainer or contributor will be removed +As codeowners, you have the freedom and responsibility to decide what your review process will be like. You can decide how many reviewers you'd like. If your team is small, one reviewer may be enough. But if you have lots of contributors and enough codeowners, you may want to require two reviewers for additional quality. + +You have the ability to install any plugin or automation tool that will make your life easier as codeowners. Is there a text linter that works well in your language? Is there any automation that you can add? If you feel that these improvements would be beneficial to other languages as well, create an issue or PR for it in the main Gatsby repository. + +#### Ask for help + +Don't be afraid to ask for help! If you're not sure about something, you can post in the `#localization` channel on the [Gatsby Discord](https://gatsby.dev/discord) or create an issue in the Gatsby repo. + +If it feels like there is too much work and you need help, you have the ability to to add more codeowners by editing the `CODEOWNERS` file in the repo. Are there any contributors who are making exceptional contributions? If so, consider making them a codeowner. + +We also understand that life sometimes gets in the way. If you find that you are no longer able to satisfy your codeowner duties, let the Gatsby team know so we can figure out the best path forward. + +#### Spread the word! + +If you're finding it hard to find people to help translate, spread the word about your translation effort! If you use social media like Twitter, tag the [gatsby Twitter account](https://twitter.com/gatsbyjs) and we'll share it. Ask people in local Gatsby or React meetups if they would be interested in contributing. + +### When a maintainer or contributor will be removed Consistent with the [Code of Conduct](/docs/code-of-conduct/) the Gatsby team reserves the right to remove a maintainer (or contributor) from the Gatsby organization if necessary. Some reasons for being removed include spammy comments, closing PRs or issues without action or productive dialogue,or generally harmful or abusive behavior inconsistent with Gatsby's policies. -#### Template responses for closing PRs +### Template responses for closing PRs Sometimes a PR has a valid reason to not be merged as-is. Templates can help speed up the process of responding to someone while encouraging future contributions. -##### PRs with quality issues +#### PRs with quality issues If a PR includes content that is of poor quality (such as from Google Translate or missing important nuance) or doesn't meet the requirements, it would help to include a drafted reply to encourage contributors to continue with the project. Here is an example that can be translated for a given repo: -``` +```text Hey! Thanks so much for opening a pull request! We really appreciate you sending this over, but the change you’ve proposed is not going to be accepted because it doesn't meaningfully translate the Gatsby docs content. @@ -93,11 +153,11 @@ Thanks again, and we look forward to seeing more PRs from you in the future! [open-issues]: YOUR_REPO_ISSUE_URL_HERE ``` -##### PRs with changes more fitting for the main Gatsby repo +#### PRs with changes more fitting for the main Gatsby repo Because the main Gatsby repo is the source of content, more substantive changes should be closed and redirected there. Here is a template that could be translated for your repo: -``` +```text Hey! Thanks so much for opening a pull request! We really appreciate you sending this over, but the change you’ve proposed is not going to be accepted because it includes broad changes to the docs content that should be done in the [main Gatsby repo](https://github.com/gatsbyjs/gatsby) instead. @@ -108,12 +168,99 @@ Thanks again, and we look forward to seeing more PRs from you in the future! [open-issues]: YOUR_REPO_ISSUE_URL_HERE ``` -## Which decisions are flexible? Which are firm guidelines? +## Style guide for translations -Each language translation may have some specific ways it differs from the advice Gatsby provides for writing in English, such as the use of "you" as the pronoun or the Oxford comma. Each translation group should decide on conventions and stick with them for consistency, documenting those decisions in the repo's README file to set contributors up for success. Having trouble making decision? See above recommendations for settling disputes and working together. +Each language translation may have some specific ways it differs from the advice Gatsby provides for writing in English, such as the use of "you" as the pronoun or the Oxford comma. Each translation group should decide on conventions and stick with them for consistency, documenting those decisions in the repo's [style guide](https://github.com/gatsbyjs/gatsby-i18n-source/blob/master/style-guide.md) file to set contributors up for success. Use the [English style guide](/contributing/gatsby-style-guide/) as a reference to determine the equivalent rules in your language. Guidelines that remain firm no matter the language stem from the goals and values of Gatsby as a project: to provide a **friendly community for Gatsby learners of all skill and experience levels** that's also **safe and welcoming to contributors**. Translated docs and learning materials should [maintain these values](/blog/2019-04-19-gatsby-why-we-write/) with **high-quality spelling and grammar**, accurate information, similar structure and purpose. For any questions about guidelines, feel free to [get in touch](/contributing/how-to-contribute/#not-sure-how-to-start-contributing) with the Gatsby team. +### Glossary + +The style guide has a [glossary section](https://github.com/gatsbyjs/gatsby-i18n-source/blob/master/style-guide.md#glossary) that you can use to fill in common translations. Look at the English [Glossary](/docs/glossary/) for a list of terms that are useful to have translations for. + +### Universal style guide + +The following rules should apply in all translations and can serve as a basis for your language-specific style guide. + +#### Keep the meaning of the source + +Keep the meaning of the original English source even if it is confusing or has a typo. If you find an error that can be fixed, create an issue or pull request to the original [gatsby repo](https://github.com/gatsbyjs/gatsby) so that all translations can benefit from the change. + +#### Text in code blocks + +Leave text in code blocks untranslated except for comments. You may optionally translate text in strings, but be careful not to translate strings that refer to code! + +✅ DO: + +```jsx +// Ejemplo +import React from "react" +export default () => ( +
Hello Gatsby!
+) +``` + +✅ ALSO OKAY: + +```jsx +// Ejemplo +import React from "react" +export default () => ( +
¡Hola Gatsby!
+) +``` + +❌ DON'T: + +```jsx +// Ejemplo +import React from "react" +export default () => ( + // 'purple' is a CSS keyword +
¡Hola Gatsby!
+) +``` + +❌ DEFINITELY DON'T: + +```jsx +importar Reaccionar desde "reaccionar" +exportar defecto () => ( +  
¡Hola Gatsby!
+) +``` + +#### Internal links + +Translate link text but keep all slugs and hashes in links the same as they are in English. + +✅ OK: + +```markdown +- [Configure su entorno de desarrollo](/tutorial/set-up-your-development-environment) +``` + +❌ DON'T: + +```markdown +- [Configura tu entorno de desarrollo](/tutorial/configura-tu-entorno-de-desarrollo) +``` + +#### External links + +If an external link is to an article in a reference like [MDN] or [Wikipedia], and a version of that article exists in your language that is of decent quality, consider linking to that version instead. + +[mdn]: https://developer.mozilla.org/en-US/ +[wikipedia]: https://en.wikipedia.org/wiki/Main_Page + +✅ OK: + +```markdown +Los elementos de React son [inmutables](https://es.wikipedia.org/wiki/Objeto_inmutable). +``` + +For links that have no equivalent (Stack Overflow, YouTube videos, etc.), use the English link. + ## Language-specific maintainer channels Each translation group may want to have a space for maintainers and community members to ask questions and coordinate the project. **[Discord](https://gatsby.dev/discord) is the official channel** and maintainers can have their own private groups if desired. Some groups may elect to use a different platform such as Wechat or Whatsapp, but that will be at your own discretion. diff --git a/docs/contributing/gatsby-style-guide.md b/docs/contributing/gatsby-style-guide.md index 4fa9e8e9a1fe0..3a4849667fa3e 100644 --- a/docs/contributing/gatsby-style-guide.md +++ b/docs/contributing/gatsby-style-guide.md @@ -32,7 +32,7 @@ examples: - [Plugin README](/packages/gatsby-source-filesystem/) - [Starter README](https://github.com/gatsbyjs/gatsby-starter-default) -Please see the [Docs templates](/contributing/docs-templates/) for guidelines on how to format the above kinds of documents. +Please see the [Docs templates](/contributing/docs-templates/) for guidelines on how to format the above kinds of documents, as well as tips for different types of guide articles. ## Writing process @@ -149,7 +149,7 @@ abstract syntax tree (AST) is ..." ### Use SEO optimized titles -This explains how to create a doc that shows up in search engines like Google or Bing. +This explains how to account for Search Engine Optimization (SEO) and create a doc that shows up in search engines like Google or Bing. When you create the new guide or tutorial under `/docs/`, you’ll either create a file or a folder if there will be images pulled into the doc. @@ -385,7 +385,7 @@ For words that have multiple spellings, prefer the US English word over British ### Use apps that help you edit -Use the [Hemingway App](https://www.hemingwayapp.com/). There’s nothing magical +Use the [Hemingway App](https://hemingwayapp.com/). There’s nothing magical about this tool, but it will automatically detect widely agreed-upon style issues: diff --git a/docs/contributing/how-to-open-a-pull-request.md b/docs/contributing/how-to-open-a-pull-request.md index ef5a5b75e23e5..8d3ff764954d3 100644 --- a/docs/contributing/how-to-open-a-pull-request.md +++ b/docs/contributing/how-to-open-a-pull-request.md @@ -14,7 +14,7 @@ Gatsby uses the PR process to review and test changes before they’re added to When someone wants to contribute to Gatsby, they open a request to _pull_ their code into the repo. Depending on the type of change, PRs are categorized into: -- [Documentation](#documentation) +- [Documentation](#documentation-prs) - [Code](#code-changes) - [Starters or Site Showcase](#starters-or-site-showcase) - [Blog posts](#blog-posts) @@ -91,6 +91,25 @@ There are specific pages about contributing to various parts of the Gatsby ecosy For the Gatsby blog, it's necessary to run your content idea by the Gatsby team before submitting it. For more information, refer to the page on [blog and website contributions](/contributing/blog-and-website-contributions/), including how to propose an idea and setting up the blog to run locally. +## Follow up with reviews and suggestions + +After a PR is sent to the Gatsby GitHub repo, the Gatsby core team and the community may suggest modifications to the changes that your PR introduces. + +The Gatsby core and learning teams review and approve every PR that the community sends to make sure that it meets the contribution guidelines of the repo, and to find opportunities for improvement to your PR changes. + +These suggestions may also be called "request changes" by the GitHub UI. When a change request is added to your PR, this and the rest of the change requests will appear on the GitHub page for your PR. From this page you can use the suggestions UI to: + +- Review the suggested changes using the "View changes" button. +- [Commit](https://help.github.com/en/articles/incorporating-feedback-in-your-pull-request#applying-suggested-changes) the suggestions. +- [Discuss suggestions](https://help.github.com/en/articles/about-conversations-on-github) to ask questions about the suggested changes. +- [Add suggestions to a batch](https://help.github.com/en/articles/incorporating-feedback-in-your-pull-request#applying-suggested-changes) so they can be pushed in a single commit. + +For suggestions that may not be resolved using the GitHub UI, remember that you can keep adding related commits to your PR before it is merged and those commits will also be a part of such PR. + +After all your questions have been resolved and the requested changes have been committed, you can [mark the conversation as solved](https://help.github.com/en/articles/commenting-on-a-pull-request#resolving-conversations). + +This process helps both the Gatsby team and the community to contribute with improvements for your changes before they are merged into the Gatsby GitHub repo. + ## Update your fork with the latest Gatsby changes The Gatsby GitHub repo is very active, so it's likely you'll need to update your fork with the latest changes to be able to merge in your code. This requires adding Gatsby as an [upstream remote](https://help.github.com/en/articles/configuring-a-remote-for-a-fork): diff --git a/docs/contributing/index.mdx b/docs/contributing/index.mdx new file mode 100644 index 0000000000000..07b3cdef0fa9a --- /dev/null +++ b/docs/contributing/index.mdx @@ -0,0 +1,16 @@ +--- +title: Contributing to Gatsby.js +disableTableOfContents: true +--- + +Thanks for being interested in contributing! We're so glad you want to help! + +Below you'll find guides on the Gatsby.js community, code of conduct, and how to get started contributing: + +- [Community](/contributing/community/): Learn why you should contribute to Gatsby.js, the most effective ways to do so, and all about the benefits (did we mention the free swag?) +- [Code of Conduct](/contributing/code-of-conduct/): Read about what we expect from everyone participating in Gatsby.js to make it the most friendly and welcoming community +- [Gatsby Style Guide](/contributing/gatsby-style-guide/): The art of contributing to Gatsby, a.k.a. the detailed requirements that will make it more likely your contribution is accepted with minimal changes +- [How to Contribute](/contributing/how-to-contribute/): How to get the most out of your Gatsby.js contributing experience, including GitHub management tips, setup instructions for docs and code contributions, and more +- [RFC process](/contributing/rfc-process): Learn how the Gatsby.js team manages bigger changes, by way of a “Request-for-comment” process on GitHub + + diff --git a/docs/contributing/managing-pull-requests.md b/docs/contributing/managing-pull-requests.md index 1393390f56ab1..40bcf89318a92 100644 --- a/docs/contributing/managing-pull-requests.md +++ b/docs/contributing/managing-pull-requests.md @@ -20,10 +20,12 @@ Some general things to verify in a pull request are: - Links ought to be relative instead of absolute when linking to docs (`/docs/some-reference/` instead of `https://www.gatsbyjs.org/docs/some-reference/`) - Language ought to be inclusive and accessible -- Issues and RFCs (if any) that this PR addresses ought to be linked to +- Issues and Requests for Comments (RFCs) (if any) that this PR addresses ought to be linked to > 💡 When looking at a PR for the first time, it can help to read up on linked issues or [RFCs](/contributing/rfc-process/) (if there are any) to gain context on what the PR intends to add or fix. +Note for Gatsby Core or Learning team members: if a PR has merge conflicts or needs a little help to push it across the finish line, contributing directly to a fork or branch can be a great way to resolve it. See notes on [pushing to a remote fork in Git](#pushing-changes-to-a-remote-fork). + ### Type Specific Guidelines Each kind of PR also requires a different set of specific checks from us before they are merged in. @@ -140,11 +142,23 @@ These are bad PR titles because they are generic, don't communicate the change p - Be objective and limit nitpicks (a few are fine if they add value or improve code readability) - Don't suggest and expect changes out of scope which are best addressed in a separate PR +## Pushing changes to a remote fork + +Sometimes the easiest way to unblock a stalled PR is to sort out merge conflicts or apply remaining suggestions. When the GitHub UI won't cut it, you can (often) apply changes directly to someone's remote fork with Git: + +- Add their Gatsby fork as a remote:
`git remote add git@github.com:/gatsby.git` +- Fetch the branches:
`git fetch ` +- Check out their branch locally:
`git checkout -b /` +- Make your changes, add some commits +- Push branch to the remote fork (also see [Gotchas](#gotchas) below):
`git push head:` + +Alternatively, you can manage forks and branches with [hub](https://github.com/github/hub). + ## Rights and Permissions ### Who can review a PR? -If you're a member of the [gatsbyjs](http://github.com/gatsbyjs) organization on GitHub, you can review a PR. +If you're a member of the [gatsbyjs](http://github.com/gatsbyjs) organization on GitHub, you can review **most** PRs. PRs with [`topic: internal`](https://github.com/gatsbyjs/gatsby/issues?q=is%3Aopen+is%3Aissue+label%3A%22topic%3A+internal%22) are reserved for Core and Learning team members as they are typically part of an internal project or hiring process. > 💡 Not a member yet? Want to [get involved in contributing](/contributing/how-to-contribute/) to open source projects? Make your first contribution and you'll be invited automatically! diff --git a/docs/contributing/organize-a-gatsby-event.md b/docs/contributing/organize-a-gatsby-event.md index f298a02415fa0..946ed67170114 100644 --- a/docs/contributing/organize-a-gatsby-event.md +++ b/docs/contributing/organize-a-gatsby-event.md @@ -2,30 +2,34 @@ title: Organize a Gatsby Event --- -Interested in organizing a Gatsby event? We want to help build the Gatsby community in your area. If your event meets a few basic requirements listed below, you’ll be eligible to receive support from Gatsby such as Gatsby swag, \$300 for food, learning resources, and more. Get started by requesting event support below. +Interested in organizing a Gatsby event? We want to help build the Gatsby community in your area. If your event meets a few basic requirements listed below, you’ll be eligible to receive support from Gatsby such as Gatsby stickers, learning resources, up to \$300 for event costs, and more. Get started by requesting event support below. [Request Event Support](https://airtable.com/shrpwc99yogJm9sfI) ## What constitutes a Gatsby event? -A community organized Gatsby event can be a local meetup, a small conference, a _lunch and learn_ with coworkers, or a larger event. It’s up to you how many people you want to invite and how casual the environment. You can organize an event at your workplace or for the local community. +A community-organized Gatsby event can be a local meetup, a small conference, a “lunch and learn” with coworkers, or a larger event - as long as **it includes at least one Gatsby-focused presentation or discussion**. It’s up to you how many people you want to invite and how casual the environment. You can organize an event at your workplace or for the local community. ## What support does Gatsby provide? -There are several ways Gatsby may support your event: +There are several ways Gatsby can support your event: - Promote event on the [Gatsbyjs.org Events Page](/contributing/events/) -- Promote event via [Gatsby’s Twitter handle](https://twitter.com/gatsbyjs) -- \$300 off food related expenses +- Promote event via [Gatsby’s Twitter account](https://twitter.com/gatsbyjs) +- \$300 off event expenses (food, supplies, space rental, etc.) - Free Gatsby stickers from the [Gatsby Swag Store](https://store.gatsbyjs.org/) - 20% off swag in the [Gatsby Swag Store](https://store.gatsbyjs.org/) for your attendees -- Gatsby team member speaker (when available) + +### A note on shipping + +We support US and international Gatsby events, but it’s not uncommon to run into issues with international shipping that can delay orders for weeks. Shipments to non-western countries in particular can often take well over a month to arrive. We’re working on finding international shipping partners, but until that’s sorted out, **if you need stickers shipped internationally, please make sure you’re submitting your event at least 6 weeks in advance**. ## Requirements -- The event must have at least half of the content focused on Gatsby or a Gatsby-related topic (such as JAMstack) -- Both US and international events qualify for support -- If you’re requesting the \$300 food credit, then you must submit a receipt for the expense +- Requests should be made at least 1 month in advance of your event date. (If your event is outside the US and you plan to request stickers, we strongly recommend making your request at least 6 weeks in advance.) +- The event must have at least one Gatsby-focused presentation or discussion. +- Please announce Gatsby as a sponsor for the event and/or list us on the event as a sponsor. +- If you’re requesting the \$300 reimbursement, then you must submit a receipt or receipts for event-related expenses. - The event must be in harmony with the [Gatsby Code of Conduct](/contributing/code-of-conduct/) and follow the [Gatsby brand guidelines](/guidelines/logo/) ## How do you qualify for Gatsby support? @@ -34,6 +38,9 @@ To request support and submit your event to the Gatsby events page, apply at the [Request Event Support](https://airtable.com/shrpwc99yogJm9sfI) +Events are evaluated on a weekly basis. If your submission is approved, you will receive an email with instructions for receiving event support and other guidance. +If you have any questions, please send them to events@gatsbyjs.com. + ## Related Links - [Gatsby's Community Events](/contributing/events/) diff --git a/docs/contributing/pair-programming.md b/docs/contributing/pair-programming.md index a54f4d852c3d4..b414d39c806c0 100644 --- a/docs/contributing/pair-programming.md +++ b/docs/contributing/pair-programming.md @@ -2,29 +2,26 @@ title: Open Community Pair Programming Sessions --- -The best part of open source is the community, and every community is stronger when it works together. To help build the strongest community possible, Gatsby is offering free [one-hour pair programming sessions][cal] to anyone and everyone in the open source community. +The best part of open source is the community, and every community is stronger when it works together. To help build the strongest community possible, Gatsby is offering free [45 minute pair programming sessions][cal] to anyone and everyone in the open source community. ## How community pair programming sessions work -1. Sign up for any available slot on [the open pairing calendar][cal] -2. You’ll be paired with one of the Gatsby Inkteam -3. Join the video meeting during your time slot -4. Build, learn, or discuss your Gatsby or other OSS project! +1. Select or create [an issue](https://github.com/gatsbyjs/gatsby/issues) you would like to work on and work on it yourself +2. [Create a pull request](https://www.gatsbyjs.org/contributing/how-to-open-a-pull-request/) when you encounter any problem +3. Sign up for any available slot on [the open pairing calendar][cal] +4. You’ll be paired with a Gatsby team member +5. Join the video meeting during your time slot (we use [Zoom](https://zoom.us) for meetings) +6. We'll help you with your pull request or issue! ### What we expect in pair programming sessions -These sessions are intended for people who: - -- would like to get started with Gatsby, or -- would like to get started with contributing to open source software, or -- would like to work on an issue or pull request related to Gatsby, or -- are using Gatsby for a personal, open source, charity or education project +These sessions are intended for people who would like to contribute to Gatsby. We will pair program together to solve an issue or pull request related to Gatsby. If you're interested in support for a commercial Gatsby project, please [get in touch via the contact page](https://www.gatsbyjs.com/contact-us/). We also expect the following from pair programming participants: -- These sessions tend to work best when you have a specific goal for the session. +- These sessions work best when you have a specific goal for the session. You should choose an issue or pull request that you'd like to work on. - If you're new to building with Gatsby we recommend [working through the tutorial](https://www.gatsbyjs.org/tutorial/) before your session. If you get stuck part way through that's a great time to book a pairing session. - If you're new to contributing to open source we recommend following the ["Setting Up Your Local Dev Environment" guide](https://www.gatsbyjs.org/contributing/setting-up-your-local-dev-environment/) before your session. - All participants are expected to adhere to [Gatsby’s code of conduct](/contributing/code-of-conduct/) diff --git a/docs/contributing/setting-up-your-local-dev-environment.md b/docs/contributing/setting-up-your-local-dev-environment.md index 2716ed270e7f2..d1ffb0df7d84d 100644 --- a/docs/contributing/setting-up-your-local-dev-environment.md +++ b/docs/contributing/setting-up-your-local-dev-environment.md @@ -19,28 +19,58 @@ Yarn is a package manager for your code, similar to [NPM](https://www.npmjs.com/ ## Gatsby repo install instructions +### Install Node and Yarn + - Ensure you have the latest **LTS** version of Node installed (>= 10.16.0). `node --version` - [Install](https://yarnpkg.com/en/docs/install) the Yarn package manager. - Ensure you have the latest version of Yarn installed (>= 1.0.2). `yarn --version` -- Fork the [official repository](https://github.com/gatsbyjs/gatsby). + +### Fork, clone, and branch the repository + +- [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [official `gatsbyjs/gatsby` repository](https://github.com/gatsbyjs/gatsby). - Clone your fork: `git clone --depth=1 https://github.com//gatsby.git` - Set up repo and install dependencies: `yarn run bootstrap` - Make sure tests are passing for you: `yarn test` - Create a topic branch: `git checkout -b topics/new-feature-name` -- See [docs setup instructions](/contributing/docs-contributions#docs-site-setup-instructions) below for docs-only changes. + +### Docs only changes + +- See [docs setup instructions](/contributing/docs-contributions#docs-site-setup-instructions) for docs-only changes. - Run `yarn run watch` from the root of the repo to watch for changes to packages' source code and compile these changes on-the-fly as you work. + - Note that the watch command can be resource intensive. To limit it to the packages you're working on, add a scope flag, like `yarn run watch --scope={gatsby,gatsby-cli}`. - To watch just one package, run `yarn run watch --scope=gatsby`. -- Install [gatsby-dev-cli](https://www.npmjs.com/package/gatsby-dev-cli) globally: `yarn global add gatsby-dev-cli` + +### Gatsby functional changes + +- Install [gatsby-cli](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-cli): + - Make sure you have the Gatsby CLI installed with `gatsby -v`, + - if not, install globally: `yarn global add gatsby-cli` +- Install [gatsby-dev-cli](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-dev-cli): + - Make sure you have the Gatsby Dev CLI installed with `gatsby-dev -v` + - if not, install globally: `yarn global add gatsby-dev-cli` - Run `yarn install` in each of the sites you're testing. - For each of your Gatsby test sites, run the `gatsby-dev` command inside the test site's directory to copy the built files from your cloned copy of Gatsby. It'll watch for your changes to Gatsby packages and copy them into the site. For more detailed instructions see the [gatsby-dev-cli README](https://www.npmjs.com/package/gatsby-dev-cli) and check out the [gatsby-dev-cli demo video](https://www.youtube.com/watch?v=D0SwX1MSuas). + - Note: if you plan to modify packages that are exported from `gatsby` directly, you need to either add those manually to your test sites so that they are listed in `package.json` (e.g. `yarn add gatsby-link`), or specify them explicitly with `gatsby-dev --packages gatsby-link`). + +### Add tests + - Add tests and code for your changes. - Once you're done, make sure all tests still pass: `yarn test`. + - To run tests for a single package you can run: `yarn jest `. - To run a single test file you can run: `yarn jest `. + +### Commits and pull requests + - Commit and push to your fork. - Create a pull request from your branch. + +### Sync your fork + +- GitHub Help Page [Syncing a fork](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork) +- GitHub Help Page [Merging an upstream repository into your fork](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/merging-an-upstream-repository-into-your-fork) diff --git a/docs/contributing/site-showcase-submissions.md b/docs/contributing/site-showcase-submissions.md index d54268ff7853a..6c5588506b9d7 100644 --- a/docs/contributing/site-showcase-submissions.md +++ b/docs/contributing/site-showcase-submissions.md @@ -28,7 +28,7 @@ There are three major steps: # optional: short paragraph describing the content and/or purpose of the site that will appear in the modal detail view and permalink views for your site description: > - {titleofthesite} is a shiny new website built with Gatsby v2 that makes important contributions towards a faster web for everyone. + This blog is a shiny new website built with Gatsby v2 that makes important contributions towards a faster web for everyone. # You can list as many categories as you want here. Check list of Categories below in this doc! # If you'd like to create a new category, simply list it here. @@ -132,7 +132,7 @@ If your site is chosen as featured, here's what to do next: 2. Add `featured` as a category: -```shell +```yaml categories: - featured ``` diff --git a/docs/contributing/submit-to-plugin-library.md b/docs/contributing/submit-to-plugin-library.md index 915dd3aa89c28..d545ef7c6fd2d 100644 --- a/docs/contributing/submit-to-plugin-library.md +++ b/docs/contributing/submit-to-plugin-library.md @@ -6,10 +6,10 @@ title: Submit to Plugin Library In order to add your plugin to the [Plugin Library](/plugins/), you need to: -1. publish a package to npm (learn how [here](https://docs.npmjs.com/getting-started/publishing-npm-packages)), -2. include the [required files](/docs/files-gatsby-looks-for-in-a-plugin/) in your plugin code, -3. **include a `keywords` field** in your plugin's `package.json`, containing `gatsby` and `gatsby-plugin`, -4. and document your plugin with a README, there are [plugin templates](/contributing/docs-templates/#plugin-readme-template) available to be used as reference. +1. Publish a package to npm (learn how on the [npm docs](https://docs.npmjs.com/getting-started/publishing-npm-packages)). +2. Include the [required files](/docs/files-gatsby-looks-for-in-a-plugin/) in your plugin code. +3. **Include a `keywords` field** in your plugin's `package.json`, containing `gatsby` and `gatsby-plugin`. If your plugin is a theme, please also include `gatsby-theme`. +4. Document your plugin with a README, there is a [plugin template](/contributing/docs-templates/#plugin-readme-template) available to be used as reference. After doing so, Algolia will take up to 12 hours to add it to the library search index (the exact time necessary is still unknown), and wait for the daily rebuild of https://gatsbyjs.org to automatically include your plugin page to the website. Then, all you have to do is share your wonderful plugin with the community! diff --git a/docs/contributing/triaging-github-issues/BugFlow.png b/docs/contributing/triaging-github-issues/BugFlow.png new file mode 100644 index 0000000000000..655a2c5e3d691 Binary files /dev/null and b/docs/contributing/triaging-github-issues/BugFlow.png differ diff --git a/docs/contributing/triaging-github-issues/DocumentationFlow.png b/docs/contributing/triaging-github-issues/DocumentationFlow.png new file mode 100644 index 0000000000000..d8b2e01c722d9 Binary files /dev/null and b/docs/contributing/triaging-github-issues/DocumentationFlow.png differ diff --git a/docs/contributing/triaging-github-issues/FeatureFlow.png b/docs/contributing/triaging-github-issues/FeatureFlow.png new file mode 100644 index 0000000000000..4c502f41c05c7 Binary files /dev/null and b/docs/contributing/triaging-github-issues/FeatureFlow.png differ diff --git a/docs/contributing/triaging-github-issues.md b/docs/contributing/triaging-github-issues/index.md similarity index 62% rename from docs/contributing/triaging-github-issues.md rename to docs/contributing/triaging-github-issues/index.md index cfc24c0ac66e1..5d83381c61d1d 100644 --- a/docs/contributing/triaging-github-issues.md +++ b/docs/contributing/triaging-github-issues/index.md @@ -16,7 +16,7 @@ For Gatsby the first line of communication between a user and the team is the is An opened issue could be: -- a question that can be answered immediately +- [a question that can be answered immediately](#questions-with-immediate-answers) - a bug report - a request for a feature - or a discussion on a complicated use case @@ -25,7 +25,7 @@ On the core team, we regularly designate someone to be a first touch maintainer. First touch maintainers will typically: -- answer questions that can be answered immediately +- [answer questions by pointing to documentation](#questions-with-immediate-answers) - test and reproduce possible bug reports and label them appropriately - communicate feature requests to the rest of the team and ensure a valid response - enable discussions on complicated use cases, whether themselves or via the rest of team @@ -65,7 +65,51 @@ Check out [the docs on issue labeling for more info](/contributing/how-to-label- ### Resolution flowchart -The [resolution flowchart](https://whimsical.co/QvuMgo31T2C3xcWbou8xhy) provides a decision tree for how issues should be categorized into one of five types: question or discussion, bug report, feature request, documentation, or maintenance. +Issues are categorized into one of five types: question or discussion, bug report, feature request, documentation, or maintenance. + +#### Questions with immediate answers + +- Point to existing documentation to answer the question +- If insufficient, do the following: + 1. Provide an answer + 2. Label the issue with documentation + 3. Keep it open until a PR has added the answer to the documentation, and the issue includes a link to said documentation + +If an issue comes in as a question with a known answer it can be tempting to answer it and close the issue. However, the consequence of this approach is that the answer to a question others may have is now buried in a closed issue and may be hard to surface. The preferred solution is to get that answer documented in the main Gatsby documentation and connect the issue to an answer by including a docs link. + +#### Bug Report + +Bug Reports are issues that identify functionality in Gatsby that should work but does not in a given scenario. If an issue is a Bug Report, it should include steps to reproduce the problem. If it doesn't, ask the issue filer for those steps and label the issue with `needs reproduction`. + +Attempt to reproduce the bug using the steps given. If that's not possible, ask for more information and label the issue as `needs more info`. + +If the reproduction is successful, label the issue with `confirmed` and determine who is best suited to implement a fix. If it's approachable for the community, consider the `help wanted` or `good first issue` labels. Otherwise, label with `inkteam to review` so it can be picked up by a Gatsby team member. + +![Flow chart for handling a Bug Report](./BugFlow.png) + +#### Feature Request + +Feature Requests are issues that request support for additional functionality not currently covered in the existing codebase. The first step in triaging a feature request is to determine if it's a reasonable request; this is a challenge and if you don't feel comfortable making this determination please label with `inkteam to review`. If it's clear that this isn't a feature it makes sense for Gatsby to implement, provide a comment explaining the decision making and close the issue. Review the [saved replies](#saved-replies) to see if there is an appropriate response already available. + +If it's determined to be a worthwhile feature, the next decision point is whether the feature should be added to core or upstream. Upstream issues are those that are outside of Gatsby's control and caused by dependencies. Upstream features should be labeled with `upstream` and include comments about the scope. + +If it's a core change, is it a breaking change? Breaking changes should be labeled with `breaking change` and typically closed. Note that they may sometimes be left open with the note that the functionality can only be added in a major release. + +Non-breaking changes can be labeled as `help wanted` and it is often best to ask the creator of the issue if they'd be interested in helping develop the PR. +![Flow chart for handling a Feature Request](./FeatureFlow.png) + +#### Documentation + +Issues can be filed requesting documentation on a particular topic. Sometimes the documentation already exists, so you can link to it and close the issue. + +Alternatively, the issue may be something the team is unable to address. Consider using a [saved reply](#saved-replies) in that circumstance. + +Otherwise, label the issue with `documentation` and ask the issuer filer if they'd like to help with a PR. +![Flow chart for handling a Documentation Request](./DocumentationFlow.png) + +#### Maintenance + +Maintenance issues are things like bumping a package version. These issues should be labeled with `maintenance`. ### Saved replies diff --git a/docs/contributing/why-contribute-to-gatsby.md b/docs/contributing/why-contribute-to-gatsby.md index 0fe47bb06fdbe..0267b487058d0 100644 --- a/docs/contributing/why-contribute-to-gatsby.md +++ b/docs/contributing/why-contribute-to-gatsby.md @@ -6,7 +6,7 @@ There are many reasons to contribute to Gatsby.js and open source software in ge - **Growing your community.** Working with Gatsby.js in open source can connect you with people working on similar things. You can get help or give help, and you might even make an IRL acquaintance! It has happened. -- **Improving your skills.** When you work on a Gatsby issue or pull request, inevitably you'll learn more about how something works in the project; either by asking questions and gathering info, or by digging deeper into the code yourself. Gatsby.js also offers free [pair programming sessions](/contributing/pair-programming/) to the community, if there's something you'd like to work on together. There's definitely a skill-building benefit to contributing in OSS! +- **Improving your skills.** When you work on a Gatsby issue or pull request, inevitably you'll learn more about how something works in the project; either by asking questions and gathering info or by digging deeper into the code yourself. Gatsby.js also offers free [pair programming sessions](/contributing/pair-programming/) to the community, if there's something you'd like to work on together. There's a skill-building benefit to contributing to OSS! - **Getting free swag!** By participating in the repo on GitHub, you can become eligible for free swag that the Gatsby team offers as a way to say thank you. With 5 contributions, you can advance to a second level with even more swag options! Learn more about this [sweet swag deal](/contributing/contributor-swag/). diff --git a/docs/creators/creators.yml b/docs/creators/creators.yml index 595195f0cfeb2..3e82e60fd7255 100644 --- a/docs/creators/creators.yml +++ b/docs/creators/creators.yml @@ -199,9 +199,9 @@ - name: Ramón Chancay type: individual description: >- - Front-end / Back-end Developer in Guayaquil Ecuador. - Currently at Everymundo. - I enjoy teaching and sharing what I know. + Front-end Engineer in Guayaquil Ecuador. + Currently at Everymundo and Freelancer in other companies. + Fan number 1 of Jamstack, I propose solutions serverless. I give professional advice to developers and companies. location: "Guayaquil, Ecuador" website: "https://ramonchancay.me" @@ -447,3 +447,34 @@ for_hire: true hiring: true portfolio: true +- name: Bare Advertising & Communications + type: agency + image: images/bare-advertising-communications.png + description: >- + We’re an agile group of full-time, fast-moving, hard-working, idea-generating, results-getting, on-timing, on-budgeting, espresso-fuelled content writers, designers, developers, media mavens, strategists, and producers. + location: Canada + website: "https://bare.ca/" + for_hire: true + hiring: false + portfolio: true +- name: Epic Awesome + type: agency + image: images/epic-awesome.jpg + description: >- + We help startups and small business to grow their business. We provide business and tech consulting alongside web and mobile development. + location: Brazil and Sweden + website: "https://epicawesome.se/" + for_hire: true + hiring: false + portfolio: true +- name: Eric Howey + type: individual + description: >- + My name is Eric Howey. I am a web developer and mental health therapist. I specialize in Gatsby, React, and Theme-UI. I listen and care. + location: Canada + website: "https://www.erichowey.dev/" + github: "https://github.com/ehowey" + image: images/eric-howey.jpeg + for_hire: true + hiring: false + portfolio: true diff --git a/docs/creators/images/bare-advertising-communications.png b/docs/creators/images/bare-advertising-communications.png new file mode 100644 index 0000000000000..7d0253e6650c7 Binary files /dev/null and b/docs/creators/images/bare-advertising-communications.png differ diff --git a/docs/creators/images/epic-awesome.jpg b/docs/creators/images/epic-awesome.jpg new file mode 100644 index 0000000000000..815f5a35f6c73 Binary files /dev/null and b/docs/creators/images/epic-awesome.jpg differ diff --git a/docs/creators/images/eric-howey.jpeg b/docs/creators/images/eric-howey.jpeg new file mode 100644 index 0000000000000..da547f014f9da Binary files /dev/null and b/docs/creators/images/eric-howey.jpeg differ diff --git a/docs/creators/images/ramon-chancay.png b/docs/creators/images/ramon-chancay.png index ee4db3dd43c28..5e87e860d124f 100644 Binary files a/docs/creators/images/ramon-chancay.png and b/docs/creators/images/ramon-chancay.png differ diff --git a/docs/docs/add-404-page.md b/docs/docs/add-404-page.md index 026eec5b697df..967057b77f0c4 100644 --- a/docs/docs/add-404-page.md +++ b/docs/docs/add-404-page.md @@ -2,27 +2,16 @@ title: Adding a 404 Page --- -To create a 404 page create a page whose path matches the regex -`^\/?404\/?$` (`/404/`, `/404`, `404/` or `404`). Most often you'll want to create a React component page at -`src/pages/404.js`. +To create a 404 page create a page whose path matches the regex `^\/?404\/?$` (`/404/`, `/404`, `404/` or `404`). Most often you'll want to create a React component page at `src/pages/404.js`. -Gatsby ensures that your 404 page is built as `404.html` as many static hosting -platforms default to using this as your 404 error page. If you're hosting your -site another way, you'll need to set up a custom rule to serve this file for 404 -errors. +Gatsby ensures that your 404 page is built as `404.html` as many static hosting platforms default to using this as your 404 error page. If you're hosting your site another way you'll need to set up a custom rule to serve this file for 404 errors. -Because Gatsby creates this page for you by default, there is no need to configure -it in your `gatsby-node.js` file. +Because Gatsby creates this page for you by default, there is no need to configure it in your `gatsby-node.js` file. -When developing using `gatsby develop`, Gatsby uses a default 404 page that -overrides your custom 404 page. However, you can still preview your 404 page by -clicking "Preview custom 404 page" to verify that it's working as expected. This is -useful when you're developing so that you can see all the available pages. +When developing using `gatsby develop`, Gatsby uses a default 404 page that overrides your custom 404 page. However, you can still preview your 404 page by clicking "Preview custom 404 page" to verify that it's working as expected. This is useful when you're developing so that you can see all the available pages. -The screenshot below shows the default 404 page that Gatsby creates. -It also lists out all the pages on your website. Clicking the "Preview custom 404 -page" button will allow you to view the 404 page you created. -![Gatsby Default 404 Page](images/gatsby-default-404.png) +The screenshot below shows the default 404 page that Gatsby creates. It also lists out all the pages on your website. Clicking the "Preview custom 404 page" button will allow you to view the 404 page you created. +![Gatsby Default 404 Page](./images/gatsby-default-404.png) The screenshot below shows the custom 404 page. -![Gatsby Custom 404 Page](images/gatsby-custom-404.png) +![Gatsby Custom 404 Page](./images/gatsby-custom-404.png) diff --git a/docs/docs/add-a-manifest-file.md b/docs/docs/add-a-manifest-file.md index ae48ba6f0ce07..13c6786cafe55 100644 --- a/docs/docs/add-a-manifest-file.md +++ b/docs/docs/add-a-manifest-file.md @@ -16,7 +16,7 @@ Quoting [Google](https://developers.google.com/web/fundamentals/web-app-manifest [Gatsby's manifest plugin](/packages/gatsby-plugin-manifest/) configures Gatsby to create a `manifest.webmanifest` file on every site build. -### Using `gatsby-plugin-manifest` +## Using `gatsby-plugin-manifest` 1. Install the plugin: diff --git a/docs/docs/add-custom-webpack-config.md b/docs/docs/add-custom-webpack-config.md index 70384ee3b35aa..60a40ee01668d 100644 --- a/docs/docs/add-custom-webpack-config.md +++ b/docs/docs/add-custom-webpack-config.md @@ -2,39 +2,22 @@ title: "Adding a Custom Webpack Config" --- -_Before creating custom webpack configuration, check to see if there's a Gatsby -plugin already built that handles your use case in the -[plugins section](/docs/plugins/). If there's not yet one and your use case is a -general one, it is highly encouraged you to contribute back your plugin to the -Gatsby Plugin Library so it's available to others (including your future self)._ - -To add custom webpack configurations, create (if there's not one already) a -`gatsby-node.js` file in your root directory. Inside this file, export a -function called `onCreateWebpackConfig`. - -When Gatsby creates its webpack config, this function will be called allowing -you to modify the default webpack config using -[webpack-merge](https://github.com/survivejs/webpack-merge). - -Gatsby does multiple webpack builds with somewhat different configuration. Gatsby -calls each build type a "stage". The following stages exist: - -1. develop: when running the `gatsby develop` command. Has configuration for hot - reloading and CSS injection into page -2. develop-html: same as develop but without react-hmre in the babel config for - rendering the HTML component. -3. build-javascript: production JavaScript and CSS build. Creates route JS bundles as well - as common chunks for JS and CSS. +_Before creating custom webpack configuration, check to see if there's a Gatsby plugin already built that handles your use case in the [plugins section](/docs/plugins/). If there's not yet one and your use case is a general one, it is highly encouraged you to contribute back your plugin to the Gatsby Plugin Library so it's available to others (including your future self)._ + +To add custom webpack configurations, create (if there's not one already) a `gatsby-node.js` file in your root directory. Inside this file, export a function called `onCreateWebpackConfig`. + +When Gatsby creates its webpack config, this function will be called allowing you to modify the default webpack config using [webpack-merge](https://github.com/survivejs/webpack-merge). + +Gatsby does multiple webpack builds with somewhat different configuration. Gatsby calls each build type a "stage". The following stages exist: + +1. develop: when running the `gatsby develop` command. Has configuration for hot reloading and CSS injection into page +2. develop-html: same as develop but without react-hmre in the babel config for rendering the HTML component. +3. build-javascript: production JavaScript and CSS build. Creates route JS bundles as well as common chunks for JS and CSS. 4. build-html: production build static HTML pages -Check -[webpack.config.js](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/webpack.config.js) -for the source. +Check [webpack.config.js](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/webpack.config.js) for the source. -There are many plugins in the Gatsby repo using this API to look to for examples -e.g. [Sass](/packages/gatsby-plugin-sass/), -[TypeScript](/packages/gatsby-plugin-typescript/), -[Glamor](/packages/gatsby-plugin-glamor/), and many more! +There are many plugins in the Gatsby repo using this API to look to for examples e.g. [Sass](/packages/gatsby-plugin-sass/), [TypeScript](/packages/gatsby-plugin-typescript/), [Glamor](/packages/gatsby-plugin-glamor/), and many more! ## Examples diff --git a/docs/docs/add-offline-support-with-a-service-worker.md b/docs/docs/add-offline-support-with-a-service-worker.md index 6182dd920e696..9e21da2fe15e3 100644 --- a/docs/docs/add-offline-support-with-a-service-worker.md +++ b/docs/docs/add-offline-support-with-a-service-worker.md @@ -7,19 +7,19 @@ If you've run an [audit with Lighthouse](/docs/audit-with-lighthouse/), you may 1. You can [add a manifest file](/docs/add-a-manifest-file/). Ensure that the manifest plugin is listed _before_ the offline plugin so that the offline plugin can cache the created `manifest.webmanifest`. 2. You can also add offline support, since another requirement for a website to qualify as a PWA is the use of a [service worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). [Gatsby's offline plugin](/packages/gatsby-plugin-offline/) makes a Gatsby site work offline--and makes it more resistant to bad network conditions--by creating a service worker for your site. -### What is a service worker? +## What is a service worker? A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction. They increase your site availability in spotty connections, and are essential to making a nice user experience. It supports features like push notifications and background synchronization. -### Using service workers in Gatsby with `gatsby-plugin-offline` +## Using service workers in Gatsby with `gatsby-plugin-offline` Gatsby provides an awesome plugin interface to create and load a service worker into your site: [gatsby-plugin-offline](https://www.npmjs.com/package/gatsby-plugin-offline). We recommend using this plugin together with the [manifest plugin](https://www.npmjs.com/package/gatsby-plugin-manifest). (Don’t forget to list the offline plugin after the manifest plugin so that the manifest file can be included in the service worker). -### Installing `gatsby-plugin-offline` +## Installing `gatsby-plugin-offline` `npm install --save gatsby-plugin-offline` @@ -43,7 +43,7 @@ That's all you need to add offline support to your Gatsby site. Note: Service worker registers only in production builds (`gatsby build`). -### Displaying a message when a service worker updates +## Displaying a message when a service worker updates To display a custom message once your service worker finds an update, you can use the [`onServiceWorkerUpdateReady`](/docs/browser-apis/#onServiceWorkerUpdateReady) browser API in your `gatsby-browser.js` file. The following code will display a confirm prompt asking the user whether they would like to refresh the page when an update is found: @@ -60,7 +60,7 @@ export const onServiceWorkerUpdateReady = () => { } ``` -### Using a custom service worker in Gatsby +## Using a custom service worker in Gatsby You can add a custom service worker if your use case requires something that `gatsby-plugin-offline` doesn't support. @@ -74,7 +74,7 @@ export const registerServiceWorker = () => true That's all! Gatsby will register your custom service worker. -### Removing the service worker +## Removing the service worker If you would like to fully remove the service worker from your site, you can use the plugin `gatsby-plugin-remove-serviceworker` in place of `gatsby-plugin-offline`. See [the README for `gatsby-plugin-offline`](/packages/gatsby-plugin-offline/#remove) for instructions how to do this. diff --git a/docs/docs/add-page-metadata.md b/docs/docs/add-page-metadata.md index e2028997bd56f..1a243d1a02c1d 100644 --- a/docs/docs/add-page-metadata.md +++ b/docs/docs/add-page-metadata.md @@ -10,7 +10,7 @@ Adding metadata to pages (such as a title or description) is key in helping sear Gatsby's [react helmet plugin](/packages/gatsby-plugin-react-helmet/) provides drop-in support for server rendering data added with React Helmet. Using the plugin, attributes you add to React Helmet will be added to the static HTML pages that Gatsby builds. -### Using `React Helmet` and `gatsby-plugin-react-helmet` +## Using `React Helmet` and `gatsby-plugin-react-helmet` 1. Install both packages: diff --git a/docs/docs/add-seo-component.md b/docs/docs/add-seo-component.md index 51e949707cf8f..8d471a2b20bd5 100644 --- a/docs/docs/add-seo-component.md +++ b/docs/docs/add-seo-component.md @@ -63,10 +63,7 @@ Now define the query and place it in the StaticQuery (you can also save the quer ```jsx:title=src/components/SEO.js const SEO = ({ title, description, image, pathname, article }) => ( - + ) export default SEO @@ -84,7 +81,7 @@ const query = graphql` } } } -`; +` ``` The next step is to destructure the data from the query and to create an object that checks if the props were used — if not the default values are utilized. The name aliasing comes in handy here: It avoids name collisions. diff --git a/docs/docs/adding-a-list-of-markdown-blog-posts.md b/docs/docs/adding-a-list-of-markdown-blog-posts.md index ddd855671a78f..f61a04c5c9022 100644 --- a/docs/docs/adding-a-list-of-markdown-blog-posts.md +++ b/docs/docs/adding-a-list-of-markdown-blog-posts.md @@ -4,11 +4,11 @@ title: Adding a List of Markdown Blog Posts Once you have added Markdown pages to your site, you are just one step away from being able to list your posts on a dedicated index page. -### Creating posts +## Creating posts As described [here](/docs/adding-markdown-pages), you will have to create your posts in Markdown files which will look like this: -```md +```markdown --- path: "/blog/my-first-post" date: "2017-11-07" @@ -18,7 +18,7 @@ title: "My first blog post" Has anyone heard about GatsbyJS yet? ``` -### Creating the page +## Creating the page The first step will be to create the page which will display your posts, in `src/pages/`. You can for example use `index.js`. @@ -41,7 +41,7 @@ const IndexPage = ({ export default IndexPage ``` -### Creating the GraphQL query +## Creating the GraphQL query Second, you need to provide the data to your component with a GraphQL query. Add it, so that `index.js` looks like this: @@ -83,7 +83,7 @@ export const pageQuery = graphql` ` ``` -### Creating the `PostLink` component +## Creating the `PostLink` component The only thing left to do is to add the `PostLink` component. Create a new file `post-link.js` in `src/components/` and add the following: diff --git a/docs/docs/adding-an-rss-feed.md b/docs/docs/adding-an-rss-feed.md index 053d9f500902e..e3f2a078d751f 100644 --- a/docs/docs/adding-an-rss-feed.md +++ b/docs/docs/adding-an-rss-feed.md @@ -132,7 +132,7 @@ The `output` field in your feed object allows you to customize the filename for By default, feed is referenced in every page. You can customize this behavior by providing an extra field `match` of type `string`. This string will be used to build a `RegExp`, and this regular expression will be used to test the `pathname` of current page. Only pages that satisfied the regular expression will have feed reference included. -To see your feed in action, run `gatsby build && gatsby serve` and you can then inspect the content and URLs in your RSS file at `http://localhost:9000/rss.xml`. +To see your feed in action, run `gatsby build && gatsby serve` and you can then inspect the content and URLs in your RSS file at . > NOTE: if your blog has custom permalinks, such as links with or without dates in them, you may need to [customize `gatsby-node.js`](https://github.com/gatsbyjs/gatsby-starter-blog/blob/master/gatsby-node.js#L57) to output the correct URLs in your RSS feed. [Get in touch with us](/contributing/how-to-contribute/) if you need any help! diff --git a/docs/docs/adding-app-and-website-functionality.md b/docs/docs/adding-app-and-website-functionality.md new file mode 100644 index 0000000000000..e123b5ef3d6ee --- /dev/null +++ b/docs/docs/adding-app-and-website-functionality.md @@ -0,0 +1,94 @@ +--- +title: Adding App and Website Functionality +overview: true +--- + +Gatsby empowers developers and creators to make many different types of websites. One may wish to add additional functionality to their site such as search, authentication, forms, comments, and plenty of others. + +The distinction between apps and websites is blurry, the way Dustin Schau puts it in a [blog post](/blog/2018-10-15-beyond-static-intro/): + + + I contend that the line between these two concepts is extremely blurry. There + isn’t some magic percentage threshold that, when crossed, indicates that a + static site is now an application. Nor is the inverse true, that an “app” is + somehow static because some percentage of its content never or rarely changes. + + +Gatsby allows you to orchestrate data fetching, transforming, and usage in pages, but it also allows you to make the call about how, when, and where, that happens. It allows you to make a site as feature-less or feature-rich as you want, you aren't restricted to just static sites. + +## How hydration makes apps possible + +Even though Gatsby generates static files, Gatsby apps [rehydrate](/docs/glossary#hydration) from static HTML rendered by ReactDOM APIs into an app running client-side JavaScript. The general approach as outlined in the [React Hydration guide](/docs/react-hydration) is as follows: + +1. Build and render static HTML, creating content and pages with data injected at build time +2. Invoke `ReactDOM.hydrate()` method to pick up where the static HTML was left +3. Transfer rendering to the React reconciler + +It's this last phase that bridges the gap between static sites and full-fledged applications. In this phase you can make calls for [dynamic data](/docs/client-data-fetching/), [authenticate users](/docs/building-a-site-with-authentication/), and perform all the app-like functionality you desire because the page is running a React application. + +## Common patterns for Gatsby apps + +There are different options for organizing how your pages are created and what they will be responsible for. These patterns can be combined and tweaked for specific use cases such as pulling in data at [build time](/docs/glossary#build) for great performance, or calling for data at [runtime](/docs/glossary#runtime) for a more dynamic experience. + +Because all Gatsby pages are hydrated into React, **any of the following patterns are capable of app-like behavior**. This section is to help explain some higher level patterns for thinking about Gatsby. + +### Static pages + +Static files are output by running `gatsby build` from exported components in your `src/pages` folder or from pages created using the [`createPage` API](/docs/node-apis/#createPages), as shown in this diagram: + +![Static Site diagram with pages created from Gatsby automatically and programmatically](./images/simple-static-site.png) + +The diagram illustrates the 2 main methods for creating pages in your site: + +1. Automatically through `src/pages` +2. Programmatically with the `createPage` API + +_**Note**: plugins and themes can also implement the `createPage` API and create pages on your behalf_ + +When you export a React component from a file in the `src/pages` directory (in this case `src/pages/home.js` for `/home`) Gatsby will automatically create a static page. By looping through Markdown files in your filesystem you can create pages for all blog posts programmatically. The docs have more information about [creating and modifying pages](/docs/creating-and-modifying-pages/). + +These created pages _could_ run JavaScript once React hydrates them, but they don't need to. + +### Hybrid app pages + +Your created pages can make calls to external services and APIs in order to allow more interactive and dynamic behavior. These are sometimes referred to as hybrid app pages because they share a combination of static features that Gatsby creates to help load your site quickly and performantly as well as traditional web app features. + +The following diagram shows a similar site to the one in the previous example, but with a subscription form added to the home page that makes client-side `POST`'s to a database somewhere, as well as blog posts that `GET` recommendations from a database or other API endpoint. + +![Hybrid Site diagram with pages hitting other services with JavaScript](./images/simple-hybrid-site.png) + +Following a pattern like this means you are relying on a [backend](/docs/glossary#backend) to remain operational for features like email signups and blog recommendations, but because the static assets created aren't generated by the server on demand, the content on your site (like your blog posts or home page) will never go down or become unavailable. + +### Client only routes + +Using a React-based client-side router is also supported by Gatsby. This pattern is often referred to as client only routes, which are routes not reflected in your statically rendered files. Gatsby ships with `@reach/router`, so it is a great option to keep your site from having to ship additional JavaScript with another routing library. + +With Gatsby, you can import a router and set up routes for navigation the same way you would in traditional React apps. The only difference is Gatsby doesn't build those routes into individual pages in the `/public` folder. As a result, in order to allow users to access that URL directly, you can use a plugin to create those pages. This is covered in the [Client Only Routes](/docs/client-only-routes-and-user-authentication/) guide. + +The following diagram shows how a `` component can be mounted on a page. In this example, `src/pages/app` references ``s. + +![Client Only Routes Site diagram with pages setup using a router](./images/simple-client-only-routes.png) + +In this illustration, a client-rendered user page could display specific information about the logged-in user, and dynamic client-side routes at `/app/tasks/:id` could display specific information for a task of a given ID. + +## Differences between Gatsby and other React apps + +There is a bit of a paradigm shift to overcome in understanding how a Gatsby app is different from an app created with a tool like Create React App. + +> _A site built with Create React App can actually be [ported to Gatsby](/docs/porting-from-create-react-app-to-gatsby/)._ + +### The global `App.js` component + +One main distinction explained in the diagrams in the section on [common patterns for Gatsby apps](#common-patterns-for-gatsby-apps) is the combination of hybrid and static pages that Gatsby offers vs one global `App.js` component. An app from Create React App will have exclusivley client routes set up on one `App.js` component rendered at the root, which isn't unmounted. The `App.js` component is often the place in a React app where Theme Providers and Context are wrapped around the entire app so some data can be provided to all components or preserved between route changes. Gatsby has a root element that can be wrapped to preserve state or data between page navigation as well, but it is accessed through the [`wrapRootElement` API](/docs/browser-apis/#wrapRootElement) instead of being in a file in your `src` folder. Persistent UI elements can be wrapped around pages with the [`wrapPageElement` API](/docs/browser-apis/#wrapPageElement). + +### Page and route creation + +In a React app, creating pages requires setting up a router. Gatsby instead handles some pieces of routing on your behalf; you can create a page by putting an exported component inside the pages directory. Gatsby will generate a page with a fixed URL based on the filename of the component. You can still import a router and set up routes yourself though. + +> _To compare Gatsby with other Jamstack tools like Next.js and Jekyll, check out the [feature comparison](/features/jamstack/) page._ + +--- + +Generating performant sites with statically rendered assets is a core focus of Gatsby, but it's only one side of the coin. In this section of the docs, you will find a showcase of guides and concepts on how to level up your site to include all the app-like features on top of the static base. + + diff --git a/docs/docs/adding-comments.md b/docs/docs/adding-comments.md index 4930ac894602b..9b321a2556306 100644 --- a/docs/docs/adding-comments.md +++ b/docs/docs/adding-comments.md @@ -34,7 +34,7 @@ If these concerns outweigh the benefits of Disqus, you may want to look into som ## Implementing Disqus -![Disqus logo](images/disqus-logo.svg) +![Disqus logo](./images/disqus-logo.svg) Here are the steps for adding Disqus comments to your own blog: @@ -47,12 +47,12 @@ npm install disqus-react 3. Add the shortname from step 1 as something like `GATSBY_DISQUS_NAME` to your `.env` and `.env.example` files so that people forking your repo will know that they need to supply this value to get comments to work. (You need to prefix the environment variable with `GATSBY_` in order to [make it available to client-side code](https://www.gatsbyjs.org/docs/environment-variables/#client-side-javascript).) -```title=.env.example +```text:title=.env.example # enables Disqus comments for blog posts GATSBY_DISQUS_NAME=insertValue ``` -```title=.env +```text:title=.env GATSBY_DISQUS_NAME=yourSiteShortname ``` @@ -76,7 +76,7 @@ const disqusConfig = { Where `identifier` must be a string or number that uniquely identifies the post. It could be the post's slug, title or some ID. Finally, add `DiscussionEmbed` to the JSX of your post template. -```js:title=src/templates/post.js +```jsx:title=src/templates/post.js return ( @@ -89,4 +89,4 @@ return ( And you're done. You should now see the Disqus comment form appear beneath your blog post [looking like this](https://janosh.io/blog/disqus-comments#disqus_thread). Happy blogging! -[![Disqus comments](images/disqus-comments.png)](https://janosh.io/blog/disqus-comments#disqus_thread) +[![Disqus comments](./images/disqus-comments.png)](https://janosh.io/blog/disqus-comments#disqus_thread) diff --git a/docs/docs/adding-markdown-pages.md b/docs/docs/adding-markdown-pages.md index 98ad25de3f8d5..71cb81c588962 100644 --- a/docs/docs/adding-markdown-pages.md +++ b/docs/docs/adding-markdown-pages.md @@ -17,11 +17,11 @@ Here are the steps Gatsby follows for making this happen. Use the plugin [`gatsby-source-filesystem`](/packages/gatsby-source-filesystem/#gatsby-source-filesystem) to read files. -#### Install +### Install `npm install --save gatsby-source-filesystem` -#### Add plugin +### Add plugin **NOTE:** There are two ways to add a plugin in `gatsby-config.js`. Either you can pass a string with the plugin name or in case you want to include options, pass an object. @@ -41,15 +41,15 @@ plugins: [ Completing the above step means that you've "sourced" the Markdown files from the filesystem. You can now "transform" the Markdown to HTML and the YAML frontmatter to JSON. -### Transform Markdown to HTML and frontmatter to data using `gatsby-transformer-remark` +## Transform Markdown to HTML and frontmatter to data using `gatsby-transformer-remark` You'll use the plugin [`gatsby-transformer-remark`](/packages/gatsby-transformer-remark/) to recognize files which are Markdown and read their content. The plugin will convert the frontmatter metadata part of your Markdown files as `frontmatter` and the content part as HTML. -#### Install +### Install transformer plugin `npm install --save gatsby-transformer-remark` -#### Add plugin +### Configure plugin Add this to `gatsby-config.js` after the previously added `gatsby-source-filesystem`. @@ -66,12 +66,12 @@ plugins: [ ] ``` -### Add a Markdown file +## Add a Markdown file Create a folder in the `/src` directory of your Gatsby application called `markdown-pages`. Now create a Markdown file inside it with the name `post-1.md`. -#### Frontmatter for metadata in markdown files +### Frontmatter for metadata in Markdown files When you create a Markdown file, you can include a set of key value pairs that can be used to provide additional data relevant to specific pages in the GraphQL data layer. This data is called frontmatter and is denoted by the triple dashes at the start and end of the block. This block will be parsed by `gatsby-transformer-remark` as `frontmatter`. The GraphQL API will provide the key value pairs as data in your React components. @@ -85,7 +85,7 @@ title: "My first blog post" What is important in this step is the key pair `path`. The value that is assigned to the key `path` is used in order to navigate to your post. -### Create a page template for the Markdown files +## Create a page template for the Markdown files Create a folder in the `/src` directory of your Gatsby application called `templates`. Now create a `blogTemplate.js` inside it with the following content: diff --git a/docs/docs/adding-page-transitions-with-plugin-transition-link.md b/docs/docs/adding-page-transitions-with-plugin-transition-link.md index cf980a6486a69..bca376c4e36a1 100644 --- a/docs/docs/adding-page-transitions-with-plugin-transition-link.md +++ b/docs/docs/adding-page-transitions-with-plugin-transition-link.md @@ -48,13 +48,13 @@ npm install --save gsap Then, import the AniLink component: -```javascript +```jsx import AniLink from "gatsby-plugin-transition-link/AniLink" ``` Finally, make sure you provide your desired animation's name as a blank prop to `AniLink`: -```javascript +```jsx Go to Page 4 @@ -71,11 +71,11 @@ You have two main methods of creating page transitions: Additionally, you can specify a number of props and options on the `TransitionLink` component, like `length`, `delay`, and more. For more options and details, see [the documentation of TransitionLink](https://transitionlink.tylerbarnes.ca/docs/transitionlink/). For further examples of usage, visit the [plugin's GitHub repository.](https://github.com/TylerBarnes/gatsby-plugin-transition-link) -#### Using the trigger function +### Using the trigger function You can specify a `trigger` function that will handle the animation. This is useful for _imperative_ animation libraries like [animejs](https://animejs.com/) or [GSAP](https://greensock.com/gsap) that specify animations with function calls. -```javascript +```jsx ``` -#### Using passed props +### Using passed props The exiting and entering pages/templates involved in the transition will receive props indicating the current transition status, as well as the `exit` or `enter` props defined on the `TransitionLink`. -```javascript +```jsx const PageOrTemplate = ({ children, transitionStatus, entry, exit }) => { console.log(transitionStatus, entry, exit) return
{children}
@@ -112,7 +112,7 @@ If you want to access these props in one of your components instead of a page/te Here's an example using `TransitionState` and `react-pose` to trigger enter/exit transitions for a `Box` component. -```javascript +```jsx import { TransitionState } from "gatsby-plugin-transition-link" const Box = posed.div({ @@ -121,15 +121,16 @@ const Box = posed.div({ }) - {({ transitionStatus, exit, enter }) => { - console.log('exit object is', exit) - console.log('enter object is', enter) + {({ transitionStatus, exit, enter, mount }) => { + console.log("current page's transition status is", transitionStatus) + console.log("exit object is", exit) + console.log("enter object is", enter) return ( ``` -Now, the `Box` component will be aware of the transition status of the page it's a child of, and it will fade in/out accordingly. +Now, the `Box` component will be aware of whether the page it's a child of is mounting or unmounting, and it will fade in/out accordingly. ## Excluding elements from page transitions -You may want to have elements on a page that persist throughout the page transition (_ex. a site-wide header_). This can be accomplished by wrapping elements in the `TransitionPortal` component. - -```javascript -import { TransitionPortal } from "gatsby-plugin-transition-link" -``` +You may want to have elements on a page that persist throughout the page transition (_ex. a site-wide header_). This can be accomplished by wrapping elements in a persistent layout component by using the following plugin option in your `gatsby-config.js`. ```javascript - - - This component will sit on top of both pages, and persist through page - transitions. - - +module.exports = { + plugins: [ + { + resolve: "gatsby-plugin-transition-link", + options: { + layout: require.resolve(`./src/components/Layout.js`) + } + } + ] +]; ``` -As always, check out [the `TransitionPortal` docs](https://transitionlink.tylerbarnes.ca/docs/transitionportal/) for more information about `TransitionPortal`. +As always, check out [the installation docs](https://transitionlink.tylerbarnes.ca/docs/transitionportal/) for more information. ## Further reading diff --git a/docs/docs/adding-pagination.md b/docs/docs/adding-pagination.md index fdfb1584910a8..0fb4ddd1e59fc 100644 --- a/docs/docs/adding-pagination.md +++ b/docs/docs/adding-pagination.md @@ -11,9 +11,9 @@ Each page will [query GraphQL](/docs/querying-with-graphql/) for those specific The information needed to query for those specific items (i.e. values for [`limit`](/docs/graphql-reference/#limit) and [`skip`](/docs/graphql-reference/#skip)) will come from the [`context`](/docs/graphql-reference/#query-variables) that is added when [creating pages](/docs/creating-and-modifying-pages/#creating-pages-in-gatsby-nodejs) in `gatsby-node`. -### Example +## Example -```js:title=src/templates/blog-list-template.js +```jsx:title=src/templates/blog-list-template.js import React from "react" import { graphql } from "gatsby" import Layout from "../components/layout" @@ -126,7 +126,7 @@ exports.onCreateNode = ({ node, actions, getNode }) => { The code above will create an amount of pages that is based on the total number of posts. Each page will list `postsPerPage`(6) posts, until there are less than `postsPerPage`(6) posts left. The path for the first page is `/blog`, following pages will have a path of the form: `/blog/2`, `/blog/3`, etc. -### Other resources +## Other resources - Follow this [step-by-step tutorial](https://nickymeuleman.netlify.com/blog/gatsby-pagination/) to add links to the previous/next page and the traditional page-navigation at the bottom of the page diff --git a/docs/docs/adding-react-components.md b/docs/docs/adding-react-components.md new file mode 100644 index 0000000000000..eb632e9f6b8d1 --- /dev/null +++ b/docs/docs/adding-react-components.md @@ -0,0 +1,84 @@ +--- +title: Adding React Components +--- + +This guide covers how to add React components to your Gatsby site. + +## React components + +React components are prebuilt elements or groups of elements that can be used to split your User Interface (UI) into independent, reusable pieces. There are multiple types of components you can write: this guide covers functional components. For more in-depth information on writing React components including classes, check out the [React documentation](https://reactjs.org/docs/components-and-props.html). + +Components also offer the ability to be customized using inputs, better known as "props" (properties). Props can be of any JavaScript type, such as Boolean, String, Object, Array or almost anything you can think of. + +For example, you could use a component for Buttons on your site. This would enable them to be used multiple times across pages with different labels or actions each time. + +## Importing React components + +In Gatsby, when using React components, you can import and use them like you would in a React application. Here's an example of the [Gatsby Link](/docs/gatsby-link/) component in action, which brings with it extra functionality for performance: + +```jsx +import React from "react" +import { Link } from "gatsby" + +export default () => ( +
+ Contact +
+) +``` + +### Importing third-party components + +Just like React, Gatsby also supports third-party components and libraries. You can install a third-party component or library via your package manager. We tend to favour and use npm and we will reflect this in our examples. + +Here's an example of adding a third-party component to your site. + +First, you have to install the component or library's package via a package manager. It's recommended not to mix package managers, so if you use npm, don't use another and vice versa. + +```shell +npm install @material-ui/core +``` + +After you've installed a package, import and use it in your page's source: + +```jsx:title=my-page.jsx +import React from "react" + +// import my fancy third-party component +import Button from "@material-ui/core/Button" + +export default () => ( +
+

This is my super awesome page made with Gatsby!

+ + {/* use my fancy third-party component */} + +
+) +``` + +## Things to watch out for + +Since Gatsby uses Server-Side Rendering (SSR) to generate your site's pages, the JSX code you write is usually compiled before the browser loads the page. Because of this, certain features are not available at compile time and can cause a build error. + +### Use of browser globals + +Some components or code reference browser globals such as `window`, `document` or `localStorage`. These objects are not available at [build](/docs/glossary#build) time and can result in a webpack error when compiling: + +```text +WebpackError: ReferenceError: window is not defined +``` + +To learn more about solutions for supporting SSR and client-side libraries, check out the related section on the [Porting from Create React App documentation](/docs/porting-from-create-react-app-to-gatsby#server-side-rendering-and-browser-apis). + +#### Fixing third-party modules + +Some packages expect `window` or another browser global to be defined. These packages will have to be patched. + +You can learn how to patch these packages on the [Debugging HTML Builds documentation](/docs/debugging-html-builds/#fixing-third-party-modules). + +### Components without server-side rendering + +Server-side rendering means pages and content are built out by the Node.js server and then sent to a browser ready to go. It’s like your pages are constructed before even being sent to the user. Gatsby is server-side rendered at build time, meaning that the code that gets to your browser has already been run to build pages and content, but this doesn’t mean you can’t still have dynamic pages. + +Some React components don't have server-side rendering support (SSR) out-of-the-box so you might have to add SSR yourself. diff --git a/docs/docs/adding-search-with-algolia.md b/docs/docs/adding-search-with-algolia.md index 43d3096b16984..d4df4058cf74b 100644 --- a/docs/docs/adding-search-with-algolia.md +++ b/docs/docs/adding-search-with-algolia.md @@ -78,7 +78,7 @@ Since your .env file contains your real private API keys, it is considered a sec ```text:title=.env.example # rename this file to .env and supply the values listed below # also make sure they are available to the build tool (e.g. Netlify) -# warning: variables prexifed with GATSBY_ will be made available to client-side code +# warning: variables prefixed with GATSBY_ will be made available to client-side code # be careful not to expose sensitive data (in this case your Algolia admin key) GATSBY_ALGOLIA_APP_ID=insertValue @@ -157,7 +157,7 @@ It might look a little intimidating at first, but basically you're just letting Transformers allow you to modify the data returned by the queries to bring it into a format ready for searching. All you're doing here is 'flattening' posts and pages to 'unnest' the frontmatter fields (such as `author`, `date`, `tags`) but transformers could do much more for you if required. This makes the whole process of indexing your data really flexible and powerful. You could for instance use them to filter the results of your queries, format fields, add or merge them, etc. -If you've come this far, then the "backend" is done. You should now be able to run `gatsby build` and see your indices in Algolia's webinterface be flooded with your data. +If you've come this far, then the "backend" is done. You should now be able to run `gatsby build` and see your indices in Algolia's web interface be flooded with your data. ## Adding a search interface to your site @@ -176,7 +176,7 @@ There's quite a lot happening in these files so break them down one by one and p ### `index.js` -```js:title=src/components/search/index.js +```jsx:title=src/components/search/index.js import React, { useState, useEffect, createRef } from "react" import { InstantSearch, @@ -254,7 +254,7 @@ At the top, you import `InstantSearch` from [`react-instantsearch-dom`](https:// You then import the styled components that make up the UI and the `Input` component into which the user enters the query. -```js:title=src/components/search/index.js +```jsx:title=src/components/search/index.js import { Root, SearchBox, HitsWrapper, PoweredBy } from "./styles" import Input from "./Input" ``` @@ -263,13 +263,13 @@ import Input from "./Input" The last thing you need for the `Search` component to work are hit components for every type of result you want to display to the user. The hit component determines how attributes of matching results (such as author, date, tags and title in the case of a blog post) are displayed to the user. -```js:title=src/components/search/index.js +```jsx:title=src/components/search/index.js import * as hitComps from "./hitComps" ``` Next you define two connected components. `Results` informs the user that no matches could be found for a query unless the number of hits is positive, i.e. `searchResults.nbHits > 0`. `Stats` just displays `searchResults.nbHits`. -```js:title=src/components/search/index.js +```jsx:title=src/components/search/index.js const Results = connectStateResults( ({ searchState: state, searchResults: res, children }) => res && res.nbHits > 0 ? children : `No results for ${state.query}` @@ -283,7 +283,7 @@ const Stats = connectStateResults( Now comes the actual `Search` component. It starts off with some state initialization, defining handler functions and event listeners to trigger them. All they do is make the search input slide out when the user clicks a search icon and disappear again when the user clicks or touches (on mobile) anywhere. -```js:title=src/components/search/index.js +```jsx:title=src/components/search/index.js export default function Search({ indices, collapse, hitsAsGrid }) { const ref = createRef() const [query, setQuery] = useState(``) @@ -309,7 +309,7 @@ export default function Search({ indices, collapse, hitsAsGrid }) { `Search` returns JSX that renders a dynamic array of `indices` passed as a prop. Each array item should be an object with keys `name`, `title`, `hitComp` that specifies the name of the index in your Algolia account to be queried, the title to display above the results shown to the user and the component `hitComp` that renders the data returned for each match. -```js:title=src/components/search/index.js +```jsx:title=src/components/search/index.js return ( ({ hit }) => ( Now all you need to do is import `Search` somewhere. The obvious place is the `Header` component so add it there. -```js:title=src/components/Header/index.js +```jsx:title=src/components/Header/index.js import React from "react" import { Container, Logo } from "./styles" @@ -586,12 +586,12 @@ Note that this is where you define your array of search indices and pass it as a If everything works as expected, running `gatsby develop` should now give you some instant search magic looking something like in the video below! You can also play around with it [here](https://janosh.io/blog). -`youtube: Amsub4xJ3Jc` +https://youtu.be/Amsub4xJ3Jc ## Additional Resources If you have any issues or if you want to learn more about using Algolia for search, check out this tutorial from Jason Lengstorf: -`youtube: VSkXyuXzwlc` +https://youtu.be/VSkXyuXzwlc You can also find stories of companies using Gatsby + Algolia together [in the Algolia section of the blog](/blog/tags/algolia). diff --git a/docs/docs/adding-search-with-js-search.md b/docs/docs/adding-search-with-js-search.md index 72b2b6c6714d4..e0b00dbf24309 100644 --- a/docs/docs/adding-search-with-js-search.md +++ b/docs/docs/adding-search-with-js-search.md @@ -52,7 +52,7 @@ And finally, as you go through the code, be mindful it does not adhere to the be Start by creating a file named `SearchContainer.js` in the `src/components/` folder, then add the following code to get started: -```javascript +```jsx:title=src/components/SearchContainer.js import React, { Component } from "react" import Axios from "axios" import * as JsSearch from "js-search" @@ -253,7 +253,7 @@ Breaking down the code into smaller parts: In order to get it working in your site, you would only need to import the newly created component to a page. As you can see [in the example site](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-js-search/src/pages/index.js). -Run `gatsby develop` and if all went well, open your browser of choice and enter the url `http://localhost:8000` - you'll have a fully functional search at your disposal. +Run `gatsby develop` and if all went well, open your browser of choice and enter the url - you'll have a fully functional search at your disposal. ## JS-Search with a big dataset @@ -263,7 +263,7 @@ To do this, some changes are required. Start by modifying the `gatsby-node.js` file by adding the following code: -```javascript +```javascript:title=gatsby-node.js const path = require("path") const axios = require("axios") @@ -309,7 +309,7 @@ exports.createPages = ({ actions }) => { Create a file named `ClientSearchTemplate.js` in the `src/templates/` folder, then add the following code to get started: -```javascript +```jsx:title=src/templates/ClientSearchTemplate.js import React from "react" import ClientSearch from "../components/ClientSearch" @@ -334,7 +334,7 @@ export default SearchTemplate Create a file named `ClientSearch.js` in the `src/components/` folder, then add the following code as a baseline: -```javascript +```jsx:title=src/components/ClientSearch.js import React, { Component } from "react" import * as JsSearch from "js-search" @@ -571,7 +571,7 @@ Once again to get it to work on your site you would only need to copy over [the And both the [template](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-js-search/src/templates/ClientSearchTemplate.js) and the [search component](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-js-search/src/components/ClientSearch.js). -Issuing `gatsby develop` again, and if all went without any issues one more time, open your browser of choice and enter the url `http://localhost:8000/search`, you'll have a fully functional search at your disposal coupled with Gatsby API. +Issuing `gatsby develop` again, and if all went without any issues one more time, open your browser of choice and enter the url , you'll have a fully functional search at your disposal coupled with Gatsby API. Hopefully this rather extensive guide has shed some insights on how to implement client search using js-search. diff --git a/docs/docs/adding-search.md b/docs/docs/adding-search.md index ae0405676dfd1..e1eb3cad059a0 100644 --- a/docs/docs/adding-search.md +++ b/docs/docs/adding-search.md @@ -39,9 +39,9 @@ Now that you know the three required components, there are a few ways to approac Using an open source search engine is always free and allows you to enable offline search for your site. Note that you need to be careful with offline search because the entire search index has to be brought into the client, which can affect the bundle size significantly. -Open source libraries like [`elasticlunr`](https://www.npmjs.com/package/elasticlunr) or [`js-search`](https://github.com/bvaughn/js-search) can be used to enable search for your site. +Open source libraries like [`elasticlunr`](https://www.npmjs.com/package/elasticlunr), [`flexsearch`](https://github.com/nextapps-de/flexsearch) or [`js-search`](https://github.com/bvaughn/js-search) can be used to enable search for your site. -Doing so will require you to create a search index when your site is built. For [`elasticlunr`](https://www.npmjs.com/package/elasticlunr), there is a plugin called [`gatsby-plugin-elasticlunr-search`](https://github.com/gatsby-contrib/gatsby-plugin-elasticlunr-search) that creates a search index automatically. +Doing so will require you to create a search index when your site is built. For [`elasticlunr`](https://www.npmjs.com/package/elasticlunr), there is a plugin called [`gatsby-plugin-elasticlunr-search`](https://github.com/gatsby-contrib/gatsby-plugin-elasticlunr-search) that creates a search index automatically. For [`flexsearch`](https://github.com/nextapps-de/flexsearch) there is a plugin called [`gatsby-plugin-flexsearch`](https://github.com/tmsss/gatsby-plugin-flexsearch). For other libraries, you can use a combination of [`onCreateNode`](/docs/node-apis/#onCreateNode), [`setFieldsOnGraphQLNodeType`](/docs/node-apis/#setFieldsOnGraphQLNodeType) and [`sourceNodes`](/docs/node-apis/#sourceNodes) from the Gatsby node API to create the search index and make it available in GraphQL. For more info on how to do this check out [`gatsby-plugin-elasticlunr-search`'s source code](https://github.com/gatsby-contrib/gatsby-plugin-elasticlunr-search/blob/master/src/gatsby-node.js#L96-L131). diff --git a/docs/docs/adding-tags-and-categories-to-blog-posts.md b/docs/docs/adding-tags-and-categories-to-blog-posts.md index a8788f17c7545..840cf89219010 100644 --- a/docs/docs/adding-tags-and-categories-to-blog-posts.md +++ b/docs/docs/adding-tags-and-categories-to-blog-posts.md @@ -19,7 +19,7 @@ The process will essentially look like this: You add tags by defining them in the `frontmatter` of your Markdown file. The `frontmatter` is the area at the top surrounded by dashes that includes post data like the title and date. -```md +```markdown --- title: "A Trip To the Zoo" --- @@ -29,7 +29,7 @@ I went to the zoo today. It was terrible. Fields can be strings, numbers, or arrays. Since a post can usually have many tags, it makes sense to define it as an array. Here you add your new tags field: -```md +```markdown --- title: "A Trip To the Zoo" tags: ["animals", "Chicago", "zoos"] diff --git a/docs/docs/adding-website-functionality.md b/docs/docs/adding-website-functionality.md deleted file mode 100644 index 3c92a7164935f..0000000000000 --- a/docs/docs/adding-website-functionality.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Adding Website Functionality -overview: true ---- - -Gatsby empowers developers and creators to make a diverse amount of websites. One may wish to add additional functionality to their site such as search, authentication, forms, comments, and plenty of others. In this section, you will find a showcase of guides and concepts on how to level up your site. - - diff --git a/docs/docs/api-files-gatsby-config.md b/docs/docs/api-files-gatsby-config.md index 81c3d325d8c1e..699550e5f96cb 100644 --- a/docs/docs/api-files-gatsby-config.md +++ b/docs/docs/api-files-gatsby-config.md @@ -100,7 +100,7 @@ module.exports = { } ``` -### Mixed plugins +#### Mixed plugins You can add plugins with and without options in the same array. Your site's config file could look like this: diff --git a/docs/docs/api-files-gatsby-node.md b/docs/docs/api-files-gatsby-node.md index 10acbec50a1a7..9a1014c3ba65f 100644 --- a/docs/docs/api-files-gatsby-node.md +++ b/docs/docs/api-files-gatsby-node.md @@ -6,10 +6,10 @@ Code in the file `gatsby-node.js` is run once in the process of building your si Every Gatsby Node API passes a [set of Node API helpers](/docs/node-api-helpers/). These let you access several methods like reporting, or perform actions like creating new pages. -```jsx:title=gatsby-node.js +```js:title=gatsby-node.js const path = require(`path`) // Log out information after a build is done -exports.onPostBuild = ({reporter}) => { +exports.onPostBuild = ({ reporter }) => { reporter.info(`Your Gatsby site has been built!`) } // Create blog pages dynamically @@ -27,13 +27,13 @@ exports.createPages = async ({ graphql, actions }) => { } } } - ` + `) result.data.allSamplePages.edges.forEach(edge => { createPage({ path: `${edge.node.slug}`, component: blogPostTemplate, context: { - title: edge.node.title + title: edge.node.title, }, }) }) diff --git a/docs/docs/api-proxy.md b/docs/docs/api-proxy.md index bfda15aad77e3..7d1517b7faa58 100644 --- a/docs/docs/api-proxy.md +++ b/docs/docs/api-proxy.md @@ -14,7 +14,7 @@ backend implementation. To tell the development server to proxy any unknown requests to your API server in development, add a `proxy` field to your `gatsby-config.js`, for example: -```js:title=gatsby-config.js +```javascript:title=gatsby-config.js module.exports = { proxy: { prefix: "/api", @@ -23,6 +23,23 @@ module.exports = { } ``` +or: + +```js:title=gatsby-config.js +module.exports = { + proxy: [ + { + prefix: "/api", + url: "http://dev-mysite.com", + }, + { + prefix: "/api2", + url: "http://dev2-mysite.com", + }, + ], +} +``` + This way, when you `fetch('/api/todos')` in development, the development server will recognize that it’s not a static asset, and will proxy your request to `http://dev-mysite.com/api/todos` as a fallback. diff --git a/docs/docs/api-reference.md b/docs/docs/api-reference.md index 5947b29d2898d..b1ac0fb17f607 100644 --- a/docs/docs/api-reference.md +++ b/docs/docs/api-reference.md @@ -3,6 +3,6 @@ title: Gatsby API Reference overview: true --- -Learn more about Gatsby APIs and configuration. +Learn more about Gatsby API methods and options, common files, and customizations. diff --git a/docs/docs/api-specification.md b/docs/docs/api-specification.md index d79f258d5f59b..8e560c300db55 100644 --- a/docs/docs/api-specification.md +++ b/docs/docs/api-specification.md @@ -55,9 +55,9 @@ in some of its data fields. See [the full list of (official only for now — adding support for community plugins later) plugins](/docs/plugins/). -# API +## API -## Concepts +### Concepts - _Page_ — a site page with a pathname, a template component, and optional GraphQL query. @@ -78,7 +78,7 @@ See _More definitions and terms are defined in the [Glossary](/docs/glossary/)_ -## Operators +### Operators - _Create_ — make a new thing - _Get_ — get an existing thing @@ -86,7 +86,7 @@ _More definitions and terms are defined in the [Glossary](/docs/glossary/)_ - _Replace_ — replace an existing thing - _Set_ — merge into an existing thing -## Extension APIs +### Extension APIs Gatsby has multiple processes. The most prominent is the "bootstrap" process. It has several subprocesses. One tricky part to their design is that they run both diff --git a/docs/docs/audit-with-lighthouse.md b/docs/docs/audit-with-lighthouse.md index 5862650860839..d10122a2d43b6 100644 --- a/docs/docs/audit-with-lighthouse.md +++ b/docs/docs/audit-with-lighthouse.md @@ -10,7 +10,7 @@ Lighthouse is included in Chrome DevTools. Running its audit -- and then address If you haven't yet, you need to create a production build of your Gatsby site. The Gatsby development server is optimized for making development fast, but the site that it generates, while closely resembling a production version of the site, isn't as optimized. -### Create a production build +## Create a production build 1. Stop the development server (if it's still running) and run: @@ -28,7 +28,7 @@ gatsby serve Once this starts, you can now view your site at `localhost:9000`. -### Run a Lighthouse audit +## Run a Lighthouse audit Now run your first Lighthouse test. diff --git a/docs/docs/awesome-gatsby-resources.md b/docs/docs/awesome-gatsby-resources.md index ac6ebf8574917..c79d0808079cd 100644 --- a/docs/docs/awesome-gatsby-resources.md +++ b/docs/docs/awesome-gatsby-resources.md @@ -16,6 +16,10 @@ See the [library of official and community starters](/starters/) See the [library of official and community plugins](/plugins/) +## Themes + +See the [unofficial list of themes](https://gatsbytemplates.io/) + ## Tools - [Develop & Build GatsbyJS static sites within Docker](https://github.com/aripalo/gatsby-docker/) @@ -85,6 +89,8 @@ See the [library of official and community plugins](/plugins/) - [Gatsby - Full Tutorial for Beginners](https://www.youtube.com/watch?v=mHFAM0CXviE) - [Building a Video Blog with Gatsby and Markdown (MDX)](https://scotch.io/tutorials/building-a-video-blog-with-gatsby-and-markdown-mdx) - [Deploying Your First Gatsby Site to Netlify](https://scotch.io/tutorials/deploying-your-first-gatsby-site-to-netlify) +- [Add a chat widget to your Gatsby blog](https://pusher.com/tutorials/chat-gatsby/) +- [Headless WordPress: Why Gatsby Should Be Next on Your List of Things to Learn](https://deliciousbrains.com/gatsby-headless-wordpress/) ### German diff --git a/docs/docs/babel.md b/docs/docs/babel.md index 6829dece1f6f7..218507c184fed 100644 --- a/docs/docs/babel.md +++ b/docs/docs/babel.md @@ -10,8 +10,8 @@ support for writing modern JavaScript — while still supporting older browsers. Gatsby supports by default the last two versions of major browsers, IE 9+, as well as any browser that still has 1%+ browser share. -This means we automatically compile your JavaScript to ensure it works on older browsers. -We also automatically add polyfills as needed — no more shipping code which mysteriously +This means that your JavaScript is automatically compiled to ensure it works on older browsers. +Polyfills are also automatically added — no more shipping code which mysteriously breaks on older browsers! If you only target newer browsers, see the [Browser diff --git a/docs/docs/basic-hardware-software-requirements.md b/docs/docs/basic-hardware-software-requirements.md index 302b65bee6d58..4c125f9528397 100644 --- a/docs/docs/basic-hardware-software-requirements.md +++ b/docs/docs/basic-hardware-software-requirements.md @@ -4,5 +4,4 @@ title: Basic Hardware and Software Requirements This is a stub. Help our community expand it. -Please use the [Gatsby Style Guide](/contributing/gatsby-style-guide/) to ensure your -pull request gets accepted. +Please use the [Gatsby Style Guide](/contributing/gatsby-style-guide/) to ensure your pull request gets accepted. diff --git a/docs/docs/browser-support.md b/docs/docs/browser-support.md index daf07498573e5..018e5aa3c1504 100644 --- a/docs/docs/browser-support.md +++ b/docs/docs/browser-support.md @@ -35,12 +35,9 @@ Browserslist — https://css-tricks.com/browserlist-good-idea/ By default, Gatsby emulates the following config: -```javascript:title=package.json +```json:title=package.json { - "browserslist": [ - ">0.25%", - "not dead" - ] + "browserslist": [">0.25%", "not dead"] } ``` diff --git a/docs/docs/building-a-contact-form.md b/docs/docs/building-a-contact-form.md index a87db9101bd38..4d95f916a96d6 100644 --- a/docs/docs/building-a-contact-form.md +++ b/docs/docs/building-a-contact-form.md @@ -43,6 +43,33 @@ Each method detailed below will start with the following contact form: ## Form submission options in Gatsby +### Getform + +Getform is a form backend platform which offers a free-plan for handling form submissions on static sites. Begin by creating a form on your Gatsby site that you can receive submissions from. When creating the form, direct the HTTP POST method to the Getform, by placing the `name` attributes for the fields you want to make visible. (name, email, message etc.) + +```jsx:title=src/pages/contact.js +
+ ... + + + + ... +
+``` + +Once you've made the code changes to your form, you can head over to the contact page on your site and start submitting data to the form. The submissions will then be visible on the Getform dashboard. You can add multiple email addresses to receive email notifications for the forms created, as well as manipulate the data you see on Getform using Zapier and Webhooks options that are offered. + +You can find more info on the registration process and form setup on the [Getform website](https://getform.io/) and find code examples (AJAX, reCAPTCHA etc) on their [Codepen](https://codepen.io/getform). + ### Netlify If you're hosting your site with Netlify, you gain access to their excellent [form handling feature](https://www.netlify.com/docs/form-handling/). @@ -85,7 +112,7 @@ All forms set up in this way come with reCAPTCHA by default, but you can also en ``` -Because the input is hidden, Formspree will know that only a bot could have made the submission, and it will be silently ignore it! +Because the input is hidden, Formspree will know that only a bot could have made the submission and it will be silently ignored! ### Run your own server @@ -147,4 +174,4 @@ For an in-depth guide on running your own mail server, you can refer to [this aw If you have any issues or if you want to learn more about implementing your own contact form in Gatsby, check out this tutorial from Scott Tolinski: -`youtube: hF7xJhzrr9s` +https://youtu.be/hF7xJhzrr9s diff --git a/docs/docs/building-a-site-with-authentication.md b/docs/docs/building-a-site-with-authentication.md index a0baa1a3a2e20..aa3d6cafd8cb7 100644 --- a/docs/docs/building-a-site-with-authentication.md +++ b/docs/docs/building-a-site-with-authentication.md @@ -2,33 +2,84 @@ title: Building a Site with Authentication --- -With Gatsby, you are able to create restricted areas in your app. For that, you -must use the concept of [client-only routes](/docs/building-apps-with-gatsby/#client-only-routes). +Many sites require users to be authenticated in order to protect private data. -Using the [@reach/router](https://reach.tech/router/) library, which comes -installed with Gatsby, you can control which component will be loaded when a -certain route is called, and check for the authentication state before serving -the content. +## Understanding authentication between client and server -## Prerequisites +In many modern websites, the [client](/docs/glossary#client-side) -- or [frontend](/docs/glossary#frontend) -- is [decoupled](/docs/glossary#decoupled) from the [backend](/docs/glossary#backend). This pattern is how Gatsby functions to combine data from a myriad of backend sources to facilitate building the frontend. -You must know how to set up a basic Gatsby project. If you need to, check the -[main tutorial](/tutorial). +In order to provide authentication functionality, another service has to be leveraged and connected to Gatsby. There are many open source technologies than can provide this functionality. Examples include: -## Setting the authentication workflow +- A Node.js app using Passport.js +- A Ruby on Rails API using Devise -To create a common authentication workflow, you can usually follow these steps: +Another option are third party technologies like: -- [Create client-only routes](/tutorial/authentication-tutorial/#creating-client-only-routes), - to tell Gatsby which routes should be rendered on demand -- [Wrap private content in a PrivateRoute component](/tutorial/authentication-tutorial/#controlling-private-routes), - to check if a user is authenticated or not, therefore rendering the content or - redirecting to another page (usually, the login page) +- Firebase +- Auth0 +- AWS Amplify +- Netlify Identity + +These tools follow a process in order to verify a user on the client against an authentication service. The service returns a token that the client can use to access protected data. This diagram visualizes the process: + +![Diagram of Gatsby using an authentication service to get data from an API](./images/basic-auth.png) + +1. First, a request is made from a Gatsby site (the client) to an authentication service to perform an action like register a new user or login. + +2. If the credentials (like a username and password) provided from the client match a user in the authentication service, it returns a token (like a JSON Web Token, abbreviated as JWT) so the user has a key they can use to prove they are who they say they are. The user data returned can be stored in the Gatsby app by passing it to components using a Provider component with the React Context API and [`wrapRootElement` API](/docs/browser-apis/#wrapRootElement) from Gatsby. + +3. With the key, the client can make a request to an external data source like an API (the server) where protected data is stored. The key is unique to a specific user and allows the client to access their specific data. + +4. The server returns data back to the client that it can use to pass information into components. + +_**Note**: this is the same pattern that other sites built with React (like Create React App) would need to follow._ + +## Implementing authentication in a Gatsby site + +There are a few things to be aware of when implementing authentication in a Gatsby site, because of how Gatsby uniquely builds pages and renders static assets with dynamic capabilities. + +### Setting up client-only routes + +With Gatsby, you are able to create restricted areas in your app using [client-only routes](/docs/building-apps-with-gatsby/#client-only-routes). + +Gatsby is a little [different from a traditional React app](/docs/adding-app-and-website-functionality/#differences-between-gatsby-and-other-react-apps) in how its routes and pages are created. Because static HTML files generated by Gatsby sit on a file server, you cannot programmatically control access to those files (for example: a user could guess or type in a URL and navigate straight to the page). As the [section from the Adding App and Website functionality](/docs/adding-app-and-website-functionality/#client-only-routes) overview page demonstrates, client-only routes can be created to route a user between pages using a React-based router, as opposed to navigating between different static HTML files on a server. + +Taking advantage of this client-side routing allows you to protect or customize your routes. Using the [`@reach/router` library](https://reach.tech/router/), which comes installed with Gatsby, you can set up a router on a page and control which component loads when a certain route is called, and check for the existence of a variable like authentication state before serving the content. + + +```jsx + + {isAuthenticated ? : } + +``` + +More specific code examples for this pattern are outlined in the [Client-only Routes & User Authentication guide](/docs/client-only-routes-and-user-authentication/#implementing-client-only-routes). + +### Protecting code from accessing browser globals during build + +Global objects that are accessible in the browser like `localStorage` aren't available while a Gatsby site is building, because the build runs in a Node.js environment. + +However, some third party services might try and access `localStorage` or the `window` object with internal methods. To keep those snippets from breaking the build, those invocations should be wrapped in checks or `useEffect` hooks to verify that the code is running in the browser and is skipped during the build process: + +```javascript +import app from "firebase/app" + +... + +if (typeof window !== 'undefined') { // highlight-line + app.initializeApp(config) +} // highlight-line +``` + +More information on build related errors is available in the guide on [debugging HTML builds](/docs/debugging-html-builds/). ## Real-world example: Gatsby store -The [Gatsby store](https://github.com/gatsbyjs/store.gatsbyjs.org) uses this -approach when handling a private route: +The [Gatsby store](https://github.com/gatsbyjs/store.gatsbyjs.org) is a live application built with Gatsby that implements authentication using Auth0. + +[Util functions](https://github.com/gatsbyjs/store.gatsbyjs.org/blob/master/src/utils/auth.js) in the Gatsby Store repo make use of Auth0's APIs to authenticate users with GitHub, and wrap Auth0's APIs to check that [some of the Auth0 code runs only in the browser](https://github.com/gatsbyjs/store.gatsbyjs.org/blob/master/src/utils/auth.js#L3). + +In order to protect authenticated content with a private route, a `` is implemented in the `` component that checks whether a user is authenticated or reroutes them to `/login`. ```jsx // import ... @@ -51,14 +102,16 @@ const PrivateRoute = ({ component: Component, ...rest }) => { } ``` +This private route pattern is also covered in the [tutorial on making a site with authentication](/tutorial/authentication-tutorial/#controlling-private-routes). + ## Further reading If you want more information about authenticated areas with Gatsby, this (non-exhaustive list) may help: -- [Making a site with user authentication](/tutorial/authentication-tutorial), a Gatsby advanced tutorial -- [Gatsby repo simple auth example](https://github.com/gatsbyjs/gatsby/tree/master/examples/simple-auth) +- [Making a site with user authentication](/tutorial/authentication-tutorial), an advanced Gatsby tutorial +- [Gatsby repo "simple auth" example](https://github.com/gatsbyjs/gatsby/tree/master/examples/simple-auth) +- [Live version of the "simple auth" example](https://simple-auth.netlify.com/) - [A Gatsby email _application_](https://github.com/DSchau/gatsby-mail), using React Context API to handle authentication -- [The Gatsby store for swag and other Gatsby goodies](https://github.com/gatsbyjs/store.gatsbyjs.org) - [Add Authentication to your Gatsby apps with Auth0](/blog/2019-03-21-add-auth0-to-gatsby-livestream/) (livestream with Jason Lengstorf) - [Add Authentication to your Gatsby apps with Okta](https://www.youtube.com/watch?v=7b1iKuFWVSw&t=9s) - [Other authentication-related posts on the Gatsby blog](/blog/tags/authentication/) diff --git a/docs/docs/building-an-e-commerce-site.md b/docs/docs/building-an-e-commerce-site.md index 87ddc4f2c9528..6e48ffcc1cab4 100644 --- a/docs/docs/building-an-e-commerce-site.md +++ b/docs/docs/building-an-e-commerce-site.md @@ -1,11 +1,11 @@ --- -title: Building an E-commerce Site +title: Building an e-commerce Site --- -The speed and performance of sites built with Gatsby make it a great tool for building E-commerce sites. There are existing plugins for connecting services like [Shopify](/packages/gatsby-source-shopify/) and [Snipcart](/packages/gatsby-plugin-snipcart/) to Gatsby, and this section contains reference guides to help get things setup. +The speed and performance of sites built with Gatsby make it a great tool for building e-commerce sites. There are existing plugins for connecting services like [Shopify](/packages/gatsby-source-shopify/) and [Snipcart](/packages/gatsby-plugin-snipcart/) to Gatsby, and this section contains reference guides to help get things setup. -To see examples of E-commerce sites built with Gatsby, check out the [showcase](/showcase/?filters%5B0%5D=eCommerce). +To see examples of e-commerce sites built with Gatsby, check out the [showcase](/showcase/?filters%5B0%5D=eCommerce). -_You can also check out the ["Making an E-commerce Site with Stripe" tutorial](/tutorial/ecommerce-tutorial/) for more information._ +_You can also check out the ["Making an e-commerce Site with Stripe" tutorial](/tutorial/ecommerce-tutorial/) for more information._ diff --git a/docs/docs/building-an-ecommerce-site-with-shopify.md b/docs/docs/building-an-ecommerce-site-with-shopify.md index 2611b6c5afb92..f55cbbac51a91 100644 --- a/docs/docs/building-an-ecommerce-site-with-shopify.md +++ b/docs/docs/building-an-ecommerce-site-with-shopify.md @@ -44,7 +44,7 @@ plugins: [ ## Querying Shopify data and listing products -Open the Gatsby GraphiQL interface by visiting `http://localhost:8000/___graphql`. With at least one example product added into Shopify you should see several new types of nodes in the Explorer tab, like `allShopifyProduct`. To query all products in your store sorted by title, try running the query: +Open the Gatsby GraphiQL interface by visiting . With at least one example product added into Shopify you should see several new types of nodes in the Explorer tab, like `allShopifyProduct`. To query all products in your store sorted by title, try running the query: ```graphql { diff --git a/docs/docs/building-apps-with-gatsby.md b/docs/docs/building-apps-with-gatsby.md deleted file mode 100644 index 5a80cdb6f5b89..0000000000000 --- a/docs/docs/building-apps-with-gatsby.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Building Apps with Gatsby ---- - -Gatsby is an excellent framework for building web apps. You can use Gatsby to create personalized, logged-in experiences with two different approaches. - -1. "hybrid" app pages, and -2. client-only routes & user authentication - -## Hybrid app pages - -When a visitor lands on a Gatsby page, the page's HTML file is loaded first, then the JavaScript bundle; When your React components load in the browser, they can fetch and render data from APIs. - -> 💡 The [React docs](https://reactjs.org/docs/faq-ajax.html) have a great, straightforward example demonstrating this approach. - -Some examples of how you could apply this: - -- A news site with live data like sports scores or the weather -- An e-commerce site with universal product pages and category pages, but also personalized recommendation sections - -You can also use your React components to create interactive widgets e.g. allow a user to do searches or submit forms. Because Gatsby is just React, it's easy to blend static and interactive/dynamic models of building web sites. - -## Client-only routes & user authentication - -Often you want to create a site with client-only routes that are gated by authentication. For more on this approach, check out the reference guide on [client-only routes and authentication](/docs/client-only-routes-and-user-authentication/). diff --git a/docs/docs/building-with-components.md b/docs/docs/building-with-components.md index 4e7e5edfc6377..d72ce3144cfd7 100644 --- a/docs/docs/building-with-components.md +++ b/docs/docs/building-with-components.md @@ -2,8 +2,6 @@ title: Building with Components --- -import LayerModel from "../../www/src/components/layer-model" - To use Gatsby, you will need a basic understanding of React components. The [official tutorial](https://reactjs.org/tutorial/tutorial.html) @@ -30,7 +28,7 @@ Everything in Gatsby is built using components. A basic directory structure of a project might look like this: -``` +```text . ├── gatsby-config.js ├── package.json @@ -157,7 +155,7 @@ function HTML(props) { {props.headComponents} - + {css} diff --git a/docs/docs/bulma.md b/docs/docs/bulma.md index 1e607afbbae24..8c0659010fe57 100644 --- a/docs/docs/bulma.md +++ b/docs/docs/bulma.md @@ -6,7 +6,7 @@ title: Bulma This guide assumes that you have a Gatsby project set up. If you need to set up a project, head to the [**Quick Start guide**](/docs/quick-start), then come back. -### Installation +## Installation For starters, lets install all the required packages we're going to need. @@ -18,11 +18,11 @@ Then add the `gatsby-plugin-sass` in to `gatsby-config.js`. plugins: [`gatsby-plugin-sass`], ``` -### File for styles +## File for styles Now is the time to create a scss-file that holds your simple style customisation and the import statement for bulma. -(To keep things simple, insert the file next to index.js in the pages-directory) +(To keep things simple, insert the file next to `index.js` in the pages-directory) ```scss:title=mystyles.scss @charset "utf-8"; @@ -33,13 +33,13 @@ $title-color: #ff0000; @import "~bulma/bulma.sass"; ``` -### Using Bulma +## Using Bulma The last step is to import the style and use it. -Replace the default contents of the index.js file. +Replace the default contents of the `index.js` file. -```javascript:title=index.js +```jsx:title=index.js import React from "react" import "./mystyles.scss" @@ -66,6 +66,6 @@ export default IndexPage And that's all there is to it! Now you can use Bulma as you normally would. -### Resources +## Resources - [Bulma documentation on how to use sass](https://bulma.io/documentation/customize/with-node-sass/) diff --git a/docs/docs/caching.md b/docs/docs/caching.md index 36cb81ff35dc2..6e49e14b3e7c5 100644 --- a/docs/docs/caching.md +++ b/docs/docs/caching.md @@ -51,4 +51,7 @@ When deploying with Now, follow the instructions in the [Now documentation](http --- -1 It's important that you use the combination of `max-age=0` and `must-revalidate` instead of using `no-cache`. This allows the CDN to store copies of the files on the servers closest to your users and only download a new version from the origin server in the event that the files have changed. Using `no-cache`, on the other hand, decreases performance because it forces the CDN to download a new copy of the file from the origin server on every request. +1 You can use 'no-cache' instead of 'max-age=0, must-revalidate'. Despite what the name might imply, 'no-cache' permits a cache to serve cached content as long as it validates the cache freshness first. [2][3] In either case, clients have to make a round trip to the origin server on each request. However, if you are correctly utilizing ETags or Last-Modified validation you will avoid downloading assets when the cached copy is still valid (e.g. the file hasn't changed on the origin server since it was cached). + +[2]: https://tools.ietf.org/html/rfc7234#section-5.2.2.1 +[3]: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#no-cache_and_no-store diff --git a/docs/docs/cheat-sheet.md b/docs/docs/cheat-sheet.md index e236e2a12f9df..91dad8bd901c7 100644 --- a/docs/docs/cheat-sheet.md +++ b/docs/docs/cheat-sheet.md @@ -157,7 +157,7 @@ Get the PDF: gatsby-cheat-sheet.pdf-p, --port

-

Set port. Defaults to 8000

+

Set port. Defaults to env.PORT or 8000

diff --git a/docs/docs/client-data-fetching.md b/docs/docs/client-data-fetching.md deleted file mode 100644 index c8166cbc54304..0000000000000 --- a/docs/docs/client-data-fetching.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: Client Data Fetching ---- - -## Context - -This article touches on how to fetch data at both _build time_ and _run time_. It uses the plugin [`gatsby-source-graphql`](/packages/gatsby-source-graphql/) to fetch data at [build time](/docs/glossary#build) on the server, while it uses the [`axios`](https://github.com/axios/axios) package to fetch different data on the [client-side](/docs/glossary#client-side) when the page loads. - -When this article mentions [hydration](/docs/glossary#hydration), it means that Gatsby (through React.js) builds static files to render server-side. When Gatsby's script bundle downloads and executes in the browser, it preserves the HTML markup built by Gatsby and turns the site into a full React web application that can manipulate the [DOM](/docs/glossary#dom). The result of this process creates fast loading pages and a nice user experience. - -Compiling pages at [build-time](/docs/glossary#build) is useful when your website content won't change often, or when triggering a build process to recompile works fine. However, some websites with more dynamic needs require a [client-side](/docs/glossary#client-side) [runtime](/docs/glossary#runtime) to handle constantly changing content after the page loads, like a chat widget or an email client web application. - -## Combining build-time and client run-time data - -Because a Gatsby site [hydrates](/docs/glossary#hydration) into a React app after loading statically, Gatsby is not just for static sites. You can also fetch data dynamically on the client-side as needed, like you would with any other React app. - -To illustrate this, check out a small example site that uses both Gatsby's data layer at build-time and data on the client at run-time. This example is based loosely on Jason Lengstorf's [Gatsby with Apollo](https://github.com/jlengstorf/gatsby-with-apollo) example. You'll be fetching character data for Rick (of Rick and Morty) and a random pupper image. - -> Note: Check out the [full example here](https://github.com/amberleyromo/gatsby-client-data-fetching), if helpful. - -### 1. Create a Gatsby page component - -No data yet. Just the basic React page that you'll be populating. - -```jsx:title=index.js -import React, { Component } from "react" -import { graphql } from "gatsby" - -class ClientFetchingExample extends Component { - render() { - return ( -
-

Image of Rick

-

This will come from a build time query

- -

Image of Rick's pupper

-

This will come from a request on the client

-
- ) - } -} - -export default ClientFetchingExample -``` - -### 2. Query for character info at build time - -To query for Rick's character info and image, you'll use the `gatsby-source-graphql` plugin. This will allow you to query the Rick and Morty API using Gatsby queries. - -> Note: To learn more about using [`gatsby-source-graphql`](/packages/gatsby-source-graphql/), or about [Gatsby's GraphQL data layer](/docs/graphql/), check out their respective docs. The purpose of including it here is only for comparison. - -```javascript:title=gatsby-config.js -module.exports = { - plugins: [ - { - resolve: "gatsby-source-graphql", - options: { - typeName: "RMAPI", - fieldName: "rickAndMorty", - url: "https://rickandmortyapi-gql.now.sh/", - }, - }, - ], -} -``` - -Now you can add the query to your `index.js` page: - -```jsx:title=index.js -import React, { Component } from "react" -import { graphql } from "gatsby" - -// highlight-start -// This query is executed at build time by Gatsby. -export const GatsbyQuery = graphql` - { - rickAndMorty { - character(id: 1) { - name - image - } - } - } -` -// highlight-end - -class ClientFetchingExample extends Component { - render() { - // highlight-start - const { - rickAndMorty: { character }, - } = this.props.data - // highlight-end - - return ( -
- // highlight-start -

{character.name} With His Pupper

-

Rick & Morty API data loads at build time.

-
- {character.name} -
- // highlight-end -

Image of Rick's pupper

-

This will come from a request on the client

-
- ) - } -} - -export default ClientFetchingExample -``` - -### 3. Fetch pupper info and image data on the client - -Now you'll finish out by fetching pupper info from the [Dog CEO Dog API](https://dog.ceo/dog-api/). (You'll fetch a random pupper. Rick isn't picky.) - -```jsx:title=index.js -import React, { Component } from "react" -import { graphql } from "gatsby" -import axios from "axios" // highlight-line - -// This query is executed at build time by Gatsby. -export const GatsbyQuery = graphql` - { - rickAndMorty { - character(id: 1) { - name - image - } - } - } -` - -class ClientFetchingExample extends Component { - // highlight-start - state = { - loading: false, - error: false, - pupper: { - img: "", - breed: "", - }, - } - // highlight-end - - // highlight-start - componentDidMount() { - this.fetchRicksPupper() - } - // highlight-end - - render() { - const { - rickAndMorty: { character }, - } = this.props.data - - const { img, breed } = this.state.pupper // highlight-line - - return ( -
-

{character.name} With His Pupper

-

Rick & Morty API data loads at build time.

-

Dog API data loads at run time.

// highlight-line -
- {character.name} -
- {/* highlight-start */} -
- {this.state.loading ? ( -

Please hold, pupper incoming!

- ) : img && breed ? ( - <> -

{`${breed} pupper!`}

- {`cute - - ) : ( -

Oh noes, error fetching pupper :(

- )} -
-
{/* highlight-end */} - ) - } - - // This data is fetched at run time on the client. // highlight-start - fetchRicksPupper = () => { - this.setState({ loading: true }) - - axios - .get(`https://dog.ceo/api/breeds/image/random`) - .then(pupper => { - const { - data: { message: img }, - } = pupper - const breed = img.split("/")[4] - - this.setState({ - loading: false, - pupper: { - ...this.state.pupper, - img, - breed, - }, - }) - }) - .catch(error => { - this.setState({ loading: false, error }) - }) - } -} // highlight-end - -export default ClientFetchingExample -``` - -That's it -- an example of querying for data at build time using the Gatsby GraphQL data layer and dynamically requesting data on the client at run time. - -## Other resources - -You may be interested to check out other projects (both used in production and proof of concepts) that illustrate this usage: - -- [Gatsby store](https://github.com/gatsbyjs/store.gatsbyjs.org) -- [Gatsby mail](https://github.com/DSchau/gatsby-mail) diff --git a/docs/docs/client-only-routes-and-user-authentication.md b/docs/docs/client-only-routes-and-user-authentication.md index 94b94e7eb3d43..ca0f573a0abbd 100644 --- a/docs/docs/client-only-routes-and-user-authentication.md +++ b/docs/docs/client-only-routes-and-user-authentication.md @@ -2,15 +2,110 @@ title: Client-only Routes & User Authentication --- -Often you want to create a site with client-only portions that are gated by authentication. +Often you want to create a site with client-only portions, which allows you to gate them by authentication or load different content based on URL parameters. + +## Understanding client-only routes A classic example would be a site that has a landing page, various marketing pages, a login page, and then an app section for logged-in users. The logged-in section doesn't need to be server rendered as all data will be loaded live from your API after the user logs in. So it makes sense to make this portion of your site client-only. -Gatsby uses [@reach/router](https://reach.tech/router/) under the hood. You should use @reach/router to create client-only routes. +Client-only routes will exist on the client only and will not correspond to `index.html` files in an app's built assets. If you'd like site users to be able to visit client routes directly, you need to [set up your site to handle those routes](#handling-client-only-routes-with-gatsby) appropriately. Or, if you have control over the configuration of the file server yourself (instead of using another static file host like Netlify), you can [set up the server](#configuring-and-handling-client-only-routes-on-a-server) to handle these routes. + +A sample site might be set up like this: + +![Site with a static homepage and client-only routes](./images/client-only-routes.png) + +Gatsby converts components in the `pages` folder into static HTML files for the Home page and the App page. A `` is added to the App page so that the profile and details components can be rendered from the App page; they don't have static assets built for them because they exist only on the client. The profile page can `POST` data about a user back to an API, and the details page can dynamically load data about a user with a specific id from an API. + +## Handling client-only routes with Gatsby + +Gatsby uses [@reach/router](https://reach.tech/router/) under the hood, and it is the recommended approach to create client-only routes. + +You first need to set up routes on a page that is built by Gatsby: + +```jsx:title=src/pages/app.js +import React from "react" +import { Router } from "@reach/router" // highlight-line +import Layout from "../components/Layout" +import Profile from "../components/Profile" +import Details from "../components/Details" +import Login from "../components/Login" +import Default from "../components/Default" + +const App = () => { + return ( + + // highlight-start + + +
+ + + + // highlight-end + + ) +} + +export default App +``` + +With routes nested under the `` from Reach Router, it will [render the component from the route that corresponds to the `location`](https://reach.tech/router/api/Router). In the case of the `/app/profile` path, the `Profile` component will be rendered. + +### Adjusting routes to account for authenticated users + +With [authentication set up](/docs/building-a-site-with-authentication) on your site, you can create a component like a `` to extend the example above and gate content: + +```jsx:title=src/pages/app.js +import React from "react" +import { Router } from "@reach/router" +import Layout from "../components/Layout" +import Profile from "../components/Profile" +import Details from "../components/Details" +import Login from "../components/Login" +import Default from "../components/Default" +import PrivateRoute from "../components/PrivateRoute" // highlight-line + +const App = () => { + return ( + + + // highlight-start + + + // highlight-end + + + + + ) +} + +export default App +``` + +The `` component would look something like this one (taken from the [Authentication Tutorial](/tutorial/authentication-tutorial/#controlling-private-routes), which implements this behavior): + +```jsx:title=src/components/PrivateRoute.js +// import ... +import React, { Component } from "react" +import { navigate } from "gatsby" +import { isLoggedIn } from "../services/auth" + +const PrivateRoute = ({ component: Component, location, ...rest }) => { + if (!isLoggedIn() && location.pathname !== `/app/login`) { + navigate("/app/login") + return null + } + + return +} + +export default PrivateRoute +``` -These routes will exist on the client only and will not correspond to index.html files in an app's built assets. If you'd like site users to be able to visit client routes directly, you'll need to set up your server to handle those routes appropriately. +### Configuring pages with `matchPath` -To create client-only routes, add the following code to your site’s `gatsby-node.js` file: +To ensure that users can navigate to client-only routes directly, pages in your site need to have the [`matchPath` parameter](/docs/gatsby-internals-terminology/#matchpath) set. Add the following code to your site’s `gatsby-node.js` file: ```javascript:title=gatsby-node.js // Implement the Gatsby API “onCreatePage”. This is @@ -18,9 +113,10 @@ To create client-only routes, add the following code to your site’s `gatsby-no exports.onCreatePage = async ({ page, actions }) => { const { createPage } = actions - // page.matchPath is a special key that's used for matching pages - // only on the client. + // Only update the `/app` page. if (page.path.match(/^\/app/)) { + // page.matchPath is a special key that's used for matching pages + // with corresponding routes only on the client. page.matchPath = "/app/*" // Update the page. @@ -32,6 +128,34 @@ exports.onCreatePage = async ({ page, actions }) => { > 💡 Note: There's also a plugin to simplify the creation of client-only routes in your site: > [gatsby-plugin-create-client-paths](/packages/gatsby-plugin-create-client-paths/). +The above code (as well as the `gatsby-plugin-create-client-paths` plugin) updates the `/app` page at build time to add the `matchPath` parameter in the page object to make it so that the configured pages (in this case, everything after `/app`, like `/app/dashboard` or `/app/user`) can be navigated to by Reach Router. + +_Without_ this configuration set up, a user that clicks on a link to `/app/user` will instead be routed to the static `/app` page instead of the component or page you have set up at `/app/user`. + > Tip: For applications with complex routing, you may want to override Gatsby's default scroll behavior with the [shouldUpdateScroll](/docs/browser-apis/#shouldUpdateScroll) Browser API. -Check out the ["simple auth" example site](https://github.com/gatsbyjs/gatsby/blob/master/examples/simple-auth/) for a demo implementing user authentication and restricted client-only routes. +## Configuring and handling client-only routes on a server + +If you are hosting on your own server, you can opt to configure the server to handle client-only routes instead of using the `matchPath` method explained above. + +Consider the following router and route to serve as an example: + +```jsx:title=src/pages/app.js + + + +``` + +In this example with a router and a single route for `/app/why-gatsby-is-awesome/`, the server would not be able to complete this request as `why-gatsby-is-awesome` is a client-side route. It does not have a corresponding HTML file on the server. The file found at `/app/index.html` on the server contains all the code to handle the page paths after `/app`. + +A pattern to follow, agnostic of server technology, is to watch for these specific routes and return the appropriate HTML file. + +In this example, when making a `GET` request to `/app/why-gatsby-is-awesome`, the server should respond with `/app/index.html` and let the client handle the rendering of the route with the matching path. It is important to note that the response code should be a **200** (an OK) and not a **301** (a redirect). + +One result of this method is that the client is completely unaware of the logic on the server, decoupling it from Gatsby. + +## Additional resources + +- [Gatsby repo "simple auth" example](https://github.com/gatsbyjs/gatsby/blob/master/examples/simple-auth/) - a demo implementing user authentication and restricted client-only routes +- [Live version of the "simple auth" example](https://simple-auth.netlify.com/) +- [The Gatsby store](https://github.com/gatsbyjs/store.gatsbyjs.org) which also implements an authenticated flow diff --git a/docs/docs/component-libraries.md b/docs/docs/component-libraries.md index a9bc0ab6ac9be..cf72c5d6185ba 100644 --- a/docs/docs/component-libraries.md +++ b/docs/docs/component-libraries.md @@ -4,7 +4,7 @@ title: Creating Component Libraries Component libraries are often used in component-based UI systems like React and Vue. They are typically versioned repositories of components. -IBM's [Carbon Design System](http://carbondesignsystem.com/) and Palantir's [Blueprint](https://blueprintjs.com/) are both good examples. +IBM's [Carbon Design System](https://www.carbondesignsystem.com/) and Palantir's [Blueprint](https://blueprintjs.com/) are both good examples. ## Why component libraries diff --git a/docs/docs/conceptual-guide.md b/docs/docs/conceptual-guide.md index aaea0dbbf3262..f82a4545dd505 100644 --- a/docs/docs/conceptual-guide.md +++ b/docs/docs/conceptual-guide.md @@ -3,6 +3,6 @@ title: Conceptual Guide overview: true --- -Read high-level overviews of the Gatsby approach. +Read high-level overviews of important Gatsby concepts and philosophies. diff --git a/docs/docs/creating-a-local-plugin.md b/docs/docs/creating-a-local-plugin.md index aa8a09b87a906..87266e7da4b39 100644 --- a/docs/docs/creating-a-local-plugin.md +++ b/docs/docs/creating-a-local-plugin.md @@ -6,7 +6,7 @@ If a plugin is only relevant to your specific use-case, or if you’re developin Place the code in the `plugins` folder in the root of your project like this: -``` +```text plugins └── my-own-plugin └── package.json diff --git a/docs/docs/creating-a-sitemap.md b/docs/docs/creating-a-sitemap.md index 6758052bcc9fa..87607b4523ba4 100644 --- a/docs/docs/creating-a-sitemap.md +++ b/docs/docs/creating-a-sitemap.md @@ -17,7 +17,7 @@ Install the package by running the following command: ### How to configure -Once installation is complete, we can now add this plugin to our `gatsby-config.js`, like so: +Once installation is complete, you can now add this plugin to your `gatsby-config.js`, like so: ```javascript:title=gatsby-config.js module.exports = { diff --git a/docs/docs/creating-a-source-plugin.md b/docs/docs/creating-a-source-plugin.md index d5b601c6b3c5b..4572c90eb41ce 100644 --- a/docs/docs/creating-a-source-plugin.md +++ b/docs/docs/creating-a-source-plugin.md @@ -2,62 +2,29 @@ title: Creating a Source Plugin --- -There are two types of plugins that work within Gatsby's data system: "source" -and "transformer" plugins. +Source plugins are essentially out of the box integrations between Gatsby and various third-party systems. -- **Source** plugins "source" data from remote or local locations into what - Gatsby calls [nodes](/docs/node-interface/). -- **Transformer** plugins "transform" data provided by source plugins into new - nodes and/or node fields. +These systems can be CMSs like Contentful or WordPress, other cloud services like Lever and Strava, or your local filesystem -- literally anything that has an API. Currently, Gatsby has [over 300 source plugins](/plugins/?=gatsby-source). -This doc focuses on source plugins and uses `gatsby-source-filesystem` to explain how source plugins work. +Once a source plugin brings data into Gatsby's system, it can be transformed further with **transformer plugins**. ## What do source plugins do? -The [`gatsby-source-filesystem`](/packages/gatsby-source-filesystem/) plugin -"sources" data about files from the file system. It creates nodes with a type -`File`, each File node corresponding to a file on the filesystem. On each node -are fields like the `absolutePath`, `extension`, `modifiedTime`, etc. +At a high-level, a source plugin: -## What fields are required? - -### `media type` is not required, yet necessary to work with transformer plugins - -Each node created by the filesystem source plugin includes the -raw content of the file and its _media type_. - -[A **media type**](https://en.wikipedia.org/wiki/Media_type) (also **MIME type** -and **content type**) are an official way to identify the format of -files/content that is transmitted on the internet e.g. over HTTP or through -email. You're probably familiar with many media types such as -`application/javascript`, `application/pdf`, `audio/mpeg`, `text/html`, -`text/plain`, `image/jpeg`, etc. - -Each source plugin is responsible for setting the media type for the nodes they -create. This way, source and transformer plugins can work together easily. - -This is not a required field but it's the way for source plugins to indicate to -transformers that there is "raw" data that can still be further processed. It -allows plugins to remain small and focused. Source plugins don't have to have -opinions on how to transform their data. They can just set the `mediaType` and -push that responsibility to transformer plugins. - -For example, it's quite common for services to allow you to add content as -markdown. If you pull that markdown into Gatsby and create a new node, what -then? How would a user of your source plugin convert that markdown into HTML -they can use in their site? Luckily you don't have to do anything. Just create a -node for the markdown content and set its mediaType as `text/markdown` and the -various Gatsby markdown transformer plugins will see your node and transform it -into HTML. - -This loose coupling between the data source and the transformer plugins allow Gatsby site builders to quickly assemble complex data transformation pipelines with -little work on their (and your (the source plugin author)) part. +- Ensures local data is synced with its source and is 100% accurate. +- Creates [nodes](/docs/node-interface/) with accurate media types, human-readable types, and accurate + [contentDigests](/docs/node-interface/#contentdigest). +- Links nodes & creates relationships between them. +- Lets Gatsby know when nodes are finished sourcing so it can move on to processing them. ## What does the code look like? -A source plugin is a normal NPM package. It has a package.json with optional -dependencies as well as a `gatsby-node.js` where you implement Gatsby's Node.js -APIs. Gatsby's minimum supported Node.js version is Node 8 and as it's common to want to use more modern Node.js and JavaScript syntax, many plugins write code in a +A source plugin is a regular NPM package. It has a `package.json` file with optional +dependencies as well as a [`gatsby-node.js`](/docs/api-files-gatsby-node) file where you implement Gatsby's [Node +APIs](/docs/node-apis/). Read more about [Files Gatsby Looks for in a Plugin](/docs/files-gatsby-looks-for-in-a-plugin/). + +Gatsby's minimum supported Node.js version is Node 8 and as it's common to want to use more modern Node.js and JavaScript syntax, many plugins write code in a source directory and compile the code. All plugins maintained in the Gatsby repo follow this pattern. @@ -82,20 +49,37 @@ Peruse the [`sourceNodes`](/docs/node-apis/#sourceNodes) and [`createNode`](/docs/actions/#createNode) docs for detailed documentation on implementing those APIs. -## What are the jobs of a source plugin? +### Transforming data received from remote sources -At a high-level, these are the jobs of a source plugin: +Each node created by the filesystem source plugin includes the +raw content of the file and its _media type_. -- Ensure local data is synced with its source and 100% accurate. If your source - allows you to add an `updatedSince` query (or something similar) you can store - the last time you fetched data using - [`setPluginStatus`](/docs/actions/#setPluginStatus). -- Create nodes with accurate media types, human meaningful types, and accurate - contentDigests. -- "Link" nodes types you create as appropriate (see - [_Node Link_](/docs/api-specification/) in the API specification concepts - section). -- Return either a promise or use the callback (3rd parameter) to report back to Gatsby when `sourceNodes` is fully executed. If a promise or callback isn't returned, Gatsby will continue on in the build process, before nodes are finished being created. Your nodes might not end up in the generated schema at compilation, or the process will hang while waiting for an indication that it's finished. +[A **media type**](https://en.wikipedia.org/wiki/Media_type) (also **MIME type** +and **content type**) is an official way to identify the format of +files/content that is transmitted on the internet, e.g. over HTTP or through +email. You might be familiar with other media types such as +`application/javascript`, `application/pdf`, `audio/mpeg`, `text/html`, +`text/plain`, `image/jpeg`, etc. + +Each source plugin is responsible for setting the media type for the nodes they +create. This way, source and transformer plugins can work together easily. + +This is not a required field -- if it's not provided, Gatsby will [infer](/docs/glossary#inference) the type from data that is sent -- but it's the way for source plugins to indicate to +transformers that there is "raw" data that can still be further processed. It +also allows plugins to remain small and focused. Source plugins don't have to have +opinions on how to transform their data: they can set the `mediaType` and +push that responsibility to transformer plugins, instead. + +For example, it's common for services to allow you to add content in +Markdown format. If you pull that Markdown into Gatsby and create a new node, what +then? How would a user of your source plugin convert that Markdown into HTML +they can use in their site? You would create a +node for the Markdown content and set its `mediaType` as `text/markdown` and the +various Gatsby Markdown transformer plugins would see your node and transform it +into HTML. + +This loose coupling between the data source and the transformer plugins allow Gatsby site builders to assemble complex data transformation pipelines with +little work on their (and your (the source plugin author)) part. ## Getting helper functions @@ -106,15 +90,19 @@ required fields. This includes automatically generating fields like node IDs and the `contentDigest` MD5 hash, keeping your code focused on data gathering, not boilerplate. +## Gotcha: don't forget to return! + +After your plugin is finished sourcing nodes, it should either return a Promise or use the callback (3rd parameter) to report back to Gatsby when `sourceNodes` is fully executed. If a Promise or callback isn't returned, Gatsby will continue on in the build process, before nodes are finished being created. Without the necessary return statement your nodes might not end up in the generated schema at compilation time, or the process will hang while waiting for an indication that it's finished. + ## Advanced -## Two ways of adding relationships between nodes +### Adding relationships between nodes Gatsby source plugins not only create nodes, they also create relationships between nodes that are exposed to GraphQL queries. There are two ways of adding node relationships in Gatsby: (1) transformations (parent-child) or (2) foreign-key based. -### Option 1: transformation relationships +#### Option 1: transformation relationships An example of a transformation relationship is the `gatsby-transformer-remark` plugin, which transforms a parent `File` node's markdown string into a `MarkdownRemark` node. The Remark transformer plugin adds its newly created child node as a child of the parent node using the action [`createParentChildLink`](/docs/actions/#createParentChildLink). Transformation relationships are used when a new node is _completely_ derived from a single parent node. E.g. the markdown node is derived from the parent `File` node and wouldn't ever exist if the parent `File` node hadn't been created. @@ -130,7 +118,7 @@ _Examples_ [Here's another example](https://github.com/gatsbyjs/gatsby/blob/1fb19f9ad16618acdac7eda33d295d8ceba7f393/packages/gatsby-transformer-sharp/src/on-node-create.js#L3-L25) from the `gatsby-transformer-sharp` source plugin. -### Option 2: foreign-key relationships +#### Option 2: foreign-key relationships An example of a foreign-key relationship would be a Post that has an Author. @@ -138,13 +126,13 @@ In this relationship, each object is a distinct entity that exists whether or no When an object node is deleted, Gatsby _does not_ delete any referenced entities. When using foreign-key references, it's a source plugin's responsibility to clean up any dangling entity references. -#### Creating the relationship +##### Creating the relationship Suppose you want to create a relationship between Posts and Authors, and you want to call the field `author`. Before you pass the Post object and Author object into `createNode` and create the respective nodes, you need to create a field called `author___NODE` on the Post object to hold the relationship to Authors. The value of this field should be the node ID of the Author. -#### Creating the reverse relationship +##### Creating the reverse relationship It's often convenient for querying to add to the schema backwards references. For example, you might want to query the Author of a Post but you might also want to query all the posts an author has written. @@ -152,6 +140,21 @@ If you want to call this field on `Author` `posts`, you would create a field cal Here's an example from the [WordPress source plugin](https://github.com/gatsbyjs/gatsby/blob/1fb19f9ad16618acdac7eda33d295d8ceba7f393/packages/gatsby-source-wordpress/src/normalize.js#L178-L189). -### Union types +#### Union types When creating fields linking to an array of nodes, if the array of IDs are all of the same type, the relationship field that is created will be of this type. If the linked nodes are of different types; the field will turn into a union type of all types that are linked. See the [GraphQL documentation on how to query union types](https://graphql.org/learn/schema/#union-types). + +#### Further specification + +See +[_Node Link_](/docs/api-specification/) in the API Specification concepts +section for more info. + +### Improve plugin developer experience by enabling faster sync + +One tip to improve the development experience of using a plugin is to reduce the time it takes to sync between Gatsby and the data source. There are two approaches for doing this: + +- **Add event-based sync**. Some data sources keep event logs and are able to return a list of objects modified since a given time. If you're building a source plugin, you can store + the last time you fetched data using + [`setPluginStatus`](/docs/actions/#setPluginStatus) and then only sync down nodes that have been modified since that time. [gatsby-source-contentful](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-contentful) is an example of a source plugin that does this. +- **Proactively fetch updates**. One challenge when developing locally is that a developer might make modifications in a remote data source, like a CMS, and then want to see how it looks in the local environment. Typically they will have to restart the `gatsby develop` server to see changes. This can be avoided if your source plugin knows to proactively fetch updates from the remote server. For example,[gatsby-source-sanity](https://github.com/sanity-io/gatsby-source-sanity), listens to changes to Sanity content when `watchMode` is enabled and pulls them into the Gatsby develop server. diff --git a/docs/docs/creating-a-starter.md b/docs/docs/creating-a-starter.md index 8b152bcc439a3..b65c05aab8f26 100644 --- a/docs/docs/creating-a-starter.md +++ b/docs/docs/creating-a-starter.md @@ -71,6 +71,5 @@ To make sure your starter is easily discoverable, you are welcome (but not requi ## Further reading: -- [How to create a Gatsby Starter - ](https://medium.com/@emasuriano/how-to-create-a-gatsby-starter-e7d53083a880) by Emanuel Suriano +- [How to create a Gatsby Starter](https://medium.com/@emasuriano/how-to-create-a-gatsby-starter-e7d53083a880) by Emanuel Suriano - [Introducing Gatsby Themes](/blog/2018-11-11-introducing-gatsby-themes/) (including info on starters) diff --git a/docs/docs/creating-a-transformer-plugin.md b/docs/docs/creating-a-transformer-plugin.md index 05ce3d5575c0f..f0d0206bd3758 100644 --- a/docs/docs/creating-a-transformer-plugin.md +++ b/docs/docs/creating-a-transformer-plugin.md @@ -126,7 +126,7 @@ exports.onCreateNode = onCreateNode File content: -```text +```yaml - id: Jane Doe bio: Developer based in Somewhere, USA - id: John Smith diff --git a/docs/docs/creating-and-modifying-pages.md b/docs/docs/creating-and-modifying-pages.md index 732caedb70561..8484f70475e54 100644 --- a/docs/docs/creating-and-modifying-pages.md +++ b/docs/docs/creating-and-modifying-pages.md @@ -12,7 +12,7 @@ Pages can be created in three ways: - Plugins can also implement `createPages` and create pages for you You can also implement the API [`onCreatePage`](/docs/node-apis/#onCreatePage) -to modify pages created in core or plugins or to create [client-only routes](/docs/building-apps-with-gatsby/). +to modify pages created in core or plugins or to create [client-only routes](/docs/client-only-routes-and-user-authentication/). ## Debugging help diff --git a/docs/docs/centralizing-your-sites-navigation.md b/docs/docs/creating-dynamic-navigation.md similarity index 96% rename from docs/docs/centralizing-your-sites-navigation.md rename to docs/docs/creating-dynamic-navigation.md index 4b3066d4d4937..d0c389024b74e 100644 --- a/docs/docs/centralizing-your-sites-navigation.md +++ b/docs/docs/creating-dynamic-navigation.md @@ -1,9 +1,7 @@ --- -title: Centralizing Your Site's Navigation +title: Creating Dynamic Navigation in Gatsby --- -## Creating dynamic navigation in Gatsby - At times you will want to be able to edit your website's navigation in response to a _change in requirements_. To achieve this, you can use Gatsby to dynamically generate your navigation. Where you store the data for your navigation can be anywhere - a backend API, CMS, headless CMS or even the filesystem. What this section will cover: @@ -44,7 +42,7 @@ module.exports = { GraphQL can be used to query for information contained in the `siteMetadata` object located in your project's `gatsby-config.js`. In order to test this out, you can start the `default-starter-project` in development mode by running `npm run develop`. -Navigate to `http://localhost:8000/___graphql` in your browser to view the GraphiQL editor, which enables you to test GraphQL queries on the underlying APIs. Using the documentation explorer you can view the current GraphQL schema for your project, which is an invaluable resource during development. +Navigate to in your browser to view the GraphiQL editor, which enables you to test GraphQL queries on the underlying APIs. Using the documentation explorer you can view the current GraphQL schema for your project, which is an invaluable resource during development. Examining the available types in GraphQL you will notice that you can query `site`. This GraphQL type further returns the `siteMetadata` which needs to be accessed to create the dynamic navigation. At this point, it is useful if you know a little GraphQL in order to extract the menu links. If you are unfamiliar with GraphQL, there is some excellent documentation available at GraphQL's official website found [here](https://graphql.org/learn/) that you can use to brush up on your skills! The query below will return the menu links. @@ -189,9 +187,9 @@ const Layout = ({ children }) => ( ### Using the header component to display the navigation -Locate the `header.js` file inside `src/components` and remove everything so only the functional component definition is left (everything else is just boilerplate code given to us when generating our project): +Locate the `header.js` file inside `src/components` and remove everything so only the functional component definition is left (everything else is just boilerplate code given to you when generating your project): -```js:title=src/components/header.js +```jsx:title=src/components/header.js import React from "react" import { Link } from "gatsby" const Header = ({ siteTitle, menuLinks }) => ( @@ -265,7 +263,7 @@ Header.defaultProps = { export default Header ``` -Starting the development server by running `npm run develop` and navigating to `http://localhost:8000` you should now see some dynamically generated menu links on your page. +Starting the development server by running `npm run develop` and navigating to you should now see some dynamically generated menu links on your page. If you have made it this far, good job! You can now add new site links to your website dynamically by adding entries to the `gatsby-config.js` file. diff --git a/docs/docs/creating-prefixed-404-pages-for-different-languages.md b/docs/docs/creating-prefixed-404-pages-for-different-languages.md index e509f8231b1d6..b15382809efce 100644 --- a/docs/docs/creating-prefixed-404-pages-for-different-languages.md +++ b/docs/docs/creating-prefixed-404-pages-for-different-languages.md @@ -6,7 +6,7 @@ Using the [`onCreatePage`](/docs/node-apis/#onCreatePage) API in your project's Here is an example that shows you how to create an English 404 page at `src/pages/en/404.js`, and a German 404 page at `/src/pages/de/404.js`: -```javascript:title=src/pages/en/404.js +```jsx:title=src/pages/en/404.js import React from "react" import Layout from "../../components/layout" @@ -18,7 +18,7 @@ export default () => ( ) ``` -```javascript:title=src/pages/de/404.js +```jsx:title=src/pages/de/404.js import React from "react" import Layout from "../../components/layout" diff --git a/docs/docs/css-in-js.md b/docs/docs/css-in-js.md index 90c5547f2d1fa..cd99bb9ee3872 100644 --- a/docs/docs/css-in-js.md +++ b/docs/docs/css-in-js.md @@ -12,7 +12,7 @@ CSS-in-JS bridges the gap between CSS and JavaScript: 3. **Dynamic**: style your site dynamically based on component state by integrating JavaScript variables. 4. **Bonuses**: many CSS-in-JS libraries generate unique class names which can help with caching, automatic vendor prefixes, timely loading of critical CSS, and implementing many other features, depending on the library you choose. -CSS-in-JS, while not required in Gatsby, is very popular among JavaScript developers for the reasons listed above. For more context, read Max Stoiber's (creator of CSS-in-JS library [styled-components](/docs/styled-components/)) article [_Why I write CSS in JavaScript_](https://mxstbr.com/thoughts/css-in-js/). However, you should also consider whether CSS-in-JS is necessary, as not relying on it can encourage more inclusive front-end skill-sets. It is also more difficult to port styles from JSX to and from CSS. +CSS-in-JS, while not required in Gatsby, is very popular among JavaScript developers for the reasons listed above. For more context, read Max Stoiber's (creator of CSS-in-JS library [styled-components](/docs/styled-components/)) article [_Why I write CSS in JavaScript_](https://mxstbr.com/thoughts/css-in-js/). However, you should also consider whether CSS-in-JS is necessary, as not relying on it can encourage more inclusive frontend skill-sets. It is also more difficult to port styles from JSX to and from CSS. _Note that this functionality is not a part of React or Gatsby, and requires using any of the many [third-party CSS-in-JS libraries](https://github.com/MicheleBertoli/css-in-js#css-in-js)._ diff --git a/docs/docs/custom-html.md b/docs/docs/custom-html.md index d60e47b751bd8..cb2912d700d06 100644 --- a/docs/docs/custom-html.md +++ b/docs/docs/custom-html.md @@ -3,7 +3,7 @@ title: Customizing html.js --- Gatsby uses a React component to server render the `` and other parts of -the HTML outside of the core Gatsby application. Gatsby also sets a default value for the `