100DaysOfGatsby

1-Jan-2020
  • gatsbyJs
48 min read / 12717 words

Day 47

Feb 16 2020

Sad times today. I've released a first version of gatsby-plugin-prop-shop.

but... i wasn't anticipating failure, alpha tests have kind of suggested that PropShop is a bit useless 😂

When i built it i was thinking, this is great, i know i've needed functionality like this on many a project... but that's because i develop component libraries for my day job.

It would appear as though if you're developing your own blog or a theme, PropTypes and descriptions aren't really a priority. I somewhat disagree if you're building a theme because you'll want your users to know what each prop does in case they shadow the component and documenting the props would be very helpful in this instance.

However, what i learned from my alpha tests are that not a lot of people bother with PropTypes 😥.

I can understand this if you're developing in .js because there's no real reason other than for completeness to spend time writing out types and descriptions, if you're using TypeScript it's of course an absolute must! But from the alpha test PR's i created i noticed not a lot of Gatsby developers are using TypeScript.

All of this was an oversight to be honest because i was just thinking about what stack i use and how i approach a build.

I'm a huge proponent of Component Drive Development and correctly typing props and documenting them is a big part of this.

The other oversight is a pattern i've noticed where GraphQL queries are created using the new-ish Gatsby useStaticQuery method and then abstracted away in to a utils directory and then imported as and when required.

When using this method passing props around needn't occur at all as everything is returned within the component where the query is being used. I suspect in TypeScript you'd need to type the return but in .js land everything is so loose you can leave this un-typed and pass the data straight onto the .jsx no questions asked. 😬

So with that said, i've released a 0.0.1 anyway and tweeted a few people and rather than get hung up on failures, i've dusted myself off and come up with a new plan.

I'm going to build another theme!

I have for a while now been wanting to transfer my current commercial portfolio from Next.js to Gatsby and i had intended to use gatsby-theme-gatstats for both my portfolio and my blog.

but...

After digging around in the GatStats repo after having learned a lot from my recent work i think GatsStats needs a bit of an overhaul... i'm not sure when i'll tackle this and attempting to rip out methods to replace them with some new things i've learned might become messy so i've decided to start a new theme and i'll try out some new methods and see how it goes.

I'm not too disappointed with GatStats, it was my first theme after all, in fact it was the first thing i built using Gatsby so there were mistakes made along the way but that's just all part of the process ay!

Day 46

Feb 15 2020

It's been an absolute belter of a day today!

I started the day by refactoring some quite gross 🤢 functional programming i'd done in gatsby-plugin-prop-shop and i think second time round i've made the "totals" object a lot neater and streamlined the amount of times the GraphQL array needs to be looped over.

There's probably a significant performance increase but i'm not too worried about testing that at the moment.

Next up was to find a Gatsby theme written in TypeScript so i could test PropShop with .tsx files or more specifically interfaces

Fellow Gatsby fan Rich Haines has a sweet little theme for adding SEO data to your blog, you can see it here.

So i forked that repo and added gatsby-plugin-prop-shop

There are some differences between the way react-docgen returns data from PropTypes vs interface(s), the main one being with PropTypes all data objects are returned with an id, with TypeScript they don't, which was throwing my table header out of whack.

To resolve this instead of trying to get data from the GraphQL query i just manually created an array of table headers and that was that sorted.

I then forked theme-ui 😬 and set about adding PropShop to the docs so that i could see PropTypes for theme-ui/components. It worked first time amazingly even though the components directory is in a different package!

I did have an odd style issue so i've set the prop-shop page wrapper to be position: absolute so no matter which site or blog PropShop is used in that page will always cover anything else defined in a default layout.

I've also written a blog post about PropShop, which if you're interested you can read here

I'm still very much in the alpha phases of development and i now have x4 PR's open and am looking for feedback before i'm ready to release a first version of the plugin so if you're reading this and want to help, tweet me @pauliescanlon

Day 45

💖 Feb 14 2020

Today was a bit of a maintenance day on gatsby-plugin-prop-shop there were a few things i'd noticed as part of my alpha tests as mentioned yesterday with styles not quite being as i wanted them so i've been over all the css and tidied up a few things.

I also took another stab at the filtering, previously if you start to type you can filter out files containing props that don't match your search term but props from the same file still appeared in the list. The new filtering system hides any prop from any file that doesn't match the search term which makes using PropShop a much better experience.

I've still got a bit more tidying up to do before i release 0.0.1 and ideally i'd be able to see both PR's i created for Scott Spence and Eric Howey on their respective projects completed.

On that note however, when speaking with Eric he mentioned he'd not really used PropTypes that much and looking at his project i can see why. A lot of the components use a hook to grab the data so in theory all the components manage their own data source internally and don't require props to be passed in. It's a pretty sweet approach and i might "borrow" it for gatsby-theme-gatstats

I've also been thinking about how PropTypes are kinda optional in straight .js world so perhaps a lot of people developing Gatsby projects won't even use them if they're developing in .js... .ts however you have to have props defined in an "interface" or as a "type" or you get IDE errors left, right and center so i think this will be the next thing i investigate.

It looks like from the react-docgen docs that TypeScript "type" is supported... not sure about "interface" so i'll look into it and see what's what.

Day 44

Feb 13 2020

🚨 We have an alpha release of PropShop!

Yup, Yup, Yup. Today i've released an alpha version of my new Gatsby plugin gatsby-plugin-prop-shop

As you can see it's been renamed from "Project Prop" to PropShop... watta you think?

I started the day by forking a couple of repos from trusted Gatsby dev pals, Scott Spence and Eric Howey and added the plugin to their gatsby-config.

Problem No.1 was i'd set the path for gatsby-source-file-system to path.resolve(src/...) which will resolve to the demo running the plugin not the theme where it's installed. In most cases theme developers will want to inspect PropTypes for components in their theme not in the demo running the theme.

That's now changed to accept a full path of where to find .js files containing PropTypes.

Problem No.2 was as suspected style related. I was using gatsby-plugin-theme-ui for the styles but when running the plugin in a theme or, demo of a theme that was also using gatsby-plugin-theme-ui the theme object was getting overwriting and i was losing all my styles because the theme or demo theme wins out.

The resolve was to still use theme-ui but not the Gatsby plugin version which meant i needed to wrap the prop-shop.js page in a <ThemeProvider /> ... no big deal there.

I have seen a few other issues where some of my styles pick up the theme styles, things like global typography rules do affect my typography rules if i've left a css value unset. I think i can sort this by being more strict with my styles and setting things that i was taking for granted as browser defaults.

So there ya go. If you're into PropTypes and documenting components PropShop can give you a helping hand!

Enjoy!

Day 43

Feb 12 2020

So close now!

Happy to report i've very nearly completed all work required to launch an MVP of "Project Prop" looking at what i've done i'm confused as to why it's taken me so long 😂. That said, i'm finished with all design, all styles and i only have a tiny bit more functionality to add to allow for table sorting but i might not launch with this as i'm keen to get testing.

I've got the build pipeline sorted in Netlify, prepared a nice open graph image but will need to add some SEO back in to the demo but that shouldn't be too much work and i've started writing the README.

After that all i really need to do is publish it on npm... then let the world know... and by world i mean my 400 followers on Twitter 😔

That's it for today, no real problems or headaches i just cracked on and all is well!

Day 42

Feb 11 2020

Another good day today! 😃 I did have to do some traveling so lost a few hours of sweet sweet developing time but i think i've made up for it.

After yesterdays progress with the design of "Project Prop" i've moved back to development and have implemented all the new styles apart from some small data visualizations which i might try and attempt in pure css. I think i have a repo for an old project where i created some css only donut charts.

One thing that continues to play on mind is that i'll really need to test this plugin against multiple Gatsby projects.

Whilst i'm confident in the JavaScript because i'm using react-docgen to generate all the data to fill the prop table i'm unsure how the styles will cascade.

To give you some context "Project Prop" is a plugin but it works like a theme.

When you install it and spin up your project you can visit eg http://localhost:8000/project-prop/. The plugin has already generated the page that will appear on this route as it gets bundled in with your site or blog build as part of the gatsby build / gatsby develop process... but so too will the styles.

I've tried to name tokens in my theme-ui config in such a way they won't clash by pre-fixing them with a "pp" but given that this is a theme and themes are supposed to provide all the styles for the project i'm worried they'll try and overwrite styles defined by the user.

I'm currently developing a demo using the Gatsby starter blog and it works ok but it doesn't implement theme-ui so i'm not sure if they'll be complications further down the line.

I think what i'll do is release a 0.0.0-alpha version then perhaps pull some ready made Gatsby themes and see what happens when i add this plugin... should be fun!

Day 41

Feb 10 2020

Feeling good today. 😃

I put in a proper shift and made some excellent design progress on "Project Prop" i have the MVP design and interactions all sorted and i even managed to design a logo.

I know from previous experiences that for me, attempting to design in browser doesn't really do me any favours but i do like to kind of prototype stuff and then if i think it's a good idea i go ahead and design that functionality. Better that then designing a load of things and then finding out they can't be done... seems like a waste of time!

Having said that, there's a few extra things i've put in the design which i haven't prototyped, namely the sorting behavior of the "PropTable". It will probably be fairly straight forward so for now i'm happy for this to be part of the MVP.

That's kind of it for today. Design is not my favorite thing to do but it is always good to dust of the old skills and...

i reckon i still go it! 😎

Day 40

Feb 9 2020

Sometimes i really struggle with functional programming, i think it's because i'm not from that background or maybe my brain is wired differently but the problem i was having yesterday with filtering a deeply nested array was quite easily soloved with the array.some method.

some tests whether at least one element in the array passes the test implemented, this was all i was really looking to do, but instead i was messing around with map which of course returns a new array, and then trying to filter that.

some returns a boolean value and from there you can do what you want with the return value.

Anyway, i now have all the search and filtering functionality implemented to create what i suppose will be an MVP of "Project Prop".

I have an overall plan of what i'd like "Project Prop" to do but there's a little part of me that is working it out as i go and as i'm using it i'm thinking about what other functionality should be added in.

I have to go back to the design phase a little bit now as i'm not sure where some of the filter options should be positioned and this is way easier in design that it is to move styles and props around in code.

So tomorrow's plan will be just that, a little bit of pixel pushing then back on to the code. I also need a logo at some point so that'll be fun!

Day 39

Feb 8 2020

Not an overly productive day today. The good news is i'm finally back on "Project Prop", the bad news is I’ve run out of JavaScript talent.

Maybe I’m just having one of those days because I can’t for the life of me work out how to do some pretty tricky filtering. I have a search input kinda thing working but I need to filter a nested array from an array of objects and still return the parent object if it’s child array contains what I’m filtering against, but filter out anything that’s not a match for the filter.

Hopefully a good nights sleep and an offline re-think will get me over this small hurdle.

It’s probably the most important part of "Project Prop" as it’s what will be used to aid users in inspecting prop details / descriptions.

Part of me wants to move on to another part of the project, the bit that I’ll probably enjoy more as it’ll be mostly data visualization but I feel giving up on this first issue before I’ve solved the filtering problem won’t help me in the long run.

Day 38

Feb 7 2020

Challenge accepted and challenge completed.

gatsby-theme-gatstats now has a contact page hooked up with Netlify's built-in form service ... which is truly magical!

I've completed the work on the components used in the demo contact page and set it up using Formik and i've also thrown in some sweet validation using Yup

All the components used in the demo are available as shortcodes so you don't need to import anything to use them in the theme... but because this is a theme i've not included Formik or Yup.

I feel at this point it's best to leave that up to whoever is using the theme to decide how they'd like to handle forms and form validation.

I was thinking about adding a few more form components to the theme shortcodes, radio or checkboxes might be handy but until i hear from end users i'll shelve development on the theme for a while as i really want to get back to "Project Prop" and i still need to update all the posts in my commercial portfolio which i'm putting off... but... it was great to finally take part in one of the actual challenges set out by #100DaysOfGatsby

Day 37

Feb 6 2020

Today was another travel day and i think they'll be a few more before i find my vibe. But, i have done some work today on the form elements.

I've created form, text input and text area components, all work via "shortcodes" because they've been added to the components object of the MDXProvider which means they can be used in any .mdx file within the theme, no imports required!

All of the components in gatsby-theme-gatstats are documented in Storybook and i've tried to write a few unit tests where applicable.

This will probably be a job for tomorrow now, then i can look in to the magic that is Netlify's built-in form service

Day 36

Feb 5 2020

i didn't have an opportunity today to actually right any code but i did do some thinking about a conversation i had on Twitter last night.

It started because it dawned on my that i've not actually completed any of the task set out by #100DaysOfGatsby, this is largely due to having spent some months working with Gatsby and i feel i've already accomplished the first few tasks in one way or another...

...until now!

I noticed the challenge for week 6 was to integrate a serverless form solution, this is something that might be useful in my theme gatsby-theme-gatstats as currently there's nothing in the demo relating to a "contact me" page.

I had a look over the links in the challenge email and there's a mention of using Netlify's built-in form service and at first glance it appears to be really straight forward and all you really need to do is add an attribute to a form element and Netlify does the rest.

Now, this sounds great if you're building you're own blog or developing a site for someone else but i did wonder how it would work within a theme.

I've come to the conclusion that the theme doesn't really need to expose this functionality as it then limits the themes users to only using Netlify forms. Instead i think what the theme can do is provide some UI components that will work if they're dropped in to an .mdx file... yesssss the joy of .mdx

So that's what i'm gonna do, i'll probably create two new components, an input field that will spread the props for an html input element and a text area component, probably the same deal with the props. The theme is written in TypeScript so i might need to explicitly define the "netlify" attribute and perhaps i'll create a "contact" page in the demo site, plus add some documentation to the README and because i'm using Storybook to develop the components i can also add some notes in there about how to use the form components.

I think that's the theory done, now i just need to write some code.

Day 35

Feb 4 2020

Today was a travel day...

London Heathrow - Colombo Sri Lanka. I'll be here for the next 30 days working on various Gatsby related things.

For those of you who don't know, i'm a contractor, i have been self employed for nearly a decade now and have learnt along the way it's important to take time off to up-skill.

The main reason is when you're a contractor, you're the person "they" bring in because you know what you're doing... but i do sometimes find that whilst on contact i'm not really learning anything.

Of course working is great as i need to earn a living but if i only work and never up-skill, at some point i'll be out of touch with what's going on.

This is my main reason for taking the next 30 days off to up-skill. Granted i could have done this in England but why not travel and see the world and more importantly ... be warm!

The next few days might not be that productive as i've got a bit of admin to take care of but i did manage to do some work on the fight without internet access, and because of this i decided to finally transfer my commercial portfolio over from a site i built using next.js and a self hosted headless version of Ghost CMS on digital ocean.

It was actually the reason i built my theme in the first place. I wanted to have a commercial portfolio and a blog that shared the same look at feel. I also wanted to go serverless which lead me to discovering Gatsby.

I've pulled down all the content i need from my CMS and have started to create new posts in the new site which uses my theme gatsby-theme-gatstats. It's quite a boring task if i'm honest but i think i'll just chip away at it over the next few days as i can do most of the work without internet access.

That's all for today. I'm hungry and tired!

Day 34

Feb 3 2020

A fantastic day today! I've been continuing to problem solve an issue with gatsby-mdx-embed and i'm pleased to report, it's fixed!

The way the plugin works is by using the wrapRootElement api in both gatsby-browser.js and gatsby-ssr.js which does what it says on the tin and wraps the root element of the site with a component from the plugin.

In the case of gatsby-mdx-embed it's wrapping the root element with the MdxEmbedProvider, this in turn wraps the root element with an MDXProvider which handles the passing of React components from .mdx and executes them so they render in the dom.

In all cases when running gatsby develop this "wrapping" was working as expected but users were seeing issues when running gatsby build.

I started my bug fixing investigation by adding a div with a border around the MdxEmbedProvider and found that when i ran gatsby develop it was there but not when running gatsby build

This explains why users were seeing the problems with the components not rendering as expected but it took a little more investigation to work out why.

It turned out in my case to be the method i was using to export the MdxEmbedProvider in gatsby-browser.js and gatsby-ssr.js

see below

// gatsby-browser.js
export { wrapRootElement } from "./wrapRootElement"
// gatsby-ssr.js
export { wrapRootElement } from "./wrapRootElement"

and wrapRootElement looks like this

// wrapRootElement.tsx
import React, { FunctionComponent } from "react"
import { MdxEmbedProvider } from "./components/MdxEmbedProvider"
interface IWrapRootElement {
element: React.ReactNode;
}
export const wrapRootElement: FunctionComponent<IWrapRootElement> = ({
element,
}) => <MdxEmbedProvider>{element}</MdxEmbedProvider>

The first thing i changed was the name of this "component" because wrapRootElement is part of the gatsby api and i wasn't sure if something was getting screwed up due to a clash in names. I've since changed the name of this file to provider.tsx

The second thing i looked at was the method of exporting the module, this now looks like the below

// gatsby-browser.js
exports.wrapRootElement = require(`./provider`)
// gatsby-ssr.js
exports.wrapRootElement = require(`./provider`)

and the provider now looks like this

// provider.tsx
import React from "react"
import { MdxEmbedProvider } from "./components/MdxEmbedProvider"
interface IProviderProps {
element: React.ReactNode;
}
module.exports = ({ element }: IProviderProps) => (
<MdxEmbedProvider>{element}</MdxEmbedProvider>
)

Whilst i think i could have kept the ES6 method for exporting in gatsby-browser.js it wasn't working in gatsby-ssr.js.

Changing the method in both files seems to have done the trick.

At this point i released 0.0.16 but then due to some weirdness with re-naming the file from Provider.tsx to provider.tsx i had to release 0.0.17 but either way this is now fixed! Here's the full run down #11

Boogy time!

Day 33

Feb 2 2020

Kind of productive day today. I'm continuing to bug fix gatsby-mdx-embed.

At this point however i'm not entirely sure there is a bug with my plugin. I've spun up a minimal repo and installed all the relevant peer dependencies and have installed one of the "problem" plugins that was reported to have been causing issues.

So far i can't re-create the problem. Which leads me to believe it's not a problem with my plugin but might be related to having a project that uses multiple MDXProviders

I did update the README and have explained how to manually wrap the MDXRenderer with the MdxEmbedProvider which is effectively what the plugin is doing but it does appeat that importing and wrapping manually solves all the problems.

I'll continue to investigate this tomorrow.

Day 32

Feb 1 2020

Today was a bug investigation day. I've had two issues raised now relating to gatsby-mdx-embed and what appears to be a "clash of the providers".

The plugin works by wrapping a sites MDXRenderer with it's own MDXProvider. This provider is called MdxEmbedProvider, and is handled by a gatsby-ssr method called wrapRootElement

This is the core of the plugin and means that by adding @pauliescanlon/gatsby-mdx-embed to your gatsby-config the plugin can catch any components referenced in .mdx files and converts them into the components defined by the plugin.

Unfortunately when other gatsby plugins are used in a site that also use this method it prevents the custom MdxEmbedProvider from working correctly.

There is one work around that seems to do the trick and that's to manually wrap the MDXRenderer with the custom MdxEmbedProvider.

eg:

// layout.js
<MdxEmbedProvider>
<MDXRenderer>{body}</MDXRenderer>
</MdxEmbedProvider>

This indeed solves the problem but i'm still not sure why when you have multiple plugins that use the wrapRootElement you experience these bugs.

While developing the plugin i asked @chrisbiscardi if he knew of any reason why multiple providers couldn't be used. This was his response.

Multiple providers will merge the components object. Last provider wins

I'll continue to investigate this bug and hopefully be able to release a new version with a fix in the coming days.

Day 31

Jan 31 2020

Not a whole lot of code completed today but i have been tinkering with "Project Prop". The code i have done today has been to sense check that i can later implement what i'm designing. I do find myself doing this on my side projects where i'll do half in browser and half in "a hem" Photoshop ... yeah i need to switch over to Sketch!

I usually start with a prototype and build it to kinda prove that i have at least some kind of functionality in place, then i attempt to design it all in browser, then i get fed up with it not looking the way i want and then finally i give in and open Photoshop.

That's what i've pretty much done today, i will say however experimenting with the CSS as i go does at least mean that i know i will be able to build what i'm spending time designing.

I've made good progress today and have also been playing around with fonts, colors and table styles. Fortunately a lot of the CSS i will need in the prop table can be borrowed from one of my other Gatsby plugins gatsby-remark-sticky-table.

I've also had some other thoughts about how to extract what i feel will be some useful prop related information and display it in a kind of data visualization way. Who knows, there may be donut charts in "Project Prop"

Day 30

Jan 30 2020

It's been a slow day. I started the morning by investigating an issue with gatsby-mdx-embed reported by Scott #133 turns out it was a clash of MDXProviders and a little re-jig was all that was required to fix it. I should probably add a comment to the README explaining what to do if this happens.

Other than that i've been wrestling with tables and css on "Project Prop" it's coming together but it's taking me longer as i don't want to put my design hat on ... knowing full well i will have to eventually but it's fun to design in browser!

Day 29

Jan 29 2020

Had another pretty successful day today, i continued working on "project prop" and after chasing my tail for a bit i've changed tact slightly.

To start off my thinking was to create a plugin, and i approached this the way i have with some of my other plugins but i realized after a few hours of banging my head against a brick wall that some of what i need to do is already supported out of the box if i take the theme approach.

So that's what i've done.

"Project prop" name tbc is for all intents and purposes a plugin and will act like a plugin but under the hood it's actually a theme which is a little confusing but now i've got my head round it i think it's the right way to go.

The next issue i'm facing is the style stack.

My initial thought was to use theme-ui but what i'm finding is that i'm accidentally overwriting styles in the host site. This is the expected behavior of a theme-ui so i can understand why it's happening, the problem is of course how to stop it from happening. I need to go back over the theme-ui docs and see if there's an escape hatch or perhaps some kind of order of specificity class name i can use somewhere.

Failing that i might be tempted to use StyledComponents or maybe even go back to CSS Modules or Scss.

In either case i'm pretty happy with my progress today and if i can solve the styling problem i can carry on with some Design and UX work.

Day 28

Jan 28 2020

Today has been pretty chilled. I've solved a lot of the problems with the two main projects i've been working on and i'm happy for them to be used and i'll be keeping an eye out for issues or feature requests which i'll continue to work on as and when.

I'm pretty new to open source and i've gotta say it's pretty cool that people like my stuff enough to use it and to raise issues and contact me on twitter.

I'm enjoying hearing about use cases and in quite a lot of cases i feel these issues are actually really nice improvements... so a big thanks to anyone who i've spoken with lately!

Since there's no fires to put out i decided to kick start another project that's been in the back of my mind for a while. It's quite pertinent to my day job of developing custom React component libraries - for companies that make bazillions, and for almost 4 years now my go to, must have tool has been Storybook

If you've never used Storybook, you should, it's amazing! It's ideal for Component Driven Development as it allows you to just focus in on the one thing you're working on and not worry about the larger application... well some times you might have to consider where the component will end up but usually i aim to solve for the 80% of use cases... but....

One thing missing from Storybook is a method to provide an holistic view of all the props, not just the ones in the component you're developing on that day. The prop tables in Storybook are second to none, don't get me wrong! but you can't easily see the props and prop descriptions you wrote for a similar component four sprints back. To see these i usually open another browser and put the windows / stories side by side, or use the split view option in VS Code.

But this sometimes still isn't good enough.

One important factor in the creation of Component Libraries is api consistency"

By that i mean it's really not good having a prop called CardHeader on a <Card /> component and then having a PanelHeading prop on a <Panel /> component, or worse, a prop that is actually a header / heading but called something completely different.

So i've started to think about writing a plugin that will provide me with a single view of all my props and their descriptions, i'd hope to be able to filter / search, sort and perhaps even spell check all in one place.

The method for delivering this i think at the moment will work very similarly to how Jest create their coverage reports. You run a build on it and it creates a static site right there in your repo, you can of course .gitignore the directory or deploy it.

Given that creating static sites is kinda the Gatsby thang, it seems like an obvious choice, but i have run in to one or two problems with it today. Mainly how to create the static build bundle and move it to somewhere more useful... all from the plugin.

I think i'm on the right track and i'm sure i'll have more to say tomorrow.

Toodle-pip!

Day 27

Jan 27 2020

Another sweet ass day today!

I've refactored gatsby-mdx-routes to use TypeScript and now it follows the same yarn workspace pattern as gatsby-mdx-embed and gatsby-theme-gatstats which is important to me as i'm working across multiple projects and just prefer it if they can all be developed the same way.

I did have some problems though. First off i'm not using babel/preset-env because Gatsby's static query can't be compiled by in a plugin like i'm doing so i have to just convert my .ts to .js as ES6.

I imagine when the plugin is used by another Gatsby project the compiling to browser friendly code will be taken care of by the Gatsby project using the plugin. 🤷‍♂️

Once the .ts was compiled to .js as EE6 i started to see a "multiple graphql query" error, this was because i had named the graphql query and it can't exist in both .ts and the compiled .js in the same project.

Removing the name of the query cleared this error... not sure if there's a more complicated issue i'm yet to find about using unnamed graphql queries? time will tell.

I also found that using staticQuery in gatsby dev was fine but when i ran gatsby build and gatsby serve i was seeing gatsby Loading (StaticQuery) instead of the graphql response. I did have a read of some GitHub issues but couldn't find anything solid so just decided i'd just give the new useStaticQuery hook a go! and boom 💥 it worked.

gatsby-mdx-routes is now fully converted to TypeScript! ... i've just gotta go back over my code and correctly type everything 😫

Day 26

Jan 26 2020

Pleased to report i had an excellent start to the day!

My investigation into how to solve this docz site TypeScript prop tables issue went really well and i found that by shadowing the Props component from gatsby-theme-docz i was able to re-wire the props to enable correct and full population of the prop table.

This his how i did it.

  1. Shadow the Prop component by creating a new one in my demo site at demo/src/gatsby-theme-docz/Props/index.js

  2. Remove the prop prop from the component, which i think is actually the of prop

  3. Create a new prop called name

  4. import and use the useDbQuery hook 🎣

  5. Filter the useDbQuery by the new name prop

  6. Pass the result on to the Prop component

The new component now looks like this:

...
import { useDbQuery } from "gatsby-theme-docz/src/hooks/useDbQuery"
export const Props = ({ name, getPropType, isToggle }) => {
const db = useDbQuery()
const entries = Object.entries(
db.props.filter(
prop => prop.value.length > 0 && prop.value[0].displayName === name
)[0].value[0].props
)
return (
<div sx={styles.container} data-testid="props">
{entries.map(([key, prop]) => {
return (
<Prop
key={key}
propName={key}
prop={prop}
getPropType={getPropType}
isToggle={isToggle}
/>
)
})}
</div>
)
}

...and to use it i now do this,

<Props name="Gist" />

instead of this

<Props of={Gist} />

I'm not sure if this is the best way to make this work but i think until docz have a more solid way of creating prop tables for TypeScript components it'll have to do.

I've tested this in dev and in prod and it works!

So, as of this morning i released 0.0.15 of gatsby-mdx-embed which is fully working with TypeScript and populated prop tables in the demo site

🥳

Day 25

Jan 25 2020

Had another day of wins and loses. I got docz site prop tables finally working and it's able to read props and prop descriptions from my TypeScript files

but...

only when running in dev not prod!

This is both mad and extremely frustrating!

When i run gatsby develop all is well, when i run gatsby build then gatsby serve i get a flash of prop tables, then nothing.

My current course of investigation is to shadow the Props component, work out what it's doing and try and find what feeds it the props prop.

I think at the moment this comes from the docz core which is not part of the theme so there's nothing i can really do from my end 😢

but...

i've had an idea which involves using the useDbQuery hook and passing the props on to the Props component manually.

This so far is proving very difficult but using a lot of console logs and a number of JavaScript array methods i think i can manipulate the data into a shape that will work in both dev and prod.

Day 24

Jan 24 2020

Tricky day today.

On one had it was great, i've got babel and tsconfig playing together nicely and the two combined take my .tsx files and output browser friendly .js

This is perfect, and now i feel like i have a much better understanding of both tsconfig and babel.

I've also learned that no matter what your "main" key in package.json is doing Gatsby ignores it and always looks to the root of your project forgatsby-browser,gatsby-ssrandgatsby-config. I suspected this was the case but thought that i might be able to work round it.

I've also got both the plugin and demo dev processes working together.

The demo site for gatsby-mdx-embed and the plugin code exist in a monorepo controlled via yarn workspaces.

In order to develop the plugin code i need babel running in --watch mode so that when i start the Gatsby develop process both projects hot reload when i make a code change. I was able to accomplish this with npm-run-all.

Things were going well until i had to address the docz site propTable issue again and i've spent nearly 8 hours trying to find a way to make it work.

docz site can read props from components in a monorepo if you tell it where to look, naturally it works with React PropTypes and using a boolean in the docz config it can also read TypeScript interfaces and populate propTables.... but no matter what i did today i couldn't get it to work.

I'd all but given up hope until i posted a message on Spectrum and watta ya know Rakan Nimer one of the maintainers has replied.

If you read along that thread he's suggested changing the repo setup. This might mean dropping Yarn workspaces but if that's gonna make these bloody PropsTables work i'm all for it!

Day 23

Jan 23 2020

Hmmmm TypeScript! I thought i'd sorted this already but after my old chum Scott started using gatsby-mdx-embed he noticed that he was seeing some TypeScript related issues.

This plugin is written in TypeScript but it should transpile back down to commonjs so you can use it in both TypeScript and JavaScript projects. This wasn't quite the case!

I've since been using babel and gooooood lord is it great! I've done TypeScript setup in the past and it was always a combination of mashing tsconfig, babel and webpack together until you had a config that worked.

This was always a ball ache because you'd have to maintain both babel and webpack but now i've discovered babel 7 it's got so much easier!

The tsconfig is still a little bit of a mystery to me but the new babel presets make sense, even if you just read them by name it's pretty clear what they do.

"@babel/preset-env"
"@babel/preset-react"
"@babel/preset-typescript"

This is pretty much all that's needed to covert back to browser compatible JavaScript and with only a few settings in tsconfig setup it's just a case of setting the input and output for babel and it goes off and builds out .js modules!

"build:js": "babel src --out-dir lib --extensions \".js,.ts,.tsx\" --source-maps inline",

This was all going really well until i ran into that docz site issue again with it not populating prop tables... gonna come back to that, the more pressing issue is i think i've got some weird Gatsby thing going on.

Babel now coverts all .ts to .js and moves it in to a lib directory, my package.json has a "main" key which points to this lib directory but for some reason gatsby-browser.js and gatsby-ssr.js never seem to run.

I've put the word out so hopefully i'll get this resolved soon!

Day 22

Jan 22 2020

Had a pretty sweet day today, i continued working on gatsby-mdx-routes and focused on the on the issue i described yesterday which was to enable a way to create a dynamic recursively created navigation object based on slugs... what a mouthful!

Taking a step back for a second i'll describe the problem as i see it.

When creating navigation in any website you need to think about the depths a route might be at.

Example, a top depth navigation might look like this

|-- home
|-- services
|-- contact

...which is pretty easy to display an an html list, but then you get to a navigation element that might have a second or third depth, eg;

|-- home
|-- services
|--- web design
|-- user interface
|--- web development
|-- front end
|-- mobile first
|-- backend
|-- contact

At this point you need a way to have nested navigation elements within headings, and since you don't know how many levels deep an element might be you need a solution that will cater for an element that could be 10 levels deep.

I've seen a lot of examples of this problem 'solved' by suggesting the use of a frontmatter property that can be used to group menu items together by a parent heading.

If you're creating this in your own project then that's fine, you're in charge of both the frontmatter and the graphQL query that fetches the data... but what if you're not?

You may or may not know that if you add a property to a graphQL static query and that property is not found in at least one file in your file system you get an error.

This is the problem i faced with gatsby-mdx-routes, if i add a property called menu for example, then at least one file in the project must contain it, but if you don't want to group your navigation elements you'd still need to add this property to frontmatter to avoid getting an error.

There are a couple of solutions to this.

  • I could create a hidden file somewhere in the plugin that can be used as a place where all frontmatter properties exist but the file is never rendered... 🤢...
  • Set a default using createSchemaCustomization in gatsby-node.js ... again 🤢

Until Gatsby resolve what i understand to be a really complicated problem of allowing the graphQL static query to fail gracefully if no frontmatter is found then i'm sticking by my original thoughts.

"I don't think the answer is to add any additional properties to frontmatter"

Which leaves me with one other option to determine how a navigation element should be grouped... slugs

You'll have probably seen when you inspect slugs that they represent a location on your file system, the chances are you've put all your blog posts in a posts directory in your project, you might have even created sub directories for year and month.

All this information is contained within the slug and in effect all we're trying to do in the browser is mirror what your file system is doing.

A visual example....

|-- home
|-- services
|--- web design

Given the above directory structure the slug(s) would be as follows;

  • home = "/"
  • services = "/services/"
  • web design = "/services/web-design/"

This is all the information we need to determine how many levels deep any given navigation element is... but getting at it was a real challenge for me.

My approach was to split the slug using slug.split("/")

;["", ""]
;["", "services", ""]
;["", "services", "web-design", ""]

Then i remove the empty strings so i'm just left with what is effectively an array of parents and children.

There is a bit more to it, but the code can be see here if you're interested.

Using this slug approach i don't need anyone using this plugin to do anything to their frontmatter, meaning i think this could easily be implemented into a blog / site that had loads of pages just as easily as it could be to a brand new project.

There's more info about how to use this plugin in the README and here's a very computer science looking demo

Happy routing! 🚌

Day 21

Jan 21 2020

Recursive functions continue once more. I mentioned yesterday about an issue that had been raised with gatsby-mdx-routes and after a little digging it think one of the problems can be solved with a recursive function.

There's more on the issue here

Actually let me start again. gatsby-mdx-routes is a little plugin that creates routes and generates navigation labels from frontmatter and originally i thought the issue was related to how could routes be grouped into menu headings as per the work i've been doing on the docz site but after asking that question it was communicated that wasn't the issue.

While i waited for a response i cracked on with a little enhancement to the MdxRoutes component by creating a prop to allow re-ordering of navigation routes.

For instance if you had Home , About and Contact you'd probably want Home to be the first route returned but because i wasn't sorting the results they were just returned in alphabetical order.

I thought about having an ASC and DESC option but that doesn't really solve the problem so i decided upon the reference array option.

Suppose you had a graphQL response that looked a little bit like this 👇

graphQlData = ["About", "Contact", "Home"]

By providing a navigationOrder you can sort like this 👇

const navigationOrder = ["Home", "About", "Contact"]
graphQlData.sort(
(a, b) =>
navigationOrder.indexOf(a.navigationLabel) -
navigationOrder.indexOf(b.navigationLabel)
)

Unlike the default method of sorting instead of simply determining if a - b we can use the indexOf from the navigationOrder array which is provided via a prop.

Great i thought, that's that issue closed and released 0.0.5

But nope. I was notified they'd been a new comment on the issue and it was mentioned again that a new property in frontmatter was required to sort the navigation items... "WT Flip" i thought, i've just provided a solution for that.

A few comments later and we have now established that it's both a grouping and an ordering issue.

In the first instance grouping the menus should be managed by a recursive function and not via a property in frontmatter and then once they're grouped we can order them before returning.

This does mean however, i'm back in to recursive hell! This time i'm planning on using the slug to determine how many levels deep a menu should be grouped.

My initial thoughts are to take the slug. eg some-folder/some-sub-folder/some-file and split the string to create an array and then remove any empty space. I hope to use the array length as the condition to stop the recursive function by removing the slug segment on each loop before calling it again... we'll see how it goes!

Day 20

Jan 20 2020

Recursive functions research has continued today and although i've solved what i set out to do with the docz navigation i wanted to dig a little deeper.

The main reason is i feel the method(s) i've used to reduce the menu object feel a bit ECMAScript 5, even though they're not.

I'm even using let and if you follow along on Twitter there's a lot of conversations going on about let vs const etc, etc ... but i do feel some of the if statements i'm using, or rather the nested if statements i've used to manage what to do on each iteration of the recursive function feel a bit clunky.

There's some really powerful ECMAScript 6 array methods available and i don't feel i'm taking advantage of them and as a result my reduce function isn't that readable.

I became a little frustrated today so perhaps it's best if i move on to something else and let all this sink in and try to tackle the problem again at a later date.

Ironically i've since noticed a new issue has been raised on one of my other Gatsby plugins gatsby-mdx-routes which is actually intended to make file path and menu navigation easier. 🤦

I think this will be a job for tomorrow now but perhaps it'll be an opportunity to test drive my new found knowledge of recursion... which in itself is actually kinda recursive. 🤗

Day 19

Jan 19 2020

Made good progress today on the docz recursive submenu problem and have it pretty much sorted.

I'm now able to group menu items together by defining a submenu property in the frontmatter You can see it working in the Components menu with Twitter and Pinterest acting as submenus here

The code needs a bit of cleaning up and i'll document my approach and solution in a following blog post... i just gotta make sure i fully understand what i did first 🤔

If you're interested though i've pushed to master so you can see the amended Sidebar component, the new reduce method and the new SideNavGroup component... you gotta love Component Shadowing!!!

Day 18

Jan 18 2020

I did a bit of work this morning on recursive functions to make the navigation in docz work for me. Luckily since docz is also a Gatsby theme i'm able to tap in to component shadowing. I started by looking at gatsby-theme-docz/src/components/Sidebar and investigated the menu object.

This, as it stands doesn't have a way to group by submenu but the theme does allow you to add an additional fields to frontmatter.

This is quite key given i need a way to determine if a file is part of a menu as well as part of a submenu.

I've since added a sumbmenu property to the .mdx files that i will use to "group by" and have set to work on altering the menu object created by docz core and recursively looping over any object that contains a submenu.

Now i have an object that i can use to drive the UI.

I've also been working on another blog post explaining recursive functions and will continue to update it documenting the problem i'm facing and how i intend to solve the docz theme submenu problem.

Day 17

Jan 17 2020

This morning i was attempting to work on a recursive submenu solution for the navigation in the docz site used by gatsby-mdx-embed and as i worked through a solution i thought about how this might make a good blog post.

I then thought, if i start to write the post in this blog the next time i commit and publish that post will also get published.

This blog uses my theme gatsby-theme-gatstats which currently has no way to set a post as draft which would exclude it from being published.

I then worked on my theme and have included a new property in the frontmatter called status. If status is set to draft the post won't be displayed and none of the charts will attempt to reference it as a data source, thus not skewing your metrics 😎

That issue was raised on GitHub #26 and now felt like a good time to address it.

I've had another issue raised today too, this time with gatsby-remark-sticky-table A user wanted to put images in a table cell.

There's probably something funky going on with the way i'm parsing the node to the new markup so i suggested this solution and might investigate this another time.

Right... back to the recursive submenu problem!

Day 16

Jan 16 2020

This morning i was having a google around and out the corner of my eye i saw a Pinterest logo... ooh i thought, i wonder if Pinterest have embed-able widgets?

They do! so that was me for the next few hours!

gatsby-mdx-embed now has three new components for Pinterest.

The standard <Pin /> where you can embed an image from Pinterest, a <PinterestFollowButton /> and a <PinterestBoard /> with an optional prop so you can create a board from a user or a board from a board, if that makes sense.

The inject script works very similarly to Twitter, Instagram and Flickr but i did need to do a little digging into the window object to find the build() function. This needs to be called on route change so that any components on the page will execute and display as expected.

This evening i'll be looking at how to make a change to the docz theme so i can have nested menus. I have a feeling my old enemy array.reduce() may be required and it doesn't matter how many times i read or write an array.reduce() i always struggle!

Day 15

Jan 15 2020

I spent some of the morning updating prop names and continued to work on two new components, <TwitterTimeline /> and <TwitterList /> and i really like the Twitter method for handling embeds!

The method i've used to inject the Twitter embed script remains in tact and all the other Twitter embeds work without any additional injecting, which leaves me time to just develop the components and ponder about what to name the props.

At this point i was really regretting not implementing TypeScript 😞. I use TypeScript for my day job and in my bigger projects like gatsby-theme-gatstats and developing without it feels like being nude and leaving the house.

As development continued i'd been wondering if gatsby-mdx-embed was going to need TypeScript because PropTypes kinda has my back but i'm now feeling really un-easy with working towards a stable release without it so implementing it now is an absolute must.

This evening i've refactored everything and gatsby-mdx-embed is now TypeScript enabled 🎉🥳.

It feels like a massive relief to know that's sorted and it wasn't too much of pain to setup. docz did give me a few headaches with it not generating the prop table from the TypeScript interface... until i discovered that i needed to set typescript: true in the doczrc.js

With TypeScript now in place i'm more comfortable with continuing to develop components and perhaps 1.0.0 will happen sooner than expected.

Day 14

Jan 14 2020

Last night i started to implement Twitter buttons and hit a naming issue. I'd previously named the components after the provider they represent. In the case of a Tweet this is fine because a Tweet is a unique thing but, what do i do with a hashtag button?

Twitter isn't the only provider tha uses the hashtag paradigm and so i've had to start thinking about prefixing names to allow for this plugin to scale. Maybe at some point i'll be able to introduce an Instagram hashtag button. 🤷‍♂️

This led me on to the next problem. Props!

To give some context. I build commercial React Component Libraries for companies that make bazillions and these Component Libraries are typically used by lots of engineers on various projects so i'm familiar with the trouble with naming things.

I have learnt that keeping a consistent api for prop names is key.

For instance if you have a number of components that, let's say accept some kind of render prop for a heading, this prop across the entire library should always be called heading. It makes no sense if in a Card component you name it CardHeading and then in a Modal name it Header.

I was trying with gatsby-mdx-embed to keep a consistent id prop across all components but i've now hit a point where id just doesn't cut the mustard. 🌭

On some components like YouTube the id is the video id and that's how YouTube refer to it but, in a Tweet for instance i need the prop to be less ambiguous.

I had some interesting Tweets back and forth with @AskGatsbyJS and John Otander and the general consensus was in Open Source Libraries it pays to be clear and it doesn't matter that names or prop names are long. I think there's a post or Tweet out there by Dan Abramov about how the function names at Facebook are really long, but the upside is it's clear what they do.

I've tried to keep some consistency and the id paradigm is still in use but now it's more explicit youTubeId.

For components that require more than an id, Spotify and Gist for instance where the prop includes a word tracks or album AND an id i've gone with ...Link. I thought about using URL in the prop name but the prop doesn't contain http etc so it's not really a URL.

Interestingly though when i have username as a prop i don't feel i need to change this to, e.g twitterUsername, same thing with the hashtag prop. If you're using a component that has the provider in the name like <TwitterHashtagButton /> i hope it's clear that the hashtag prop refers to a Twitter hashtag... naming things is hard 😩

A note on sem-ver. Strictly speaking these are breaking changes but i feel i can justify not bumping the plugin to a major release version of 1.0.0 because in my mind when a library is only at 0.x.x to start with it's still a pre-release... even though i have already released it. 🤯

I'm not sure if this is a bad thing to do but i suspect i'm going to encounter a lot more of these kinds of naming issues before i'm happy to release a stable 1.0.0.

I have started a CHANGELOG which should help you fix any issues, and of course the docz will always reflect the actual state of the library.

I hope this change hasn't or won't cause anyone any serious headaches but if you are having problems feel free to Tweet me @PaulieScanlon

This morning and this evening will mostly be taken up by combing over the docs and i'll be thinking hard about sensible names for both components and props.

TTFN!

Day 13

Jan 13 2020

This morning i continued to work on the Wikipedia component and switched to using the wikipedia rest_v1 api

I had a little trouble with the response, i was parsing response.json() but i needed response.text()

This can now be injected into the srcDoc of an iframe which retains all the wikipedia styles but has created a new problem.

The iframe now needs some dimensions. By default i'm setting the width as 100% and i'm allowing for a height prop which means control of the height is handed over to whoever is using this component in their .mdx

I think this will be enough for now and should i get any issues on GitHub i'll deal with them when they arise.

oh, and here's a demo of the finished component.

Day 12

Jan 12 2020

Today i continued to work on the Wikipedia component and have a new method in place for querying the Wiki api. The new method uses the fetch api which has cleaned things up a lot and means there's less JavaScript being injected into the page but the thing that's stumped me now is that the response i'm getting using this approach no longer returns a stylesheet.

I can render the page data but the content picks up the styles from the docz site rather than the usual Times New Roman style from Wikipedia that we are familiar with.

There are alternative methods documented in the Wikipedia api for fetching the css but i'm having trouble getting both the stylesheet and the data in the same response. I'll just have to keep digging!

The other issue i encountered was that the api response returns All links as relative. For instance for my test page i'm querying "The_Jimi_Hendrix_Experience" and the href's that are returned look like this

wiki/The_Jimi_Hendrix_Experience

when in fact they need to be prefixed with https://en.wikipedia.org/

https://en.wikipedia.org/wiki/The_Jimi_Hendrix_Experience

using a regex pattern i'm replacing everything that has wiki in the href with the url.

I've never really understood regex but i did spend some time reading, watching and learning about the bits i needed.

Here's the final regex pattern /<a href="\/w/g which when used in the response looks like this

text["*"].replace(
/<a href="\/w/g,
'<a target="_blank" href="//en.wikipedia.org/w'
)

I added the target="_blank" as it feels like a better option for users, perhaps i'll turn this into a prop but it works like a charm so i'm happy to move forward.

Day 11

Jan 11 2020

It's Saturday and i didn't have a lot of time today. I did continue working on the Dropbox Chooser component but i think i need to shelve development on this for the time being.

After making good progress i noticed that in order to get it hooked up i'd need to inject the script for each and every Chooser button.

The repercussions are that this could really affect page load speed and that really goes against what i'm trying to achieve with this plugin

I've pushed a branch so i can keep my work but for now i'm going to move on to something else.

I've since gone back to my list of oEmbed providers and have decided to focus on a Wikipedia component. It feels like it could be useful and the api looks to be well documented.

Upon initial inspection i think the best course of action is to fetch the "page" from the Wiki api, then render the response using dangerouslySetInnerHTML. I'll see how it goes and no doubt report back tomorrow.

Day 10

Jan 10 2020

Last night i decided to design a logo for gatsby-mdx-embed i was hoping it would be like the Fight Club logo in a bar of soap but it didn't quite work out that way... i was a designer a long time ago but i think i've now just run out of talent. 🤷‍♂️

Another early start again this morning and i started to think about how users might use this plugin and it's not always clear what i'm referring to as an id in the props. As of this morning i've created a Help page which documents how to extract the id the component needs from the providers embed code or URL.

This evening i'm planning on adding Dropbox chooser to the list of components. I don't even use Dropbox but it has an embed-able script tag so it belongs in gatsby-mdx-embed

Day 9

Jan 9 2020

I had a productive morning this morning and have added Twitch to the list of components gatsby-mdx-embed supports.

While i was digging around the Twitch embed code i noticed the skip to option which allows you to embed a video and start it a certain point. This seems like a pretty useful thing to include so i added it as an optional prop along with auto play.

The way Twitch handles the time code is by having the following parameters as part of the URL.

&t=0h21m14s

t is the time parameter which accepts a numerical value followed by the time digit h for hours, m for minutes and s for seconds. I've exposed a skipTo prop on the Twitch component so you can pass through a time-code.

skipTo={{ h: 0, m: 21, s: 14 }}

I then thought i'd add this to the YouTube component, but YouTube do the time-code a different way.

The URL parameter looks like this

&start=1274

After doing a bit of maths i realized the time-code is the total minutes from the start of the video. I wanted to keep the props the same as i've done with Twitch so i needed to calculate the total time before i pass it on to the URL.

const { h, m, s } = skipTo
const tH = h * 60
const tM = m * 60
const startTime = tH + tM + s
// startTime = 1274

First i de-structure the h, m and s from the skipTo object then multiply h by 60 and also m by 60, you don't need to do it for seconds as the start time is in minutes.

Then the last step is to add these all together to create something the YouTube URL understands.

I've also added the same prop to Vimeo, and luckily it handles the time-code in a very similar way to Twitch so not much work needed to be done on that.

This is now available in v0.0.6 of gatsby-mdx-embed

Day 8

Jan 8 2020

Last night i carried on working on gatsby-mdx-embed, made some tweaks to the docz theme and found a list of "providers" that are supported by oEmbed.

There where two that caught my eye, SoundCloud and Gist. SoundCloud was pretty straight forward as it's a very similar method to how YouTube and Vimeo so that was no problem.

This morning i moved on to Gists.

I Googled around to see if there were any existing React repos and found these two... so thanks Christian Korndörfer and Miroslav Saračević

The main bit that i didn't initially understand was how to handle the JSON callback.

If we start with a typical Gist URL and run it, you'll hit the https://gist.github.com/

https://gist.github.com/PaulieScanlon/ca0cc9239176066492cb2aba435edbf7

To provide a callback we can add on gist_callback i Googled around for how to add the callback for ages and found no official docs, just examples of how others have done this.

?gist_callback_ca0cc9239176066492cb2aba435edbf7

This is now the complete URL.

https://gist.github.com/PaulieScanlon/ca0cc9239176066492cb2aba435edbf7?callback=gist_callback_ca0cc9239176066492cb2aba435edbf7

The last step was to inject a <script> tag with the URL in a useEffect life-cycle method, create a function on the window object called gist_callback_ca0cc9239176066492cb2aba435edbf7 then investigate the response.

The response comes back with a div object which contains all the HTML for the Gist which can be handled by dangerouslySetInnerHTML

<div dangerouslySetInnerHTML={{ __html: response.div }} />

...and a stylesheet object which in turn needs to be injected into the page in a <link> tag.

With both of those things done Gists are now embed-able!

I need to do a bit more work on handling errors but i've bundled it up and Gists are now part of v0.0.4

Happy Embedding! 🧼

Day 7

Jan 7 2020

Yesterday was a pretty good day, i was relieved to finally get docz setup the way i wanted. I also launched a very early version of gatsby-mdx-embed. A fellow Gatsby enthusiast who i met at Gatsby Days London Scott Spence was keen to try it out... so, here ya go Scott!

This evening i'll mostly be focussing on documenting and testing the props for each component and perhaps if there's time i'll investigate what other providers i can include. dev.to would be sweet but i had a quick google and there's an open issue on GitHub regarding this so i don't know if it's possible yet... stay tuned 📺

Day 6

Jan 6 2020

Back to my day job today so i got up early and cracked on with the docz.site... and pleased to report i got the <Props> component working.

I was on the right track with what i thought the problem was and docz can be configured to source files from outside the root directory but this hasn't been documented anywhere.

The problem was twofold.

  1. What did node think the root was and what is the correct path to pass to docz
  2. How the WT Flip do you pass a path to docz

The way to do point 2 is to add docgenConfig.searchPath to doczrc.js which tells docz where to look for component props. You won't find this in their docs but i did find it amongst the examples

// doczrc.js
export default {
docgenConfig: {
searchPath: directoryPath,
},
}

and directoryPath is as follows;

const directoryPath = path.join(
process.cwd(),
"../@pauliescanlon/gatsby-mdx-embed/src/components"
)

First i'm using path.join to make sure i don't end up with un-wanted /'s, then i'm using process.cwd which is the node.js method for working out the Current Working Directory then finally i go up a level "../" and into the yarn workspace where i'm writing my MdxComponents

This now means from the .mdx file where i'm writing the documentation about the component i can also have a nicely formatted prop table which are the real props defined by propTypes in the component file.

You can see the example for the CodePen component here

Later tonight or early tomorrow i'd like to tweak the docz theme styles a bit then finally i can crack on with developing the MdxComponents

Oh and dark mode now works! 🎉

Day 5

Jan 5 2020

Today i decided to focus on the documentation site as i need a playground setup so i can test props for each of the MdxEmbed components.

Usually in my professional life i'd use Storybook but since part of #100DaysOfGatsby is to learn new things i've gone for using docz.site

It was a bit tricky to setup as i wanted to use gatsby-theme-docz and i found the documentation regarding setup a bit confusing.

None the less it's all looking pretty good now. I might have found a bug with how the plugin options are passed or perhaps in some cases they have to be set in the doczrc.js file... who knows, maybe i'll have to live without dark mode on ths one!

The problem i'm currently experiencing is with the <Props> component which is one of the built-in-components which can create prop tables for my components. What's not initially made clear is that it'll only work if the component in question is local to the .mdx. For example docz will generate a prop table for <MyComponent> it it's in the same things folder as MyMdx.mdx

- things
MyComponent.js
MyMdx.mdx

... But it wont work if i move <MyComponent> to somewhere else, for example...

- components
MyComponent.js
- pages
MyMdx.mdx

If you want to be able to source files from somewhere else you have to set the src value in doczrc.js

export default {
...
src: './components',
}

But my docs site and my MdxEmbed project are two different repos linked together by yarn workspaces so i think i need to tell docz to jump up a level to find my components.

export default {
...
src: '../@pauliescanlon/gatsby-mdx-embed/src/components',
}

Which causes GraphQL to error, presumably because it can't find what it needs?

I'm currently trying to work out where node thinks the root is and from there i need to refresh my memory about path.resolve and process.cwd but that sounds like a job for tomorrow!

Day 4

Jan 4 2020

Yesterday i spent the morning getting lost in a docs rabbit hole. I tried numerous documentation themes but all were tripping me up one way or another so i decided to shelve the docs part of gatsby-mdx-embed and just get something looking half decent... which led me down another rabbit hole. I had real trouble getting theme-ui and typography treatments to works. I also discovered that behind theme-ui typography is Kyle Mathews who has been creating a ton of them. I kept having the same issue though and that was the body font wasn't being set so i resorted to using emotion core global and css to just set it... again i'll come back to this.

What i was able to do on gatsby-mdx-embed though was to understand how to create a method for the provider so that once the plugin is installed that's all a user would have to do. It's similar to how gatsby-plugin-theme-ui works by using gatsby-browser and gatsby-ssr and using the wrapRootElement method to inject the MdxProvider.

This i discovered needs to be done in both files and in different ways. in gatsby-browser es6 imports work in gatsby-ssr you have to use require and node modules exports.

..both are required so that in dev and prod the MdxEmbedProvider wraps the root element. With this now working i'm almost ready for an early release.

...

Day 3

Jan 3 2020

This post is starting to feel like an agile standup so perhaps i'll treat it like one.

Yesterday

After writing yesterdays blog post i had a think about how i was gonna handle the headings with nested <a> styling in gatsby-theme-gatstats which was actually pretty easy. I'm using theme-ui for everything so a little update to my headings object to style the child <a> was all that was needed.

const headings = {
...
a: {
fontSize: 'inherit',
fontWeight: 'inherit',
lineHeight: 'inherit',
color: 'inherit'
}
}

Next i looked at how these # anchors should work. Typically in a site the browser jumps to where the # starts when clicked and if a link is shared with a # as part of the url when the page loads it'll move the page so the # link is at the top.

For this to work in my theme i needed to look at the gatsby-browser api. There's two methods that were required to make this to work.

  • onRouteUpdate which is called when a user changes routes, and also called when an <a> is clicked (if it has a #)
  • shouldUpdateScroll which allows us to influence the scroll position of the browser on load and also it would seem between route changes.

The main guts of this functionality is wrapped up in a little function i created in gatsby-browser which is called by both of the above methods.

const anchorScroll = location => {
if (location && location.hash) {
const item = document.querySelectorAll(`a[href^="${location.hash}"]`)[0]
.offsetTop
const mainNavHeight = document.querySelector(`header`).offsetHeight
setTimeout(() => {
window.scrollTo({
top: item - mainNavHeight,
behavior: "smooth",
})
}, 50)
}
}

In short all this is doing is finding the <a> element that contains the # which is found from the url / location.hash then scrolls to it. There's an offset in there because gatsby-theme-gatstats has a position fixed header so i needed to calculate the top position minus the height of the header so the selected # isn't under the header when the browser scrolls to it.

This all works well but i'm a little worried about my choice to use the native window.scrollTo method with behavior: "smooth" as some older browsers don't support this so if you're using IE 11 (🤢) can you let me know if it still works as intended?

I also had a little bit of twitter activity yesterday from a new user of gatsby-theme-gatstats who tweeted to ask me how to do something. He said he didn't want to raise as issue as he thought it was more him not knowing how to do it rather than it being a bug. My reply "was go ahead, raise an issue" Reason being is that if he's had problems with this particular "thing" then perhaps i should explain it better in the README so others don't have the same question.

I'm pretty new to open source and gatsby-theme-gatstats is the first real project i've had where users are getting in touch and / or rasing issues on GitHub. I think it's fantastic to be honest as it's quite difficult to know how your project will be used and whilst i tried to think of everything i know i've missed things so having other users point this out and let me know means i get to change and improve the project ... it's a win, win!

Today

Today i really want to focus on gatsby-mdx-embed and get this converted to TypeScript and perhaps get Storybook setup.. but i do like the idea of using a Gatsby project to use as a documentation site so i'll probably have google around and see what's out there.

I'm also thinking in the background about the subjects i'm covering on this "standup" style post and which ones should be promoted to their own blog posts. The <a> # thing i did yesterday could be a good one to write up but i'm not sure i'll have time. For now at least my main focus is on getting gatsby-mdx-embed stable and released.

Day 2

Jan 2 2020

Started this morning by fixing a bug with gatsby-theme-gatstats. Part of the dashboard has a Posts chart displaying information gathered from the previous year and current years posts. I wasn't correctly checking that the chart would render correctly if there were no posts for the current year.

I've also noticed another bug which is the chart max range needs to be calculated from grabbing the highest count value from both of the year data arrays. I was previously only checking the current year data and creating the range from the hightest count value in that year but it's quite possible that the previous year will have a higher count meaning the line chart will get cut off.

I also need to investigate anchor tags in the theme so that they don't always take on the styling for <a> if nested within an <h1> This will come in handy should i want to add anchor tags to each heading from this 100DaysOfGatsby post.

Day 1

Jan 1 2020

Today is the first day of #100DaysOfGatsby and since i already have a blog in place i think i'm gonna just continue working on my various Gatsby projects and try to write a bit each day and then see where i'm at in 100 days.

I currently have a number of Gatsby plugin projects all on npm but all in various states of completeness, these are:

Today i've pushed a fairly stable commit to gatsby-mdx-embed which i think pretty much solves the twitter, instagram and flickr embed problem. I'm not gonna release this to npm just yet as i've done with previous plugins because i'd like to get this properly tested and converted to TypeScript first.

gatsby-mdx-embed is first and foremost an MdxProvider and when used in a Gatsby project along side .mdx it'll allow for media embed codes to be used without import by using the MdxProvider and it's component prop.

So far so good and i have the first 8 components in and working, although the instagram one seems a little flakey on iOS.

Lessons learned today are similar to issues i've experienced before regarding gatsby-ssr and gatsby-browser. Or more specifically the problems when attempting to use both together to accomplish similar things.

ie. if gatsby-browser relies on something that gatsby-ssr is gonna do which might not run synchronously. I made a change and it was worth the effort now gatsby-browser does all the heavy lifting things are working much better.

In the case of gatsby-mdx-embed it was because i was using gatsby-ssr to inject the relevant provider scripts into the <head> and then using gatsby-browser to invoke them. This wasn't really working so making the <script> tags and appending them to <head> AND then invoking them from gatsby-browser proved more solid.

I'd really like to solve the instagram problem before moving on much further but getting the project converted to Typescript and then installing Storybook sounds like it's gonna be way more fun.

I plan to open up and document a load of props to make each component more useful, adding widths to videos and or aspect ratios etc would be really cool. I haven't set up a TypeScript / Storybook repo for a while so this should be fun!

Once i'm happy gatsby-mdx-embed is pretty solid i'm gonna switch out the temporary Tweet and YouTube components i hacked together in my theme gatsby-theme-gatstats

I'm gonna use this post as a kind of journal and update each day with things i'm working on of things i'm thinking about and would like to create more in depth posts for topics that warrant further explanation.