In a recent Reactiflux interview, the Gatsby team was asked this question:
Q: What is one thing that Gatsby is capable of doing that might surprise some people? — ctlee
A: Gatsby can be used to build fully dynamic sites, which surprises some people because of it’s label as a “static site generator”. It’s fully equipped to be a powerful alternative to create-react-app and other similar solutions with the addition of easy pre-rendering and perf baked in. — biscarch
Today I’d like to show you how you can incrementally add functionality to a Gatsby static site with Netlify Functions, and then add authentication with Netlify Identity to begin a proper Gatsby app.
Why would you use something like Gatsby over Jekyll or Hugo or one of the hundreds of Static Site Generators out there? There are many reasons, but one of the unique selling points is how Gatsby helps you build “Static Progressive Web Apps” with React.
Let’s say you have a typical static Gatsby site, like gatsby-starter-default. You can
npm run build it, and it spits out a bunch of HTML files. Great! I can host that for free!
Now your client comes to you and asks you to add some custom logic that needs to be executed on the server:
- Maybe you have third party API secrets you don’t want to expose to your user.
- Maybe you need a serverside proxy to get around CORS issues.
- Maybe you need to ping a database to check your inventory.
Oh no! Now you have to rewrite everything and move to a Digital Ocean droplet!
I’m kidding. No, you don’t have to rewrite everything.
The beauty of serverless functions is that it is incrementally adoptable - your site grows with your needs - and with Gatsby you can rerender entire sections of your site based on live API data. Of course, the more you do this, the more resource intensive (in terms of bandwidth and computation) it can be, so there is a performance tradeoff. Your site should be as dynamic as you need it to be, but no more. Gatsby is perfect for this.
Netlify Functions are a great low configuration solution for adding serverless functionality to your Gatsby site. You get 125,000 free calls a month - that’s a function call every 20 seconds every day of the week, month, and year - and you can emulate them in local development with
Let’s walk through the steps:
- Install dependencies:
npm install -D http-proxy-middleware netlify-lambda npm-run-all
- Run function emulation alongside Gatsby: replace your
When deploying to Netlify,
gatsby build must be run before
netlify-lambda build src/functions or else your Netlify function builds will fail. To avoid this, do not set your build script command to
"build": "run-p build:**" when you replace
package.json. Doing so will run all build scripts in parallel. This will make it possible for
netlify-lambda build src/functions to run before
- Configure your Netlify build: When serving your site on Netlify,
src/functionsfolder as a standalone Netlify function (with a path corresponding to the filename). Make sure you have a Functions path in a
netlify.tomlfile at root of your repository:
For more info or configuration options (e.g. in different branches and build environments), check the Netlify.toml reference.
command specified in
netlify.toml overrides the build command specified in your site’s Netlify UI Build settings.
- Proxy the emulated functions for local development: Head to
gatsby-config.jsand add this to your
- Write your functions: Make a
src/functionsfolder and write as many functions as you need. The only requirement is that each function must export a
netlify-lambdahelps you use webpack to bundle modules or you can zip the functions yourself. For example you can write
Now you are ready to access this API from anywhere in your Gatsby app! For example, in any event handler or lifecycle method, insert:
and watch “Hello World!” pop up in your console. (I added a random number as well to show the endpoint is dynamic) If you are new to React, I highly recommend reading through the React docs to understand where and how to insert event handlers so you can, for example, respond to a button click.
The local proxying we are doing is only for local emulation, e.g. it is actually running from
http://localhost:9000/hello despite you hitting
/.netlify/functions/hello in your Gatsby app. When you deploy your site to Netlify (either by hooking your site up through Git through our Web UI, or our l33t new CLI), that falls away, and your functions -are- hosted on the same URL and “just works”. Pretty neat!
So, yes, your site can now be more dynamic than any static site. It can hit any database or API. It runs rings around CORS (by the way, you can also use Netlify Redirects for that). But its not an app app. Yet!
The key thing about web apps (and, let’s face it, the key thing users really pay for) is they all have some concept of
user, and that brings with it all manner of complication from security to state management to role-based access control. Entire routes need to be guarded by authentication, and sensitive content shielded from Gatsby’s static generation. Sometimes there are things you -don’t- want Google’s spiders to see!
It’s a different tier of concern, which makes it hard to write about in the same article as a typical Gatsby tutorial. But we’re here to make apps, so let’s bring it on!
- Enable Netlify Identity: Netlify Identity doesn’t come enabled by default. You’ll have to head to your site admin (e.g.
https://app.netlify.com/sites/YOUR_AWESOME_SITE/identity) to turn it on. Read the docs for further info on what you can do, for example add Facebook or Google social sign-on!
- Install dependencies:
npm install netlify-identity-widget gatsby-plugin-create-client-paths
- Configure Gatsby: for dynamic-ness!
- Write an authentication service:
netlify-identity-widgetis a framework-agnostic overlay that ships with a nice signup/login UI. This gets you up and running the fastest, however if you need a smaller solution you may want to use the underlying gotrue-js, or react-netlify-identity for a React Hooks solution.
Here’s a usable example that stores your user in local storage:
- Write your app: Now, any sub paths in
src/pages/appwill be exempt from Gatsby static generation. To keep the dividing line between app and site crystal clear, I like to have all my dynamic Gatsby code in a dedicated
appfolder. This means you can use
netlify-identity-widgetto write a standard dynamic React app. Here’s some sample code to give you an idea of how to hook them up:
Phew that was a lot! but you should have a solid starting point for your app :)
Just like every magic act has a pledge, a turn, and a prestige, I have one last tidbit for you. Nothing on the client-side is safe, and although you can send along Netlify Identity user id’s to your Netlify Function endpoints for authenticated access from your Gatsby App (for example in the body of a POST request), you’ll never be truly sure if that flow is secure either from malicious users or snooping.
The best way to do authenticated actions inside serverless functions is to do it from inside the context of the function itself. Fortunately, Netlify Identity and Functions work seamlessly together. All you have to do is to send along the user’s JWT when hitting your endpoint:
And then inside a Lambda function, you can now access the
It’s 5 steps each to turn your static Gatsby sites into dynamic, authenticated, fully serverless apps with Netlify’s free tools. This makes Gatsby a perfect tool for your next app. If you’re at a hackathon, short on time, or just like to see a full working demo, check any of the following links.