Skip to main content

Kyle Mathews

Founder @ GatsbyJS. Likes tech, reading/writing, founding things. Blogs at bricolage.io.

6 min read · March 9th 2017

Gatsbygram Case Study

Gatsbygram is a clone of Instagram built with Gatsby v1.

The source code for Gatsbygram lives in the Gatsby monorepo. See the instructions at the end for how to start playing with the code!

What is Gatsby

Gatsby is a JavaScript web framework that lets you build fast, dynamic, mobile-ready websites without an advanced degree in JavaScript wizardry.

It combines the fast performance of static websites with the powerful abstractions, tools, and client capabilities of the React.js world.

Gatsby is fast

Gatsby automatically optimizes your site for the modern web. You provide pages and Gatsby stitches them together so they load as fast as possible.

As proof of this, Gatsbygram loads 2-3x faster than the real Instagram site.

I tested Gatsbygram and Instagram on webpagetest.org using a simulated 3G network and a Moto G4 smartphone—a budget Android typical of many lower-end phones used today. The median speed index score for Gatsbygram was 3151 vs. 8251 for Instagram.

gatsbygram vs. instagram filmstrip Filmstrip of Gatsbygram (top) and Instagram (bottom) loading on webpagetest.org

The second repeat view is even faster for Gatsbygram as it now loads from its service worker. It has pixels on the screen in under a 1/2 second on a budget Android device! And for both the initial and repeat view, Gatsbygram finishes loading a full second before Instagram gets started.

gatsbygram vs. instagram filmstrip repeat
load Filmstrip of a repeat view of Gatsbygram (top) and Instagram (bottom) loading on webpagetest.org

The difference in Time to Interactivity (TTI) (measure of how long before the user can actually interact with the page e.g. click on a link) between the sites is just as dramatic. Gatsbygram’s TTI is 6.1s vs 14.1s for Instagram.

Gatsby is built for the next billion internet users

As Benedict Evans has noted, the next billion people poised to come online will be using the internet almost exclusively through smartphones.

Smartphones with decent specs (as good or better than the Moto G4), a great browser, but without a reliable internet connection.

Gatsby uses modern web performance ideas (e.g. PRPL) developed by the Google Chrome Developer Relations team and others to help websites work well on modern browsers with unreliable networks.

Sites built with Gatsby run as much as possible in the client so regardless of the network conditions—good, bad, or nonexistent—things will keep working.

Many of the top e-commerce websites in areas where people are coming online for the first time are developing their websites using these techniques.

Read Google’s case studies on:

Gatsby is simple

Modern JavaScript websites are too complex to rely on developers always configuring things correctly. Gatsby simplifies website development by extracting configuration out of your site and moving it into the framework and community plugins.

You give Gatsby React.js components, data, and styles and Gatsby gives you back an optimized website.

Gatsbygram is a completely vanilla Gatsby site. Its optimizations are from the framework.

Gatsby includes a full modern JavaScript toolchain (Babel/webpack/Uglify) with optimized production builds and an innovative declarative asset pipeline.

For Gatsbygram, Gatsby generates over 1000 image thumbnails for responsive images without any custom scripting by leveraging the Gatsby image processing plugin gatsby-transformer-sharp.

Stop wasting time and build something!

App structure

All static site generators create a set of files that determine the routing in 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:

…would be transformed to:

This is fine at first, but can be limiting. For example, in Gatsbygram, we have a JSON data blob scraped from an Instagram user profile. From this we want to generate a page for each image. We couldn’t do this with a typical static site generator, but Gatsby lets you define routes programmatically through the createPages API using any data you have available.

Here is how we define pages from our JSON data for Gatsbygram at build time in the site’s gatsby-node.js file:

Using templates

Gatsby uses standard React.js components to render pages. When you define a page in the createPages API, you specify its component. Those components, usually called templates, get reused with page-specific data to generate the different pages.

As you can see above, when defining a page, we can set “context” data, which is passed as a prop to the component and as a GraphQL variable in our GraphQL query. For the ”post template”, we pass the id to the post. Below we use that id to query our GraphQL schema and return a fully formed page:

Creating React.js component pages

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.

These React component pages can query the Gatsbygram GraphQL schema for data and are automatically converted into their own pages at gatsbygram.gatsbyjs.org/ and gatsbygram.gatsbyjs.org/about/.

Gatsbygram’s about.js is a plain React component with no query. index.js is more complex. It queries for thumbnails for all images and has an infinite scroll implementation to lazy load in image thumbnails.

Read pages/index.js on GitHub Read pages/about.js on GitHub

The Layout Component

Each Gatsby site has a top-level layout component at layouts/index.js. This layout component is used on every page of your site so can contain things like your header, footer, and default page structure. It is also used as the ”app shell” when loading your site from a service worker.

A small layout component might look something like this.

Every page will be rendered as children of the Layout component:

Gatsbygram’s layout component is somewhat more complicated than most sites as it has logic to show clicked images in either a modal on larger screens or on their own page on smaller screens.

Read Gatsbygram’s Layout component on GitHub.

Client routing and pre-caching

Gatsby loads first a static server-rendered HTML page and then the JavaScript to convert the site into a web application. Which means that clicking around the site doesn’t require a page reload. Gatsby pre-caches code and data needed for other pages so that clicking on a link loads the next page instantly.

All the setup for this is handled behind the scenes. Gatsby uses @reach/router under the hood but generates all the configuration for you.

Normally page resources are pre-cached with a service worker. But as several browsers (Safari/Microsoft Edge) still don’t support Service Workers, the Gatsby <Link> component pre-caches resources for pages it links to by loading them into memory.

Plugins

Gatsby has always had a rich set of lifecycle APIs to allow you to hook into various events during development, building, and in the client.

Gatsby 1.0 adds new APIs and also adds a new plugin architecture. So functionality can now be extracted from sites and made reusable. Most of the new functionality in Gatsby 1.0 is powered by plugins.

Plugins are added to a site in its gatsby-config.js. Here’s what Gatsbygram’s config file looks like:

Styles

Gatsbygram uses two popular and complementary css-in-js libraries, Typography.js and Glamor.

Typography.js is a powerful toolkit for building websites with beautiful design.

Gatsbygram uses Typography.js to generate the global styles for the site helping set the overall feel of the design.

Glamor lets you write real CSS in JavaScript inline in your React.js components. It is used for component styles.

Typography.js exposes two helper JavaScript functions, rhythm and scale to help keep your design in sync as you make changes. Instead of using hard-coded spacing values (which break as soon as you change your global theme), you use the Typography.js helper functions e.g.

Together they allow you to quickly iterate on designs.

They also contribute to Gatsbygram’s excellent loading speed. The holy grail of CSS performance is inlined critical CSS. Meaning a) only ship a page with the CSS necessary to render that page and b) inline it in the <head> instead of putting it in a separate file. There are various tools to make this happen but they tend to involve extensive configuration and heavy post-processing.

But with Typography.js and Glamor you get optimized CSS with no tedious, error-prone bookkeeping. Typography.js (by definition) generates only global styles so its styles are included on every page. Glamor includes some clever server-rendering optimizations which I’ve implemented in the Gatsby Glamor plugin where it automatically extracts out the CSS used in components on the page being server rendered and automatically inlines those styles in the generated HTML page.

Super fast CSS by default. 👏👏👏

Creating your own Gatsbygram

It’s easy to create your own “Gatsbygram” site from an Instagram account.

Instructions on setting up your own Gatsbygram site.

While writing this post I scraped a few accounts and published their resulting “Gatsbygram” sites:

With thanks to Sam Bhagwatt, Sunil Pai, Nolan Lawson, Nik Graf, Jeff Posnick, and Addy Osmani for their reviews.

And a special thanks to Kristo Jorgenson for his refactor of the “App structure” section.

Enjoyed this post? Receive the next one in your inbox!

Docs
Tutorials
Plugins
Blog
Showcase