Repository: imorente/gatsby-netlify-form-example Branch: master Commit: fc08d5af1fa4 Files: 15 Total size: 26.2 KB Directory structure: gitextract_wse6q8pa/ ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── gatsby-config.js ├── package.json └── src/ ├── css/ │ └── typography.css ├── html.js ├── layouts/ │ └── index.js └── pages/ ├── 404.js ├── contact.js ├── file-upload.js ├── index.js ├── recaptcha.js └── thanks.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Logs logs *.log # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules .gatsby-context.js .sass-cache/ public/ .cache/ .DS_Store # Environment variables .env.development ================================================ FILE: .travis.yml ================================================ # back to language cpp to try to bypass osx node failure language: cpp sudo: false env: - export NODE_VERSION="0.12" - export NODE_VERSION="4" - export NODE_VERSION="5" os: - linux - osx # pre-install to bring in the correct version of node via nvm before_install: - git submodule update --init --recursive - git clone https://github.com/creationix/nvm.git ./.nvm - source ./.nvm/nvm.sh - nvm install $NODE_VERSION - nvm use $NODE_VERSION - npm config set python `which python` - if [ $TRAVIS_OS_NAME == "linux" ]; then export CC="gcc-4.8"; export CXX="g++-4.8"; export LINK="gcc-4.8"; export LINKXX="g++-4.8"; fi - gcc --version - g++ --version # node 4 depends on gcc 4.8 addons: apt: sources: - ubuntu-toolchain-r-test packages: - g++-4.8 - gcc-4.8 # script needed to test, because defaults don't work on osx script: - npm install - npm run lint ================================================ FILE: LICENSE ================================================ 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. ================================================ FILE: README.md ================================================ # Integrating Netlify Form Handling in Gatsby Example for integrating a basic contact form with Netlify’s form handling feature (based on the [default Gatsby starter](https://github.com/gatsbyjs/gatsby-starter-default)) Demo: https://gatsby-form-example.netlify.com ## Deploy [![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/imorente/gatsby-netlify-form-example) ## reCAPTCHA This example site uses [react-google-recaptcha](https://github.com/dozoisch/react-google-recaptcha) to render the reCAPTCHA widget. To make the reCAPTCHA example work in your own copy of this site, you’ll need to do the following: 1. [Sign up for a reCAPTCHA API key pair](http://www.google.com/recaptcha/admin) for your site. 2. [Log in to your Netlify account](https://app.netlify.com), and add the following environment variables to your site’s Settings > Build & deploy > Build environment variables: - `SITE_RECAPTCHA_KEY` with your reCAPTCHA site key. - `SITE_RECAPTCHA_SECRET` with your reCAPTCHA secret key. **Important**: the environment variables need to be called `SITE_RECAPTCHA_KEY` and `SITE_RECAPTCHA_SECRET` for the Netlify backend to find them. If you add a `GATSBY_` prefix to the variable names, the Netlify backend won't recognize them, the reCAPTCHA verification will fail, and your form submissions won't be stored. 3. Change the build command for your site to ``` echo SITE_RECAPTCHA_KEY=$SITE_RECAPTCHA_KEY >> .env.production && gatsby build ``` This will make the SITE_RECAPTCHA_KEY available to the Gatsby build in production. To see the reCAPTCHA widget locally, add `SITE_RECAPTCHA_KEY=your-reCAPTCHA-API-site-key` to your local [.env.development](https://www.gatsbyjs.org/docs/environment-variables/) file. ## Troubleshooting ### Forms stop working after upgrading to Gatsby v2 This can be caused by the offline-plugin. [Workaround](https://github.com/gatsbyjs/gatsby/issues/7997#issuecomment-419749232) is to use `?no-cache=1` in the POST url to prevent the service worker from handling form submissions (Thanks to [@phmu_office](https://twitter.com/phmu_office/status/1047810173417472000) for the heads up ✨) ================================================ FILE: gatsby-config.js ================================================ module.exports = { siteMetadata: { title: `Gatsby Netlify Form Integration` }, plugins: [`gatsby-plugin-react-helmet`] }; ================================================ FILE: package.json ================================================ { "name": "gatsby-starter-default", "description": "Gatsby default starter", "version": "1.0.0", "author": "Kyle Mathews ", "dependencies": { "gatsby": "^1.9.261", "gatsby-link": "^1.0.1", "gatsby-plugin-react-helmet": "^1.0.1", "react-async-script": "^0.9.1", "react-google-recaptcha": "^0.11.1" }, "devDependencies": { "dotenv": "^5.0.1", "gh-pages": "^0.12.0" }, "keywords": [ "gatsby" ], "license": "MIT", "main": "n/a", "scripts": { "build": "gatsby build", "deploy": "gatsby build --prefix-paths && gh-pages -d public", "develop": "gatsby develop", "format": "prettier --trailing-comma es5 --no-semi --single-quote --write \"pages/*.js\" \"utils/*.js\" \"wrappers/*.js\" \"html.js\"", "test": "echo \"Error: no test specified\" && exit 1" } } ================================================ FILE: src/css/typography.css ================================================ html { font-family: sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; } body { margin: 0; } article, aside, details, figcaption, figure, footer, header, main, menu, nav, section, summary { display: block; } audio, canvas, progress, video { display: inline-block; } audio:not([controls]) { display: none; height: 0; } progress { vertical-align: baseline; } [hidden], template { display: none; } a { background-color: transparent; -webkit-text-decoration-skip: objects; } a:active, a:hover { outline-width: 0; } abbr[title] { border-bottom: none; text-decoration: underline; text-decoration: underline dotted; } b, strong { font-weight: inherit; font-weight: bolder; } dfn { font-style: italic; } h1 { font-size: 2em; margin: .67em 0; } mark { background-color: #ff0; color: #000; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } img { border-style: none; } svg:not(:root) { overflow: hidden; } code, kbd, pre, samp { font-family: monospace, monospace; font-size: 1em; } figure { margin: 1em 40px; } hr { box-sizing: content-box; height: 0; overflow: visible; } button, input, optgroup, select, textarea { font: inherit; margin: 0; } optgroup { font-weight: 700; } button, input { overflow: visible; } button, select { text-transform: none; } [type=reset], [type=submit], button, html [type=button] { -webkit-appearance: button; } [type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner { border-style: none; padding: 0; } [type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring, button:-moz-focusring { outline: 1px dotted ButtonText; } fieldset { border: 1px solid silver; margin: 0 2px; padding: .35em .625em .75em; } legend { box-sizing: border-box; color: inherit; display: table; max-width: 100%; padding: 0; white-space: normal; } textarea { overflow: auto; } [type=checkbox], [type=radio] { box-sizing: border-box; padding: 0; } [type=number]::-webkit-inner-spin-button, [type=number]::-webkit-outer-spin-button { height: auto; } [type=search] { -webkit-appearance: textfield; outline-offset: -2px; } [type=search]::-webkit-search-cancel-button, [type=search]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-input-placeholder { color: inherit; opacity: .54; } ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; } html { font: 112.5%/1.45em georgia, serif; box-sizing: border-box; overflow-y: scroll; } * { box-sizing: inherit; } *:before { box-sizing: inherit; } *:after { box-sizing: inherit; } body { color: hsla(0, 0%, 0%, 0.8); font-family: georgia, serif; font-weight: normal; word-wrap: break-word; font-kerning: normal; -moz-font-feature-settings: "kern", "liga", "clig", "calt"; -ms-font-feature-settings: "kern", "liga", "clig", "calt"; -webkit-font-feature-settings: "kern", "liga", "clig", "calt"; font-feature-settings: "kern", "liga", "clig", "calt"; } img { max-width: 100%; margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } h1 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 2.25rem; line-height: 2.9rem; } h2 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 1.62671rem; line-height: 2.175rem; } h3 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 1.38316rem; line-height: 2.175rem; } h4 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 1rem; line-height: 1.45rem; } h5 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 0.85028rem; line-height: 1.45rem; } h6 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 0.78405rem; line-height: 1.45rem; } hgroup { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } ul { margin-left: 1.45rem; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; list-style-position: outside; list-style-image: none; } ol { margin-left: 1.45rem; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; list-style-position: outside; list-style-image: none; } dl { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } dd { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } p { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } figure { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } pre { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; font-size: 0.85rem; line-height: 1.42; background: hsla(0, 0%, 0%, 0.04); border-radius: 3px; overflow: auto; word-wrap: normal; padding: 1.45rem; } table { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; font-size: 1rem; line-height: 1.45rem; border-collapse: collapse; width: 100%; } fieldset { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } blockquote { margin-left: 1.45rem; margin-right: 1.45rem; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } form { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } noscript { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } iframe { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } hr { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: calc(1.45rem - 1px); background: hsla(0, 0%, 0%, 0.2); border: none; height: 1px; } address { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } b { font-weight: bold; } strong { font-weight: bold; } dt { font-weight: bold; } th { font-weight: bold; } li { margin-bottom: calc(1.45rem / 2); } ol li { padding-left: 0; } ul li { padding-left: 0; } li > ol { margin-left: 1.45rem; margin-bottom: calc(1.45rem / 2); margin-top: calc(1.45rem / 2); } li > ul { margin-left: 1.45rem; margin-bottom: calc(1.45rem / 2); margin-top: calc(1.45rem / 2); } blockquote *:last-child { margin-bottom: 0; } li *:last-child { margin-bottom: 0; } p *:last-child { margin-bottom: 0; } li > p { margin-bottom: calc(1.45rem / 2); } code { font-size: 0.85rem; line-height: 1.45rem; } kbd { font-size: 0.85rem; line-height: 1.45rem; } samp { font-size: 0.85rem; line-height: 1.45rem; } abbr { border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); cursor: help; } acronym { border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); cursor: help; } abbr[title] { border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); cursor: help; text-decoration: none; } thead { text-align: left; } td, th { text-align: left; border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); font-feature-settings: "tnum"; -moz-font-feature-settings: "tnum"; -ms-font-feature-settings: "tnum"; -webkit-font-feature-settings: "tnum"; padding-left: 0.96667rem; padding-right: 0.96667rem; padding-top: 0.725rem; padding-bottom: calc(0.725rem - 1px); } th:first-child, td:first-child { padding-left: 0; } th:last-child, td:last-child { padding-right: 0; } tt, code { background-color: hsla(0, 0%, 0%, 0.04); border-radius: 3px; font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono", "Liberation Mono", Menlo, Courier, monospace; padding: 0; padding-top: 0.2em; padding-bottom: 0.2em; } pre code { background: none; line-height: 1.42; } code:before, code:after, tt:before, tt:after { letter-spacing: -0.2em; content: " "; } pre code:before, pre code:after, pre tt:before, pre tt:after { content: ""; } @media only screen and (max-width: 480px) { html { font-size: 100%; } } ================================================ FILE: src/html.js ================================================ import React from "react" import PropTypes from "prop-types" const BUILD_TIME = new Date().getTime() export default class HTML extends React.Component { static propTypes = { body: PropTypes.string, } render() { let css if (process.env.NODE_ENV === "production") { css = (