Static Blog With Next.js and Markdown

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey what's going on guys so in this video we're going to be creating a static blog with next js and markdown so next js if you're unfamiliar with is a react framework that gives you a whole bunch of extra features better seo better routing and so on and it's known for rendering react on the server side but it can also be used as a static site generator similar to something like gatsby although gatsby has some extra bells and whistles like the data layer with graphql and so on but next.js can be used to create static websites if you do things in a certain way so we're going to build this blog and basically all of these posts that you're seeing are coming from markdown files if you don't know what markdown is i'm sure most of you do but if you don't it is a very easy to use markup language if you've ever created a github repo with a readme file you've probably used markdown the syntax is very very simple as you can see here on the cheat sheet i do have a like a 25 minute crash course as well on youtube if you're interested you can literally learn it in 20-25 minutes all right so i'm not going to really go over the syntax of markdown now the project we're building is is pretty much based off of this dev space blog which is actually part of my full next js udemy course so we're going to get the posts in the same way this does have some extra features obviously it has you know search which with post caching we have pagination we have categories so if you're interested in building this and kind of moving beyond this particular tutorial i'll have the link to the course in the description but basically we're going to just show the posts we're going to be able to go to the single post and since this is a static website we have to generate these paths okay because everything is going to be re is going to be requested the data will be requested at build time since this is a static website all right but we'll get into all that now as far as how we're going to parse the mark down we're going to use a couple packages one is called marked this will be used basically for the post body which will be all marked down and as you can see here this is a low level compiler for parsing markdown and then we also have front matter to deal with so front matter you can think of as like the different fields so for instance we have a title an excerpt some other fields that's the front matter and we're going to use this package called gray matter to basically be able to fetch that parse it and display it here the title the date the excerpt and all that good stuff all right so that's we'll be building as far as the styling i just have some basic css that i use we're not using any kind of framework or anything this dev space blog we did use tailwind but i didn't want to add anything extra to this so let's go ahead and get started i'm going to open up vs code and i just want to mention that you should have some basic experience with next js and obviously react i do have a react and an xjs 2021 crash course if you need to watch that beforehand because i'm not going to go over the the you know the really basic fundamentals of next so let's get started here i'm going to open up a terminal and i'm going to create a new next application with create next app so let's run npx create dash next dash app and i want to put this in the current folder that i'm in which i just called next markdown blog all right so that's going to set up all of our dependencies for next and then we have two more dependencies that we want to install so let's do that npm install marked and also gray matter all right now that that's done we'll go ahead and run the dev server with npm run dev that's going to open up on localhost 3000 just make this a little smaller right and this should just show us the default welcome page for next good and i'm just going to make this smaller in this too okay and then let's start off by just kind of cleaning things up so in our pages folder we're not using any api routes so we can actually delete the api folder and then this index.js is our home page so i mean i guess i'll explain the the some of the basics real quick so each page is just a react component you can see this is a react component called home it's a functional component and make this a little smaller and anytime we create a component in the pages folder like let's say we have an about.js that'll allow us to go to slash about and that component will automatically render or that page so that's one of the the best things about next is the easy routing so this index.js is just the home page we're looking at and i basically just want to clear everything out of this so we're going to get rid of these two imports i guess we'll keep the head which it just allows us to to give it a custom page title description i just want the page title really so get out of there and um let's delete this class name we're just going to have one global css file and then we can get rid of all this the main tag and the footer tag so basically we should just have a div with the head we'll go ahead and change this here to um we'll just say dev blog and then right here for now let's just have i don't know an h2 and we'll just say hello so we'll save that that will get rid of all that boilerplate now this app this underscore app.js basically wraps around all of our page components so no matter what route we're on or what component we're seeing this wraps around it so if we want to put something else in here to display on every page like a header we could wrap this component in let's say an empty fragment and let's go right above the component and if i say hello here that's going to show so this is actually where i want to put our header but before we do that let's take care of our styling so as you can see this global.css file is being imported which is located in styles we can actually get rid of this home module this global css and it's just some some you know default css i'm going to replace this with um with my custom css so i'm just going to grab that paste that in now i mean you can pause the video and copy this if you want but you can just go to the github repo and get the file you know the global css you can copy it download it whatever you want to do and uh and just get that in there all right so i'll save that and that will give us our css and there's just some classes that i'll be adding along the way to add the styling all right and i just didn't want to spend time typing out css that's not what this video is about so let's go ahead and create a header and basically the two pages we're going to have is the home page that we have here and then the single blo single post page which we'll get to later but let's create the header first so i'm going to create a folder called components in the root here so components is just for any react components that are not pages such as the header so let's create a new file we'll call it header.js and i'm using the es7 react redux extension for vs code where we can just do underscore rfc that'll give us a function a compo function component and this is going to be pretty simple we're just going to use an html5 header tag here and i'm going to put a container class in here which i included in my css and then we want to have the the the logo or the it's actually just an h2 we want to have that as a link to go to the home page so i'm going to import link and that's going to be from next slash link so we'll go back down here and let's add a link so that's going to be 2 that's just going to be the slash and then here we'll use an h2 and we'll say dev blog okay now nothing's going to show up obviously because we haven't brought it in so we'll go to our underscore app.js and let's import header from our components file and then we're going to go right down here and just put the header right here and we'll save and now that should show up now the the rest of the content down here i want to be wrapped in a container so this component right here i'm just gonna i'm gonna have a main tag and give it a class of container and just move that up into there and you'll see that'll push that over a little bit so that should be all we need as far as this file as far as the header so now the index.js the home page is where we want to use a data fetching method to basically fetch our markdown posts now our markdown posts are going to go in the root in a folder called post so let's create that and each post i want to be able to have an image so in public which is basically just our static folder i'm going to create a new folder called images and then inside images will have another folder called posts and this is where you want to put all your your image your post images and i actually have some that i want to add here so i'm going to bring those over and you can just grab these from the github repo so we have image one through image seven because we're gonna have seven different posts okay but for now inside post let's just create a test i'll just say test and your markdown files are gonna have an md extension and basically every time you want to create a post you're going to create the front matter which is going to be at the top between three hyphens and you can put whatever fields you want so in this case we'll just say title test post and then we could do date say june 24 2021 and then an excerpt and let's do cover image so cover image we're going to do slash images because it's going to automatically look in the public folder and then slash pose slash image1 dot jpeg so that's your front matter basically your fields and then right here is where you put all your markdown and you can use markdown syntax like if you wanted uh h2 we could do that and say heading two if you wanted uh an unordered list you could just do asterisk say item one item two and i actually have an extension installed uh what is it called it's a markdown previewer right here so markdown preview enhanced and whoops and what that allows you to do is just right click and you can say markdown preview enhanced open preview to the side and you'll see it'll actually give you a preview of your post so whatever you type in here is going to just automatically show in here so you can basically pre preview your blog post all right so i would suggest either that extension or something like it but i'm just going to go ahead and save this for now so we have one markdown file so one post now we want to be able to get the posts that are in that folder and show them on the home page so we're going to be using one of the data fetching methods here called get static props so we'll say export async function get static props and this will allow us to fetch data at build time and we can actually use this to create a static website or to fetch data for a static website and the way this works is it return we return an object and we can pass in a props object and anything i want to pass back like let's say posts and for now i'll just set it to a string that says the post and then i can go up here into the the page component into the arguments here where props are passed in and i can destructure posts or you can do props dot posts and for now i'll just go ahead and console.log here posts and if i go over here and reload and we look at our console so basically every time this page loads it's going to go ahead and return those props now obviously we don't want this to just contain a string we want it to contain the actual posts so we want to fetch that first so let's go right here and the way we're going to do this is we're not working with any kind of like api you could of course do that you could your data could come from absolutely anywhere it could come from a headless cms like strappy or sanity.io or your own api anything at all but what we're doing is getting the files from this folder right here this post folder so i'm actually going to go up top here and i'm going to bring in i'm going to import fs from fs now this alone if i save this i'm going to get an error and the reason for that is this is not something that you can import on the client side and that's what we're doing right now we're trying to basically import fs the file system node.js module into react and that's not going to work however next.js is smart enough to know if you use this fs module down here and get static props which actually runs on the server side it'll work so let's go above this return and let's say const files and we can then set that to fs which has a method called read dir sync which we're going to use here and then we can pass in the directory we want to read which is going to be posts i am going to use the path module though right here so let's say path and then in here we'll just use path dot join and post so it's going to look in the root folder for a full folder called posts if i save that now we don't get that error in fact let's console log this just so we can see what's in files now and that's going to log down here since this is running server side and we're just going to reload the page and you'll see that what we get from files is an array of all the file names that are in the post folder which right now is just one test.md so the next thing that i want to do is create an array that's going to include all the slugs for the files as well as the front matter the you know the title excerpt all that stuff so let's just put a comment here so this will get files from the posts directory and then let's say here we'll put a comment we'll say get slug and front matter from posts and the way we'll do that is we'll create a post variable and we want to take that files array we want to map through it so basically we're going to loop through it and return something else from it so this takes a function so we'll say for each file name what we want to do first is create the slug and we'll do that say con slug and we'll take the current file name in the current iteration and then we're going to replace the extension so dot md should always be the extension we're going to replace that with nothing okay and then down at the bottom from this map i'm going to return an object with all of the slugs and then for now let's go make sure you go under the map which ends right here and let's just console.log posts and then we'll just reload the page over here and you should see an array that has an object with slug test so it should just be the name the file name without the um the extension and if we had more posts in here we would see more post more slugs now in addition to the slug we want to get the front matter so let's say get front matter and we'll do that let's create a variable here call it markdown with meta and we're going to set that to fs and there's a method on this called read file sync that we're going to use and inside let's close that up inside here we'll do path dot join and we want to look in the post folder and we want the current file name so current iteration file name and then we also want to just uh specify the utf-8 character encoding so we got markdown with meta now just to kind of show you what this gives us i'm going to console log it so mark down with meta and if i go over here and reload so you can see we just get like basically what's in the file right we have the the front matter here it's just kind of it's just exactly what's in the file including the front matter now to parse that front matter we're going to use that gray matter is that what it was called yeah gray matter package so let's go up top here and let's import let's see we'll say import matter from gray matter and then let's go back down here so we have this markdown with meta which is just basically what's in the file and we're going to so basically we're going to wrap that markdown with meta inside matter which is the gray matter package and we're going to extract from that so we'll use destructuring here and we should be able to get the data which i'm going to rename to front matter okay and then what we'll do is down here in addition to the slug we'll return the front matter okay and then we're going to console.log post and we'll see what we get so let's reload and let's take a look and you'll see now we have an op we have an array with one object with the slug and then this front matter object that has the title date excerpt in whatever other fields you have so now you know this we can now use so let's return let's get rid of this console log and instead of you know a string here we're going to return posts but i do want to so well we'll just return it for now because ultimately i do want these to be sorted by date so we'll add that in a little bit but let's just return that here we can actually just do this and then if we go up here where we're passing in posts it's console.log posts and let's go over here open up our console and reload and we should now see an array with a single post with the slug in the front matter we don't need the body the content because we're not displaying that on the the index page that'll be for this the slug page the inner page so now that we know we have access to the slug and all the front matter we want to display it here so let's go ahead and uh where we have this hello let's get rid of that let's have a class of posts and then we can we should be able to just create a list by using map so post dot map and in here we'll say for each let's put an arrow function we'll say for each post and then i'm also going to have the index and for each one of these for now we'll just return let's let's do an h we'll just do an h3 and we should have access to post dot and we should have the slug as well as the front matter so let's say front matter so front matter dot title we'll save and now we see test post now instead of just working with this this one test post because i just wanted to show you how to format it um i'm going to actually bring over a bunch of posts and just use those so you can get these in the post folder in the github repo so let me just bring these over into posts and i'm just going to delete the test here all right and now if i go back here and reload we should see all of those all those post titles okay anything we create in here and just to give you an idea we have the same front matter same fields and then just some some dummy markdown okay so now we can get the posts let's create a separate component for each post instead of obviously you know just putting an h3 in here so i'm going to go into components create post dot js and let's create a component here called post and that's going to take in a prop of post you know each single post and i'm just going to add i'm going to bring in the link here from next because we do want to link to the the more page or the the single page so let's say link from next slash link and down here i'm going to give this a class these are just some basic classes that i have in that css file so we use a class of card let's put our image at the top now the source is going to come from post which is getting passed in as a prop and then front matter and then what i call it cover image like that all right and then you know what we'll just save that for now and let's just see what it looks like so inside of our index our home page we're going to import post from components and instead of the h3 here we're going to map through create a list and output the post component which is going to take in the post as a prop and now you can see that we have all of our images all right cool so let's go ahead and finish this up this component under the image let's close that up so under the image here i'm gonna have the date this will be a div with the class of post date and i'm going to say posted on and then we can get this with post dot front matter dot date so any fields that you have in the front matter you can add you'll be able to access here and then under that let's do the title which i'll put in an h3 so here we'll say post dot front matter dot title okay so there's our title and then let's do the excerpt so i'm going to do a paragraph here and we'll get the post dot front matter dot excerpt i always have trouble spelling that okay and this should actually be responsive yeah okay so once we hit this point it'll stack and then the last thing we want is a link to the inner page so here this is where we're going to use link should be uppercase l and the href this is going to go to so it's going to be slash blog slash and then the slug which isn't going to work just yet but we do want to at least add this for now um and then in here i do want to class on this so i'm going to use an a tag with a class of btn just don't want the href on the a tag and then here let's say read more okay and if i click on that it does take me to the correct url it just doesn't work it's a 404 because we haven't handled that yet but we do have all of our posts here so if you remove a markdown file or add a new markdown file it'll automatically get added here and obviously this you know it's not ideal for like um a huge blog with a bunch of different authors but if it's your own personal blog or you just have a few authors you just come in add a new post a new markdown file throw an image into the images posts folder and that's that so pretty simple very fast static website but now what we want to work on is the inner page okay so the way that we can handle this we want it to be it's a url like slash blog slash and then whatever the slug so obviously since this is a static website we need to create these paths at build time and the way we do that is with a specific data fetching method called get static paths so first things first let's create a new page for this and since it's dynamic it's going to be slash blog slug slug could be anything we need to format this in a certain way for routing so i'm going to create a folder called blog because it we want it to be slash blog and then it's going to be the slug which is dynamic so what we'll do is use some brackets here and we'll say slug inside the brackets dot js and then i'm going to create a react component here for our page we don't want to call it that so let's actually call it post page and then whatever i put in here like if i say post if i click on one of these you'll see that it'll actually show whatever we have here now there's a couple things we need to do obviously we need to fetch the the data from that particular post from that markdown file we also need to statically generate these paths because this is going to be a static website and it needs to know the the paths beforehand and we need to do that based on the data so let's do that first before we actually put any you know content up here so we're going to do export async function get static paths so that will be to get the paths but we're also going to want get static props to get the data so let's do get static props as well and get static props i'm just going to return an object with props for now which will just be an empty object and let's start with get static paths now we do need to get the files so up here let's bring in we'll say import fs from fs and let's also bring in path okay and we're going to get that same error again because remember you can't just use fs on the client side so we have to make sure we use it down here so i'm going to go into get static paths and let's say const files and we're going to use fs.read directory sync or reader sync path dot join and we want the posts folder all right and let's just go to the inner page here so we're getting the files same thing we did in the other fi in the um in the home page and then we want to generate paths now the the way that this is going to work is this is going to return an object with paths right and the way that the this path is going to look is it's going to be an array that will have in some objects in it that will have params and then that params will be an object that'll have whatever you want the path to be now in some cases it might be the id like you might have slash i don't know slash recipe slash id then you would have id here and you would set that to um you know to whatever that id is id1 then you might have another one id2 in our case we want this to be the slug and then we want to fetch and create all the slugs from the files okay so this is essentially what this this path structure will look like um we'll just say like my slug so keep that in mind now let's go up here and i'm not going to keep this here this is just to show you the format of how we need to return this so let's create a variable called paths let's take the files and let's map through and we'll say for each file name then we want uh we're just gonna we're returning an object here an array of objects so we want to use parentheses since we're returning an object and inside this object we'll have params so i'm just setting this up just like this down here that i showed you that same structure and inside here we'll have params which is actually an object with a slug and the slug we're going to get from the current file name and we just want to replace just like we did before replace the extension dot md with nothing so we just have just the file name that's going to be the slug so that's how we want to format this and then all we have to do is is add this paths to this so just like that but since they're the same we can just do that and then there's also an option called fallback and we want to set this to false basically what this does is if you try to access a path that doesn't exist or a slug that doesn't exist i should say well i guess it's a path and a slug it'll just give us a 404 page 404 not found so we want to keep that at false all right actually you know what i should do is um just show you just console log paths here so i'm going to save that and reload just so you can see what that gives us let's see so let's go all the way down yep so here it is so this path is an array of objects with params and then has the slug okay so that's what that looks like now since we're returning that here the paths or the slugs in the past what we can do and get static props is we can now access in here we can destructure and we can get params and inside params we can get the slug okay so what we'll do what i'll do is just console log that so you can see what that gives me and then i'm going to go over here and reload and let's see what we get so you'll see django crash course if i go to javascript performance tips we're going to see that so we now have direct access to whatever the slug is inside get static props so now we just want to fetch that particular file data based on the slug so this part will look pretty familiar we're going to create a variable called markdown with meta and we want to set this to fs and then read we want to use read file sync and in here let's pass in path dot join and we want to look in the posts folder and then we want the file name which is also the sl well the slug is the file name without the extension so we're just going to attach to that or concatenate to that the dot md extension to read the file and then we just want to specify that this is utf-8 as our character set okay now this markdown with meta we're going to use once again we're going to use gray matter so let's go up here and let's import matter from uh from gray matter and then inside the com the page component itself we're going to be using marked so let's import that as well so we'll import marked yeah marked from marked and let's import link as well from next all right so down here let's then say matter and then mark down with meta and what we want to pull from that let's say const and we're going to destructure from that just like we did you know just like we did in in the other in the home page we're going to get data now this is the front matter so i'm just going to rename it to front matter and then we can also get the content which we didn't need in the in the home page because we weren't displaying the actual post but this time we are so we want to get the content from that okay and then what we want to return as props is going to be three things we have the front matter we have the slug and we have the content so those are going to be the three props that we return and then we can pass in here so we can say front matter slug and content now from front matter we can d we can destructure this further and pull out from that the title the date and what else the cover image i think those are the three things and then inside here let's just test this out by adding title we'll save that and you'll see we get javascript performance tips if i go to django crash course we'll see django crash course so we now have access to the data from that particular post so let's continue on with this we don't actually need a div here we'll just use an empty fragment and then inside here let's have a go back link so i brought in links so we're just going to have this go to the home page and i do want this to have some classes so i'm going to use an a tag here with btn and then i think i have a btn-back class which will just make the button light so in here we'll say go back let's save that so now we have a go back button all right then let's go underneath the link and we're gonna have a class of card and also a class of card page just some basic css and let's have an h1 here with a class of let's say post dash title and that's where we want to have the actual title okay so we'll save that good let's do the um the date so we'll have a div with the class of post date and let's say posted on and we should be able to just do date because we destructured that from the front matter okay the next thing we want is the image so image and the source is going to be the cover image okay there's our image and then we want the post body so let's say post body and then this is where we're going to use marked now we're basically inserting html when you do that within jsx we need to use something called an attribute called dangerously set in our html um which sounds kind of crazy but we know where our html is coming from it's coming from our blog post our markdown so let's say div and in here we're going to say dangerously set in our html and the way we set this is with double curly braces and then double underscore html and then whatever the variable or whatever it is that um that contains the html so remember we have content coming in right here so that's the actual blog post and that's what we want here however we want to parse it with marked so we're going to wrap that content in marked which is coming from that package that we installed okay hopefully that makes sense so let's save that and there we go so now we're seeing all that parsed markdown as html and if you were to you know look at this in the elements tab for instance this ordered list you'll see the ol tag so that this is all being parsed from our markdown file okay so that is pretty much it hey guys one thing i forgot that i want to do before we get to the deployment is the sorting because right now you'll notice that we have march 5th 4th and then 7th 7th 8th 5th so you probably want your blog post in order so let's go into pages and then index.js so our home page where we have our get static props we're getting all the posts we're getting the front matter we're returning the posts as props so what i'll do is set post to post dot sort and then in here sort is just a javascript method that takes in a function but instead of putting the entire function in here just to kind of keep it neat i'm going to have a utility called sort by date and we're going to basically bring that in from a utils folder that we'll create in a second so let's say import and we're going to import sort by date and that's going to be from let's see we're in pages we want to go dot dot slash utils okay that doesn't exist yet so it's going to give us an error so let's go into the root create a folder called utils and then in utils we'll create a file called index.js and i'm just going to paste in this function so sort by date takes in a and b we're returning new date and we're going to do b dot front matter dot date because remember we added dot sort onto the post so we have access to front matter and then date and then minus new date and then a dot front matter date so this is going to be descending if you wanted ascending then you would do a first and then b so let's save that and let's reload this and now you'll see the first one is march 12th and then eighth seventh okay down to fourth so now they're actually in order all right i just wanted to add that and make sure that that we sort these out before we actually wrap up the video so let's get back to the deployment now what's great about the way we did this is we can just export this as a static website so if we look in our let me just close this up here if we look in our package.json there is a build script so npm run build will build our build for production but there's a command called next export that will export your site as a static website so we can add on to this double ampersand next export right we'll save that and then i'm just going to minimize all these because it's going to create a new folder called out and that will be our static website so let's cut off the server so this isn't going to work anymore and let's do npm run build all right so it looks like i have a couple issues here so let's take a look at this so do not use image using all right so it next actually comes with an image component however when you generate a static site it usually complains about it unless you do some extra things so i don't actually want to use next image so it looks like we can just add this rule to the eslint file so i'm just going to copy this if you're getting this this warning you can go to rc and we can just add rules and here we're going to just paste that in and we're going to set that to off so that will take care of that next thing missing key prop for element in our iterator all right so in our home page i must have forgot the key i always do that so where we where we mapped through this and created a list of posts we just need to add on to this post a key a unique key and that's why that's actually why i passed in indexes so we could use that as a key i just always forget to do that past href is missing in header.js so apparently i need to add this to my link in the header which is right here so we'll add on that and then this is the same image complaint all right so we took care of that so we should be able to run this again npm run build okay so creating an optimized production build and it should also generate a static website in an out folder okay so export successful files written to slash out which if we look up here and check it out we have our index.html we have our images if we look in this blog folder now we actually have all of our posts that you know we start off in markdown are now html files okay now you do need to put this on a server or the paths will be messed up and the css won't show so what i usually do is i use a package called serve you can install globally on your machine just called serve like that and then i'm going to go ahead and run serve dash s and i want it to look in the out folder which is our static website and then let's do dash i think we can do dash p for port and then let's do 8 000 so basically it'll just yeah it'll run it on 8 000 so if i go to local host 8 000 there it is so there's our static website it's super fast i know there's not much here to really kind of test but this is basically mimicking if you were to deploy this anywhere you could deploy it absolutely anywhere it's just a static website now i think what i do want to do is deploy to versa versal is great for any next.js website just about um whether it's static whether it uses um api routes or anything so let's do that let's go to versal.com and i'm already logged in here you just you can just sign in with github and you can see i have two my two next js course um websites here but you do need to get it from github so let's create a new repo all right so we'll say new repository and i'm going to call this markdown now let's call it next dash markdown dash blog say simple blog using next and markdown all right and i'll make this public this will be the exact repository i have in the description and let's go ahead and copy this and then we're going to initialize a git repo and then let's add we should have a git ignore okay yeah so we'll just add all and then let's get commit um say initial commit okay so everything is in the local repository now i'm going to add the remote with the command i copied and then we'll go ahead and create our main branch and then we'll push to github all right so reload this there we go so everything that we created is now in this github repo so now i can just go over to versal and i'm just going to reload this and say new project and you'll see the the project i just pushed to github i'm going to import that use this personal account project name um i'll just keep as that i might not i'm probably not going to keep this up but i might keep it up for a little while so let's see build output settings we don't need to do anything there we don't have any environment variables so we'll go ahead and deploy okay so now it's gonna attempt deployment all right so it says congratulations your project has been successfully deployed we'll go ahead and visit and now we have a fully deployed project hosted on versal alright so i hope you guys enjoyed this like i said in the beginning if you want to add on to this and add search functionality pagination and some other things you can check out my next js course on udemy i'll have a link to that in the description with a promo code so thanks for watching guys i appreciate it and i will see you next time
Info
Channel: Traversy Media
Views: 34,342
Rating: 4.9670658 out of 5
Keywords: next.js, markdown, next markdown, react, javascript, next.js blog
Id: MrjeefD8sac
Channel Id: undefined
Length: 46min 40sec (2800 seconds)
Published: Mon Jun 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.