This is a Livecoding Recap – an almost-weekly post about interesting things discovered while livecoding. Usually shorter than 500 words. Often with pictures. Livecoding happens almost every Sunday at 2pm PDT on multiple channels. You should subscribe to My Youtube channel to catch me live.

Gatsby is hands down the best static site generator out there. Builds sites so fast it looks like a bug.

The magic trick Gatsby uses to make sites so fast is binding data build time. Most modern server-side-rendered (ssr) sites build an HTML page of your initial view, load data into the browser, and build the rest of the page live. Or they render a skeleton and fill it with dynamic data.

Just had a CS-y insight into @gatsbyjs



Gatsby is early binding for code *and* data



Most web apps early bind code (at build) and late bind data. Gatsby does both at build time which really speeds up running the site.



Gatsby can also do late binding for data from the client. — Kyle Mathews (@kylemathews) April 23, 2018

Gatsby does all that at build time. Run gatsby build , and it loads your dynamic data and builds static HTML pages with data-dependent parts already baked in.

At a high level, Gatsby uses various source plugins to read data and make it available via a GraphQL interface. You write GraphQL queries to load this data and render React components.

Gatsby handles the rest. I'm not really sure how, but smart people assure me it works, and I've never seen it not work. 🤷‍♀️

Let's say you want to build pages with markdown files. I do that for my workshop materials. I use a bunch of markdown files published as a website, and it works great.

You have to enable the gatsby-source-filesystem plugin. It lets you read local files as a data source. Then you enable the gatsby-transformer-remark plugin, which lets you parse markdown files.

When that's set up, you can get a list of page titles with a query like this:

export const query = graphql ` allMarkdownRemark { edges { node { frontmatter { title } fields { slug } } } } ` ;

You're looking for all nodes of the markdownRemark type, collecting their edges and nodes , and plucking the title and slug value of each.

This shows up in your page component as a data prop. So to list all those page titles, you'd do something like this 👇

const allPages = _ . sortBy ( data . allMarkdownRemark . edges , ( { node } ) => node . fields . slug ) ; < ul > { allPages . map ( ( { node : { frontmatter : { title } } } ) => ( < li > { title } < / li > ) ) } < / ul > ;

There's a lot of looping and destructuring because our data comes in the shape of a graph, and I'm bad at writing GraphQL queries. I'm sure this looks terrible to someone who knows what they're doing.

The fun part is building your own data sources, which you can do, and it's easier than I thought.

Your basic approach goes like this:

Search far and wide for an existing plugin Give up and realize you'll have to build it yourself Strongly consider building a releasable plugin Decide you're better off building a one-off integration Spend the next hour fiddling inside gatsby-node.js

Your goal is to read your data source and create Gatsby data nodes for each object you want to make available.

The general template goes like this:

exports . sourceNodes = async ( { boundActionCreators } ) => { const { createNode } = boundActionCreators ; } ;

You can see my full code on GitHub.

My goal was a list of videos from a YouTube playlist. I used youtube-playlist-info to fetch a list of videos from a public playlist. Google's official node.js library is too hard to use.

const ypi = require ( "youtube-playlist-info" ) ; const YT_KEY = require ( "./client_secrets.json" ) [ "yt_key" ] ; const LWyP = "PLF8WgaD4xmjWuh7FTYTealxehOuNor_2S" ; exports . sourceNodes = async ( { boundActionCreators } ) => { const { createNode } = boundActionCreators ; const items = await ypi ( YT_KEY , LWyP ) ; } ;

When Gatsby builds my site, it goes into gatsby-nodes and calls my node builder function. This uses ypi to fetch a list of videos from the hardcoded Learn While You Poop playlist.

Yes, that means building the site is now slow. It has to talk to YouTube's API every time, but it’s worth it.

Your next step is to build Gatsby nodes for each video in the playlist.

Nodes require a contentDigest so Gatsby can tell whether they've changed. To make that easier, I built a helper function 👇

const makeNode = ( node ) => { node . internal . contentDigest = crypto . createHash ( "md5" ) . update ( JSON . stringify ( node ) ) . digest ( "hex" ) ; createNode ( node ) ; } ;

makeNode is a thin wrapper on Gatsby's built-in createNode function that automatically generates an md5 hash of the whole node and saves it in contentDigest . Not sure why this isn't default behavior.

With that set up, you can build your nodes in a loop like this:

let lwypNode = { id : "lwypPlaylist" , parent : "ytPlaylists" , children : [ ] , internal : { type : "ytPlaylist" , } , } ; lwypNode . children = items . map ( ( { title , description , resourceId , thumbnails , position } ) => { const id = ` ytVideo- ${ resourceId . videoId } ` ; makeNode ( { id , title , description , thumbnails , position , resourceId , internal : { type : "ytVideo" , } , parent : "lwypPlaylist" , children : [ ] , } ) ; return id ; } ) ; makeNode ( lwypNode ) ;

Set up an empty node for the lwypPlaylist of type ytPlaylist . Fill its children with nodes that contain important data from the YouTube API.

When all those nodes are created, then create the main lwypNode . This reverse order is important. You have to build your data graph from the bottom up otherwise you'll get strange errors.

You can see me struggling with that in the video above. Lots of head scratching.

When your nodes are created, you can read them anywhere inside Gatsby with a GraphQL query like this 👇

export const query = graphql ` query LwypPlaylist { ytPlaylist(id: { eq: "lwypPlaylist" }) { childrenYtVideo { id title description } } } ` ;

Fetch a node of type ytPlaylist with id equal to lwypPlaylist . Inside that node, get all children ytVideo nodes and their id , title , and description .

You can then render them in a loop.

Component = ( { data } ) => { const videos = data . ytPlaylist . childrenYtVideo ; return ( < div > { videos . map ( ( video ) => ( < div > < h3 > { video . title } < / h3 > { video . description } < / div > ) ) } < / div > ) ; } ;

Full page coming soon.

Should I make a real YouTube source plugin for Gatsby? Ping me on Twitter.

Did you enjoy this article? 👎 👍

Published on April 24th, 2018 in Front End, Livecoding, Technical

Learned something new?

Want to become a high value JavaScript expert? Here's how it works 👇 Leave your email and I'll send you an Interactive Modern JavaScript Cheatsheet 📖right away. After that you'll get thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over my 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths. Start with an interactive cheatsheet 📖 Then get thoughtful letters 💌 on mindsets, tactics, and technical skills for your career. "Man, love your simple writing! Yours is the only email I open from marketers and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌" ~ Ashish Kumar Your Name Your Email Your Address Subscribe & Become an expert 💌 Join over 10,000 engineers just like you already improving their JS careers with my letters, workshops, courses, and talks. ✌️

Have a burning question that you think I can answer? I don't have all of the answers, but I have some! Hit me up on twitter or book a 30min ama for in-depth help.

Ready to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz components your whole team can understand with React for Data Visualization

Curious about Serverless and the modern backend? Check out Serverless Handbook, modern backend for the frontend engineer.

Ready to learn how it all fits together and build a modern webapp from scratch? Learn how to launch a webapp and make your first 💰 on the side with ServerlessReact.Dev

Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️