By Paul Scanlon

100DaysOfGatsby

  • Gatsby

Day 100

Apr 9 2020

Stick a fork in me, i’m done! ✅

I can’t quite believe it but for 100 days i’ve written code and updated this blog post with what i’ve been doing as part of the #100DaysOfGatsby challenge.

It’s been a great experience and i’ve learned so much but to save you some time i’ve summarized all the best bits in a separate post: 100DaysOfGatsby - TheRoundup

Ta ta for now!

Paul 👊

Day 99

Apr 8 2020

Still taking it easy.

This morning i only did a very small amount of work on my commercial portfolio www.pauliescanlon.io and added some extra dates to the cards on the home page. Under the hood i’ve used the dataModified field from frontmatter and am combining it with the date field which allows me to show when i started and ended each contract.

I’m not sure how closely employers look at these details but it does at least demonstrate how flexible gatsby-theme-terminal is. Those fields technically relate to blog posts but since they are exposed by a data component i can render whatever i want in the UI… super cool! 😎

I’ve also been planning what life might look like after this challenge and stumbled upon this tweet from Fauna

Maybe Write With Fauna will be my new jam and i’ve submitted a proposal for a Full Stack Gatsby App

I think it’ll mainly focus on creating commenting functionality since this was one of the #100DaysOfGatsby challenges but none of the suggested options really worked for me, and with the work i’ve done on skin-ui.com i have all the code examples needed to document how to make a Gatsby App with the following

  • Gatsby App / With Theme UI (of course)
  • Client only routes (Admin Page)
  • Netlify identity
  • Apollo/GraphQL api
  • Fauna Database

It does sound like it’ll be quite a lot of work and i’ve never attempted to write anything like this before but i’ve rather enjoyed blogging EVERY DAY so maybe i’ll be able to handle it.

Other life work is beginning to resume to and i’ve made a list of jobs that i’d like to apply for, they are all top tier tech firms so i’m expecting many rejections but if i fire off enough applications hopefully one of them will come to fruition.

Naturally Gatsby is on this list but sadly they don’t have any open positions that’s i’m suitable for but i think i will submit a “Dream Job” application anyway. Fingers crossed ay 🤞

Tomorrow is the final day and i’m all but out of things to write about so i think tomorrow will be a rundown of everything i’ve done over the past 100 days… i know already it’s a lot but i’ve enjoyed every minute of it and if you’ve been reading along i hope you have too!

Day 98

Apr 7 2020

This morning i was doing a bit of house keeping on this blog.

Previously i’d been dumping all manner of @theme-ui/components in my .mdx so i could give the data components a test drive with some of my real data but unfortunately this led to a lot of duplication.

I’ve now abstracted some of the charts and the card component from raw @theme-ui/components in .mdx to composed React components in .js

It makes it much easier to see what’s going on in the .mdx files and means i can re-use those components in any pages, or posts since everything within them is now encapsulated.

The home page of this blog is a bit gross so i might create a separate dashboard or statistics page to showcase all the data related stuff and leave the home page to just display some intro text and the latest blog posts.

I noticed this tweet today from @AskGatsbyJS

…and whilst Component Shadowing is an important concept with Gatsby themes i feel my theme gatsby-theme-terminal side steps the whole requirement to shadow components because there are no components to shadow.

Everything you see in gatsby-theme-terminal is something from @theme-ui/components and since the only “components” that exist in the theme are data components you can render your UI in any way or style you like… maybe i should write a blog post about what i’m calling Zero Component Themes

Day 97

Apr 6 2020

Another day of data!

This morning i had another crack at the <SourceWords /> component in gatsby-theme-terminal and have exposed a new array of data, it’s called wordCountByMonth and yeap it does what it says on the tin.

It’s very similar to sourceMonths and provides a nice way to visualize how many words have been written in any given month.

Here’s another lame demo.

<SourceWords>
  {(sourceWords) => {
    const currentYear = sourceWords.wordCountByMonth[sourceWords.wordCountByMonth.length - 1];
    return (
      <Box>
        {currentYear.map((month, index) => {
          const { name, words } = month;
          return (
            <Box key={index}>
              <Text>{`${name} | ${words}`}</Text>
            </Box>
          );
        })}
      </Box>
    );
  }}
</SourceWords>

There’s a better looking bar chart version of this on the demo site if you’re interested.

Day job wise i’ve been really getting stuck in to Testing Library.

Now that i’m over the whole needing to add a data-testid to dom elements it is pretty cool to work with, i expect i’ll have a few more things to learn before i really suss it out and i haven’t written any tests that require mocked api responses so that’ll be fun when i get to it!

Day 96

Apr 5 2020

Keep it simple stupid.

That’s how i’m planning on winding up this challenge, there’s no point in starting anything new if i’m not going to be able to finish it off and so close to Day 100 i’m just combing over the work i’ve done over the last 3 months and tweaking where needed.

Today i’ve released a new patch for gatsby-theme-terminal which now includes a <SourceWords /> component.

You can see a demo of it here.

It works in much the same way as the other data components by only being responsible for returning data, it’s up to you the theme user to determine what UI element you’d like to render.

And for my next trick… because this blog is built on gatsby-theme-terminal i can use the <SourceWords /> component right here in the .mdx

<SourceWords>
  {(source) => {
    const { wordCountTotal, wordCountAverage, wordCountHighest, wordCountLowest, timeToReadTotal, timeToReadAverage } =
      source;
    return (
      <ul>
        <li>{`wordCountTotal: ${wordCountTotal}`}</li>
        <li>{`wordCountAverage: ${wordCountAverage}`}</li>
        <li>{`wordCountHighest: ${wordCountHighest}`}</li>
        <li>{`wordCountLowest: ${wordCountLowest}`}</li>
        <li>{`timeToReadTotal: ${timeToReadTotal}`}</li>
        <li>{`timeToReadAverage: ${timeToReadAverage}`}</li>
      </ul>
    );
  }}
</SourceWords>

Pretty lame list right, but if you like donut charts checkout the demo

Day 95

Apr 4 2020

I spent the morning investigating why gatsby-source-contentful was throwing errors with my blog but after a few hours i took a step back and thought about if i really need a CMS in my blog.

My motivation for looking into gatsby-source-contentful was because it’s one of the challenges and i suppose i do have a requirement for both my blog and my site to share some of the same content, but since this is a source plugin i’d still need to build and deploy both in order to keep them in sync… and if i need to do that it’s probably the same amount of effort involved in just copy and pasting the content they share.

I did then look in to perhaps making a REST-ful request to contentful which would remove the need to re-build and deploy but it would also remove the static data which would probably have a negative effect on SEO but i was curious…

I got all the way through the docs, set up a nice component that will make a request with the correct space id and bearer token and then moved on to work out what the GraphQL query would be… i then discovered that on the free plan you can’t make GraphQL queries so that was the morning pretty much wasted 😂

So, instead of messing around with things i don’t really need i’ve messed around with some things i do.

There were a few issues with my theme gatsby-theme-terminal which i wanted to look at.

The first relates to the prev and next links that were at the bottom of each “source” page but…

gatsby-theme-terminal has the ability to query from any local data source and although in “your site” you can filter and sort however you want the GraphQL query that’s inside the theme is still in charge of the source nodes and is what’s deciding what in fact is prev or next.

For example if you have two sources and filter out one in your MDX the underlying nodes won’t know about the filter and might try to link to a prev or next “source” that isn’t relevant … so i’ve removed this functionality … sorry about that.

There was also an issue with the <SourceDays /> component where i’m performing some calculations based on what date is found in the frontmatter eg.

new Date(item.node.frontmatter.date).getDay();

Unfortunately i’d forgotten that arrays start at 0 so all days where shifted forward by one! changing the above line to the below fixes that problem.

new Date(item.node.frontmatter.date).getDay() - 1;

I also added a word count, time to read and author to the post layout template. These fields were already there in the frontmatter i just forget to add them to the UI.

I’ve had another scan over the challenges and there’s not really anything that i haven’t covered in one form or another so i’m hoping i’m still on track. I appreciate these are just pointers to help you get started with Gatsby but based on the work i’ve done with my themes, plugins and more recently with skin-ui.com i feel i’ve got a solid understanding on what you can achieve with Gatsby.

It’s not long until the end now and i gotta be honest i’m feeling a little burned out. I don’t regret committing to writing a post every day, it’s kept me motivated but it has been a challenge. Every day i have to think about something to do so that i have a reason to update this post which means i’ve actually got to do at least one thing every day.

I’m quite looking forward to a day off!

Day 94

Apr 3 2020

Challenge accepted… challenge failed 😔

Today was a good opportunity to catch up on the actual #100DaysOfGatsby challenges and the headless CMS one seemed quite pertinent given my recent shift over to one theme two sites. Both my commercial portfolio and blog have the same intro header, and it would be nice if they both pulled that content from a CMS so as and when i update it i only have to do it the once.

The recent challenge to use gatsby-source-contentful fits my needs so this morning i set about adding the source plugin to this blog… but sadly ran in to issues immediately. There seems to be some kind of clash going on with my use of onCreateNode in the theme. I got as far as console logging out a few values to see if i could work out what’s going on but i feel like it’s a job for the weekend now.

The day job was pretty intense today. I’ve recently completed quite a large feature which involves a number of form elements and some odd / complicated interactivity that results in conditional rendering.

I did think during development that it would be hard to test.. and i was right.

For example, in one part of the feature there’s a form that you can’t submit until all five text inputs have a value, but the last three inputs are only revealed if one of the first two has been touched and has an input value.

The test for this is mad… i’ve had to use async and await to first fireEvent from one of the first two inputs and only then can i assert if the remaining three are visible.

I’m still not quite there with the test as i then need to assert that the button is disabled until the last three and the first one that wasn’t originally touched also have input values.

Just writing this out is complicated, imagine how odd this form will be to use, those poor users!

Anyway i’ve learned a lot about React Testing Library today and am quite liking working with it. I’m still not quite ready to ditch the Enzyme love but maybe i can just like both equally and leave it at that.

Day 93

Apr 2 2020

Never deploy in a hurry!

That’s the main take away for today. I was working on two new features for skin-ui.com these were:

  • Allow the admin user write access to all themes
  • Add a save icon button to the editor toolbar

Admin user access was a carry over from yesterday and i still can’t really work out why my environment variables in Netlify are undefined when i deploy but in any case if i run locally and log in as admin i can perform admin operations, one being write access to other users themes. This functionality is possible because i conditionally render the settings icon button if the “logged in” user id matches the user id from the theme saved in the database OR if it matches the user id of my admin login.

state.isUserOwner || (state.user.id === process.env.SKIN_UI_USER_ID && ( // render UI)

Once this was working i set about adding a save icon button to the editor toolbar, this is to improve the UX. Before this you had to open the settings panel to get at the save button which i thought was a bit shitty.

but…

in my haste to add the save icon button i forgot to add the condition, and deployed. It wasn’t until a bit later when i noticed the default theme had changed… i thought ah! i’ve been hacked!

but nope, i logged in with my regular user details and viewed the default theme and sure enough the save icon button was there meaning anyone could just save over the top of the default theme!

I was in such a hurry to deploy this new feature this morning before i started work that i hadn’t fully tested the functionality… a mistake i won’t make again!

Also… if i’d actually had unit tests this would have probably been caught before i even committed the changes.

A lesson learned.

On to the day job.

Nothing really new to report, just carrying on with a customer review feature, got all the main UI parts built and am now moving on to improving my tests.

Day 92

Apr 1 2020

Notice anything different?

If you’re one of the 3 people (including my mum) who have actually been reading this you might notice the site has completely changed. Yup! www://paulie.dev now looks very similar to www.pauliescanlon.io

… and that’s because finally after almost a year i’ve set out what i wanted to achieve and the reason i got started with Gatsby in the first place… Themes

For a long time i’ve wanted two sites, one for my commercial portfolio and one for my blog, but i didn’t want to build and maintain two separate entities.

With Gatsby Themes this is no longer an issue!

I’ve built two themes over the past year but gatsby-theme-terminal is the one i’ve put more of my learnings in to and because it’s really flexible it’s easy to create different layouts and query different parts of the file system. More on that here

So there you have it, if you have a requirement like i did, Themes is the way to go.

Today i’ve also managed to squeeze in some Skin UI work and am now handling syntax and theme object errors more gracefully. I do have some problems with creating an admin user as Netlify seems to be ignoring my .env variables… this one requires more investigation.

The day job… a pretty good day today mainly chore focussed as i was asked to convert the code base over to TypeScript 😊

Storybook was the killer here, Storybook 5 is brills but it still took a little while to configure the webpack config to get the prop tables to populate using react-docgen.

After that was done i was back on to Formik forms and wrestled with Radio buttons but got there in the end.

That’s me for today, cheerio!

Day 91

Mar 31 2020

I’ve become a night owl! 🦉

After i posted yesterday, and i don’t know why but i decided to switch this blog over to using my other theme gatsby-theme-terminal, it was a pretty easy switch but i wanna make a couple more changes before i deploy so we’re stuck with gatsby-theme-gatstats for the time being.

Then i went to bed and couldn’t sleep because i kept thinking about an enhancement i wanted to make to skin-ui.com

There’s a showcase section and it wasn’t really showcasing the themes because i wasn’t able to pull the theme_object down from Fauna using an indexes lookup.

I did some investigation and theme_object was returning null which i found very odd because if you’re on the Editor page it pulls the theme_object down ok.

I’m not sure if i’m doing something wrong with the query but if i query all themes using an indexes lookup rather than by a specific id i get null

I found that if i save the data as a string rather than an object in both queries theme_object comes back ok… so that’s what i’ve done.

No there’s some pretty sweet looking Empty States when you visit the showcase section and they represent the colours used in each of the themes that users have saved.

On to the day job.

Today i’ve been building out a customers reviews section, nothing new here, just more Formik and using Theme UI to style stuff.

Tomorrow i’ve gone a bit more to do but so far so good. Once the UI part is done i hope to be investigating a source plugin which will be great as it’s not something i’ve done with Gatsby plugins yet so i’m excited about that.

Day 90

Mar 30 2020

Back to work!

Early start this morning and i made a few changes to skin-ui.com and exposed a little more theme information on the your themes section. I exposed the user.id and the theme.id. Not huge changes but if i need to manually delete something from the database if a user emails me i’ll be able to find the entry more easily if they provide one or the other id.

Next up, the day job. Todays task mainly centered around how to build a UI with Theme UI and the code base i’m working on has the maddest looking theme object i’ve ever seen. It looks like all the styles from Tailwind but in a Theme UI shape.

This is not to say Tailwind isn’t hugely powerful but Tailwind and Theme UI are two very different beasts.

I’ll try and explain, first with one example key from the Theme UI spec.

export default {
...
  space: [4, 8, 16, 24, 32, 48],
}

You can see from the space key that there are only six different sizes, this is so when developing a UI if you need to add a margin or padding to an element you can use one of these options. Most likely in a good design system it’ll be space[2] or space[3] which gives you a nice amount of space of 16px or 24px depending on which one you choose.

If you have a theme that has something like this;

export default {
...
  space: {
    px: "1px",
    "0": "0",
    "1": "0.25rem",
    "2": "0.5rem",
    "3": "0.75rem",
    "4": "1rem",
    "5": "1.25rem",
    "6": "1.5rem",
    "8": "2rem",
    "10": "2.5rem",
    "12": "3rem",
    "16": "4rem",
    "20": "5rem",
    "24": "6rem",
    "32": "8rem",
    "40": "10rem",
    "48": "12rem",
    "56": "14rem",
    "64": "16rem",
  },
}

What you’ve done is ignore any kind of design system and are saying “use any padding or spacing you like because there’s loads to choose from”, which completely defeats the point of a theme.

If you’re going to take this approach you might as well not have any options in the theme and allow anyone developing the UI to just hard code px or rem values wherever they like.

The point, in my opinion of a theme is to restrict css properties to only a few options. The less time you spend thinking about how much padding or margin you need the more time you get actually developing features.

Also, think about how much time you’ll spend on PR’s, how on earth are you going to know what all those values are and how will you know from looking at the code if something has the correct amount of padding or margin.

To note, this is one of the smaller keys. The sizes key has 58 possible options and colors has 93!

What could you possibly need 93 colors for?!?!?

My main point being, if you’re exposing that many options in a theme which is supposed to reduce the css complexity you might as well ditch Theme UI altogether

Madness i tell thee, absolute madness!

Next up was forms i used to hate forms in React… but then Formik came along and boom! everything changed. Combine this with Yup and you’ve rock solid forms which manage their own state and really powerful validation without having to really think about anything.

I believe that like Theme UI, Formik’s approach is to remove those lower level problems so that you can start exploring higher level abstractions, and in both cases if you use the technologies for the purpose they’re were intended you can dramatically speed up UI development. Sadly i’ve seen this misunderstanding all to often and it always ends badly.

Day 89

Mar 29 2020

Today i feel good!

Another early start this morning and i was determined to solve this UX Navigation problem… to be honest i’m not 100% happy with the solution but you can now navigate around skin-ui.com with a reasonable amount of ease. The experience is a little better if you’re logged in but maybe that’s ok. If you’re just an idle browser then its probably forgivable that you have to work a bit harder to navigate.

Aside from that i’ve also tackled a few bugs and put the newly deployed features out to be beta tested by trused Gatsby dev chums Scott Spend, Richard Haines and Eric Howey who to note, i’ve all met through Twitter and because we all love Gatsby.

With the new release deployed skin-ui.com is now pretty much a fully functional application.

There are a few issues and enhancements i need to make but i’m happy for it to be out there. That said i now have THE FEAR.

Users can now sign up and save their themes which means i now have data… what do i do with data, what do i do if there’s a security issue and what happens if i need to delete data or change data that’s already been stored in Fauna?

If you’re reading this and have any advice please do get in touch. @pauliescanlon

Day 88

Mar 28 2020

Not the most productive day… but

I’ve now completed the Gallery / Showcase section on skin-ui.com. I can now pull down all saved themes from Fauna.

The response is paginated but i think i need to investigate how that works at some point, but since i’m not expecting a Facebook situation when i release this pulling all themes down at once (all 5 of them) probably won’t cause anyone any issues.

My biggest issue now though is the navigation. Once you’re in the Editor view there’s no real room for a top nav or a side nav so i think i’ll have to go back to the UX drawing board and see if i can figure out a way to maybe keep the top nav so you can navigate between the Gallery / Showcase and the Editor and if you’re logged in Your Themes and keep the Theme title and Theme description at the top of the screen… should be fun!

Day 87

Mar 27 2020

My morning started well, i got up early to look at my UX / Dropdown issue with www.skin-ui.com and i tried the reach/menu-button again and got the same “Cannot read property ‘ownerDocument’ of null” error so i gave up and wrote my own Dropdown component. It was quite an interesting process as i discovered something new about useEffect, maybe i’ll write that up at some point.

Now with this UX / navigation issue ironed out i can navigate around the app and login / out easily.

I’m gonna spend the weekend working on the gallery pages which gets me very close to the finish line.

The working day wasn’t entirely Gatsby based today but i did run in to a small problem with Jest, React Testing Library and the Theme UI provider… oh and Storybook was giving me a lot of problems with Gatsby links and GraphQL queries… here’s some comments on an open PR Docs/visual testing with storybook updates

But today’s main battle has been with massive api responses.

Imagine this scenario: You hit an api end point and it returns an absolute ton of data, probably 2% of it useful to drive the UI.

Do you…

  • A. Reduce it / format it once the response comes back, and only then pass it on to your UI / Context.
  • B. Just pass the entire object on to your UI.

If A, do you find it speeds up development as data is clean and easier to type with fewer obscure areas that require conversations.

If B, do you find that a number of smaller components need to run their own operations to wrangle the data in to a format that is helpful, do you find theres a performance impact when doing this?

My preference is A, i think it’s more prudent to think ahead rather than re-factor after.

Have your say… tweet me @pauliescanlon

Day 86

Mar 26 2020

It’s been a day of many halves!

I got up early and tried to implement a user dropdown kind of menu thing on skin-ui.com using @reach/menu-button which kinda worked but i did get some weird “Cannot read property ‘ownerDocument’ of null” error so i gave up and decided to plan my work today.

My main tasks on the new job are to refactor the UI and make a few decisions regarding the following.

  • What to name things
  • Where to save things
  • How to export things / named or default
  • How to create stories for things
  • How to test things
  • How to work round the Gatsby ‘pages’ issue - more on this later

I’ll start with how to name things. This is my preferred approach.

directory: components/SomeComponent

// components/SomeComponent/SomeComponent.js
import { React } from 'react';

export const SomeComponent = () => <div>SomeComponent</div>;

A few notes on the above; The component is a named export, it’s named the same as the directory it’s within and wherever possible it uses an implicit return.

// components/SomeComponent/index.js
export { SomeComponent } form './SomeComponent'

This is a named export of a named export but from an index.js in the same directory.

The usage then becomes;

// some other file
import { SomeComponent } from '../components/SomeComponent';

Then at some point you might have Storybook so you’ll probably want SomeComponent.stories.js and really there should be tests, SomeComponent.test.js and maybe even _snapshots_

All of that together might look something like this:

|-- src
    |-- components
        |-- SomeComponent
            _snapshots_
            SomeComponent.js
            SomeComponent.stories.js
            SomeComponent.test.js
            index.js

In my opinion it’s kind of crucial to get this locked down early on in a project.

I’m not sure why i care so much about these small details. I think it might be because when i first started doing this, Agile didn’t exist and yet we still got shit done… weird

I think it might also come from my family of tradesman where they will strictly employ a

Measure twice, cut once

approach to work. And just because on computers you and edit undo doesn’t mean you should.

I’ve re-imagined this phrase as;

Do it nice, not twice!

You can have that for free team!

Tomorrow i’ve got more of the same but am really looking forward to developing a rock solid testing strategy using React Testing Library, once i have my tests in place i’ll feel a bit more confident refactoring the UI.

I reckon with good tests you can re-build anything!

Day 85

Mar 25 2020

The first part of this is an update from last night. I just about had the brain power to tackle the Fork functionality i needed in www.skin-ui.com and am pleased to report that step one is done. I can now hit the Fork button and copy the default theme, give it a random name and push it up to Fauna. From here you can amend as normal.

I have been a bit of a hack monster in the process and now have loads of GraphQL types floating around. There’s currently only three operations that a user can perform in the application and all, i think should post and return the exact same data shape so i need to have a bit of a tidy up and work out if i can just have one type for all operations.

I also got up early this morning to tackle the delete functionality and.. wallop that’s now done too!

I now have Create Read Update and Delete!

The issue i have at the moment is that in my haste to ship i’ve neglected to write tests…

not even one! 🙀

For UI stuff i’m pretty ok and have confidence in my ability to have visually covered off all states the application could be in, but for the data i’m not so sure.

Apollo and Fauna are all totally new to me and whilst every thing appears to be working there’s a chance that it’s not, and when you start allowing users to push to a database i’m worried that it i’ve messed something up i’m gonna end up with data in Fauna that’s incorrect… then what do i do, delete it and piss off my users?

I might ask for some help here peeps. I could use Netlify’s preview deploy link and give it to a handful of people to test out and can ask for feedback but anything they do is still gonna end up in the database and as mentioned i might need to delete it later.

I’m gonna sit on this for a while as i have other areas i need to focus on.

I need to build a kind of users themes page and a global themes page and still need to check the sign up process works smoothly.

I have 15 days before the #100DaysOfGatsby challenge is up and i’m starting to feel the pressure. I’m really diggin my new job and not sure how much time i can commit to skin-ui.com over the next few weeks.

I’m also really getting in to drinking at home which is a major distraction!

Day 84

Mar 24 2020

Second day on the job and all is still going ok.

My task for today was to implement storybook. I love Storybook and it plays a huge part in my day to day work when developing component libraries but i’ve only ever implemented it with a Gatsby project once before and that was for my first theme gatsby-theme-gatstats

Like gatsby-theme-gatstats the project i’m working on also uses Theme UI and there’s a couple of little tricks one needs to implement to ensure all Theme UI styles get passed on to the component when viewed in Storybook.

The below is how you set up Theme UI in Storybook 5.3

// .storybook/preview.js
import React from 'react';
import { addDecorator } from '@storybook/react';
import { ThemeProvider } from 'theme-ui';

import yourTheme from '../src/gatsby-plugin-theme-ui';

addDecorator((storyFn) => <ThemeProvider theme={yourTheme}>{storyFn()}</ThemeProvider>);

The addDecorator works a bit like wrapRootElement does in Gatsby and provides a nice way to wrap all Storybook stories with anything you like.

Adding fonts is, according to the Storybook docs pretty straight forward however, nothing i did today using the preview-head.html seemed to work so i opted for using the <Global /> component from @emotion/core

// .storybook/preview.js
...
import { Global, css } from "@emotion/core";

addDecorator(storyFn => (
    <Fragment>
      <Global
        styles={css`
          @font-face {
            font-family: "Some Font";
            font-weight: 400;
            src: url("/fonts/Some-Font.woff2") format("woff2");
          }
        `}
      />
      <ThemeProvider theme={yourTheme}>{storyFn()}</ThemeProvider>
    </Fragment>
));

This is assuming you have the fonts located at public/fonts and have the -s flag in package.json pointing at ./public

  "scripts": {
    "storybook": "start-storybook -s ./public -p 6006",
    "build-storybook": "build-storybook"
  }

After i’d sorted that out i could now start creating stories for all the components in the code base.

I’ve done this a lot in the past but did want to experiment with pure .mdx based stories and whilst they work just fine they require you to import a number of things to get stories to display with props and previews.

Using the .js method or CSF Component Story Format in my option is just better and leaves less to get wrong. After all the whole point of having Storybook manage the documentation is so any engineer coming to the code base can quickly and easily discover how a component works, what props it needs etc and if you start to be a bit slack with the documentation the whole system breaks down.

I then moved on to unit tests and Alex has already started to implement @testing-library/react.

I’m gonna reserve judgement on this for the moment, but not because i don’t believe it’s every bit as good as everyone says it is but because it’s new to me and i need to work out if my battle hardened component testing pattern and CSF strategy works as well with Testing Library as it used to with Enzyme

So far today i’ve only written a handful of tests and they were pretty straight forward. I should imagine in time once i’m a bit more familiar with the methods i’ll get rolling but i still gotta learn and get my head round it.

That’s all for today team… keep it Gatsby! 🍺

Day 83

Mar 23 2020

This morning i was up early… and for good reason. I started a new contract today 🎉.

They’re a US based firm and are cool with me being fully remote… The stack?… Gatsby and Theme UI, how cool is that!

In fact it’s through the #100DaysOfGatsby challenge that Alex Luong found me and very kindly put me forward to work on a project with him.

It’s so cool that it’s happened this way and really makes it all worth while. I’ve been absolutely slogging a way of this stuff for the past 83 days and and it’s finally paid off.

Right ho, that’s the business stuff outta the way, back to my early start.

From around 5.30 this morning until 9.00 am when i started work i was investigating this pesky Object to String issue i was having.

The theme object is stored in Fauna as an object but i can’t type the response required by GraphQL as an object at this stage as there’s too many key value pairs. Instead i’ve typed it as a string which is what GraphQL is expecting.

Once i have the theme object as a string i’m storing it in application state and passing it on the preview which has a Theme Provider and uses JSON.parse which is how the styles get applied to the markdown and mdx.

In the Editor however i need to keep it as a string so it can be passed on to CodeMirror but i need to remove some of the quote marks around the key value pairs so it appears as JavaScript and not JSON… but, when CodeMirror passes this back via the onChange i intercept it and pop the quote marks back in before storing back in application state.

This means that each of those special requirements are handled in the places they are needed and won’t affect how the data is stored in application or in Fauna… bit of ball ache but it’s working now.

I’ve checked that saving to Fauna still works and everything is looking pretty sweet. With my test logins i can edit the object and save it back to my account

The next step is for new users to be able to Fork the default theme and to save it to their own account… i also need to think about some kind of users themes pages so you can browse and edit your own themes.

I think i’ve got everything in place to get this going but at the moment i’m not really sure what extra or temporary things i’ll have to add to allow the Fork to really work. I might need to auto generate a temporary made up name just so if you save it before you’ve re-named it you’ll see it in your users themes area.

It’s a bit of a head scratcher but i think i’ve got a plan… just need some time to get it all up and running.

Day 82

Mar 22 2020

Mother’s Day and Ma comes first. I’ve only done a few hours work today for obvious reason but i have sorted the useMutation callback. After an update is applied there’s an onCompleted arg that can be used to set state or whatever you need to do once a 200 response comes back. Currently i’m using it to hide a spinner that is set to visible when the save button is clicked.

This i think completes the update journey but yesterdays’ string to json to string parsing issue is still very much in play. I’m gonna need a good few hours to work out what to do with that which i don’t have time for right now so it’ll have to wait.

Day 81

Mar 21 2020

Only a few hours work this morning, i’ve got plans that require me to leave the house so i’m a bit short on time.

What i have managed to accomplish this morning is cracking how to use useMutation / @apollo/react-hooks and can now pass values from my form back to the Fauna Database via my Apollo / GraphQL api.

This however has un-earthed another problem which i need to un-pick a bit but in short it’s related to the transformation i’m performing on the Theme UI object. Here’s a list of data types the object currently exists in and where

  • Local State : string (modified with regex to remove quotes)
  • Application State : object (modified with regex to add quotes)
  • Database : string has quotes
  • Return type from Database : string has quotes

I think i need to workout how to keep the type the same in Application state and in the Database and leave the local state to manage the funky transformations as they are only required so the object displays nicely in CodeMirror.

I’m not even sure at this stage if i could type the Theme UI object as an object because GraphQL would want the full blown list of all object keys and their types. Unfortunately it doesn’t look like GraphQL has an any type like TypeScript does so it’s probably better to type the Theme UI object as string when i’m passing it around. It has to be a string in Fauna anyway so i think that’s pretty much how it’ll have to be.

This is quite the ball ache but i suppose it makes sense to keep the type the same in and around the application and in the database and only mutate it where i absolutely have to.

Probably a job for tomorrow now but i’m pleased i’ve made some progress albeit small.

Day 80

Mar 20 2020

I’m still sloggin a way on www.skin-ui.com and think i’ve resolved the react-codemirror2 syntax try / catch bug. If a syntax error occurs while editing the Theme UI object i’m catching it before it hits the application state and blows up. I’ve had to implement a 2nd part of local state to manage this but the application doesn’t appear any slower when using it so that all good.

I’ve now moved on to managing mutations with Apollo and GraphQL and have come a bit unstuck. As with any new technology you learn from your mistakes and i think i’ve over complicated the way context and database state work, and i think i’m gonna run in to a problem with the database callback when an update is issued. Somewhere along the line i’ll need to re-fetch the newly saved data, my current thinking is to update context which will causes all the right parts of the app to re-render.

But first things first and i need to get to grips with useMutation, once that’s done i think i’ll be in a better place to solve some of the UX issues.

I also experimented with Formik which i’ve used on a few projects but i don’t think it’s really required since i have little to no validation requirements and the value of my inputs all come from the backend.

It’s all part of the process so whilst today has been a challenge i’m still making progress.

Day 79

Mar 19 2020

Today hasn’t been all that productive.

It started off well and i’ve worked out some of the is the logged in user the theme owner and therefore should the primary call to action be to save the theme or to fork the theme… but then i got caught up in a react-codemirror2 bug chasing nightmare.

I think i mentioned this before regarding some mega regex that i’ve implemented that converts an object to a string and removes the quotes and then there’s some more regex to parse the string and re-insert the quotes, which is still required but i struggled to work out at which point in this transformation should the object be pushed to the database.

I’ve also run in to a few problems with Theme UI components, it appears Buttons error if an invalid string is passed as a hex. This causes the whole app to break so i’ve temporarily removed the <Button /> from the .mdx preview.

I’ve also got a few issues with how to manage try / catch on the actual object before i save it to state and there’s also some debounce-ing issue going on which i’ve implemented since the switched to a controlled version of CodeMirror.

I think they’re all resolvable it’s just today i’ve un-earthed multiple issues and need to pick which one to tackle first.

Either way these all jobs for tomorrow now.

Day 78

Mar 18 2020

react-codemirror2 saves the day!

I can now pass a theme object from my new Apollo / GraphQL server straight to the code editor and it’ll style the markdown as it did before. You can still update the theme using the editor and once i get the U of CRUD sorted out you’ll be able to save your theme to the Fauna database.

I’m still thinking about some of the UX issues i’ll face with this application. For instance if you where to share a link with someone they could view it but they might also want to fork it and continue to develop it under a different id. In this case the new Drawer component which houses the save button would first need to display a fork button. I think i can do this by checking if the user_id of the theme matches the logged in user_id if it does then it’s safe to assume that a save button is needed in the UI and if it doesn’t it’ll be a fork button in the UI.

This Drawer will also house a delete button and all the fields required to re-name the theme and or update the description and a pair of radio buttons to identify if the theme is a light or dark theme… this i hope will come in handy later in the gallery for filtering purposes.

I’m still wondering what to do about private themes, i had thought about a premium pricing model but the thought of hooking up a payment system at this point is a bit too much to take on. I’ll leave this field in the db but probably won’t use it for a while.

I’m posting a bit early today because i’ve got some life admin to take care off so this is pretty much me for today.

Day 77

Mar 17 2020

At what point can i claim to be full stack?

I’ve had such a belter of a day and got the first half of the Apollo / GraphQL / Funa / Netlify Identity work done.

I’m not even sure if i can fully recount what i’ve done today so i’ll try putting it in a list.

  • Shift Context Provider, Netlify Identity and Apollo Provider in to wrapRootElement
  • Use gatsby-browser as import for gatsy-ssr so the above works in prod and dev
  • Connect Apollo server to Fauna
  • Setup multiple resolvers to query Fauna via GraphQL
  • Implement initial functionality to query Fauna served theme object and re-hyrdrate CodeMirror instance / Theme UI Provider.

Actually on that note, the version of CodeMirror i’m using doesn’t like to be controlled via state, it appears that once it loads a string to use as a starting point for the code no state changes to that string will cause a re-render. There is another version of CodeMirror out there called react-codemirror2 which can be setup to handle changes in state but i played with this a little while back and there was an issue but i can’t remember what the problem was so that’s a job for tomorrow.

There are a few user journey / functionality things i’m trying to solve. These are all based around user sign up / sign in and how i’ll handle public / private themes… i might not initially provide the option to make a theme private but i will of course need to restrict saving updates to a theme unless you were the user that created it.

There’s also quite a bit of work to do around showcasing all the themes that are saved to the database by all users. I’d like a kind of gallery where you can view them or maybe fork them and save them to your own account.

It’s difficult to think in MVP terms because as soon as you introduce user sign up / sign in you’ve got a ton of work to do around, sign up verification journeys, forgot password journeys and of course everything to cover CRUD functionality.

Currently i’m aiming to have all this finished by the final day of 100DaysOfGatsby but… eeek i’ve still got a lot of problems to solve and still have a lot of things to learn so it’s a pipe dream at the moment!

I’m still enjoying myself though and it’s pretty dope building the full stack… not sure when i’ll get the opportunity to create an Apollo / GraphQL / Fauna / Netlify Identity stack again!

Day 76

Mar 16 2020

Full stack attack!

It’s been a day of ups and downs. I’ve been implementing Apollo and got the basic client Netlify function and a local users array all working and i am able to query the new GraphQL api when running gatsby develop

But… there’s some funky stuff going when gatsby build this is no doubt something to do with fetch not being available in Node so i’m trying to test and eliminate each of my suspicions one by one.

I’m currently wrestling with client side routes, if i can get this working i should be able to confirm that it is in fact a Node / Fetch issue but there’s quite a few other things i could try but need to do it methodically or else i’ll end up chasing my tail.

It is fun learning something new and i enjoy the process but i feel like i’ve put myself under pressure to perform as i’m writing about my progress each day… and today i’ve not really made great progress.

But… tomorrow is a new day so with a good nights sleep i’ll be ready to tackle it again tomorrow.

Day 75

Mar 15 2020

Not an overly productive day today but i am pretty impressed with last nights post and how well it reads considering my state when i wrote it.

Today i’m mainly beein trying to get a plan of action together about how to handle database access in www.skin-ui.com. I think Fauna looks like it will be a good fit but this is all new to me so i’m trying to work out how best to structure my repo and where to deploy Netlify functions from, also where in the repo should i build the GraphQL API layer and how is an API request handled dependant on if a user is logged in or not.

There’s some good tutorials by Chris Biscardi on egghead.io which give me a nice overview on how all of these technologies come together but i feel like i need to be a bit more research before i start hacking something together.

I’m also aware i’ve kind of fallen behind on the challenges, although i have seen one email about connecting to a CMS which i don’t really need for any of my current projects. If i get really stuck with the Skin ui database stuff maybe i’ll “pivot” to the CMS challenge so i can feel good about my self again.

Day 74

Mar 14 2020

Today’s update has to be short and sweet because i’m on the wrong side of 8 pints of sweet sweet Ale. I started the day by continuing to faff around with Context and have created a new Drawer component to expose additional functionality if you sign in / up

I’ll leave it there. 🍺

Day 73

Mar 13 2020

Mooooore context 😫

Yeap, today i’ve continued to refactor www.skin-ui.com and now, wherever possible state is managed by React context. There’s only two very small parts that remain as local state and the app seems so much more responsive. Prop drilling can really mess with an application and passing props through components to reach deeply nested components does really affect performance. It’s been a bit of a chore shifting everything over to use Context but i think it’s worth it as the the end result is an application that feels alive rather than an application that is noticeably putting the browser under a lot of pressure.

I’ve also found there’s other positives to undertaking work like this and because it’s quite repetitive and mind numbingly boring my mind has wandered… which is good because i’ve continued to think about what else skin-ui could be.

Today’s thoughts have mainly been around what i’m calling Cloud Themes … allow me to explain.

If i can get skin-ui to a point where user auth / teams auth are a thing you could have a designer using the browser UI and making and saving changes to the theme object… but then imagine rather than manually copying and pasting that theme object in to the code base it could just be in the code base and capture changes after they’re saved from the web editor.

I totally think this is possible if i were to write a build time Gatsby Plugins that once configured via gatsby-config.js using an id or something would connect to a (yet to be developed) skin-api and pull down the theme object and then continue to compile the app/site/blog with that theme object.

This might allow yet another abstraction of “web design” and “web development”… i’m thinking at the moment i could make the skin-ui UI more focussed on designers needs and provide easy to understand ways to modify the theme object along with an easy way to preview the changes then, once they hit save all that design work could be pulled in to the application and, et voilà you’d have styles for anything and everything the engineers could need to build out application functionality… this of course is dependant on Gatsby becoming the go to tool for larger builds.. but as i stated yesterday

Gatsby is just React

..so why wouldn’t you use it to build more than just blogs?

Day 72

Mar 12 2020

Gatsby is just React!

It’s pretty clear when you start with Gatsby that it’s everything React is and more but to be honest i’ve never really put it to the test.

When making themes and plugins i’ve not really had to do a lot of React, most of the time i’ve been able to leverage the Gatsby api’s to solve my problems but www.skin-ui.com is much more of an application than it is a site or blog.

I reached a point during development where local state was getting a bit gross and as i implemented more functionality i’ve had to start the dreaded prop drilling pattern which i know from experience never ends well.

I’m now pretty clear on the application architecture and it’s time to rip out local state and implement React Content.

I’ve used Context before on a few projects and do prefer it to Redux. I’m not at all attempting to compare the two but in this instance Redux would be over kill… that of course might change if the application grows further but for now it’s cool.

So today has been pretty much that. I’ve implemented Context, ripped out local state and hooked up Netlify identity through context too.

Day 71

Mar 11 2020

Today has been quite varied. Aside from trying to find a job i’ve still got stuck in and made some enhancements to www.skin-ui.com

First up i worked on a little bug i noticed when using the “Copy” button. It was indeed copying the theme object you see in the code editor panel but because it’s imported and rendered as a string before it’s passed on to CodeMirror when you paste it in to your own code editor it was missing the default export.

By adding export default { ${codeEditorData} } i’m able to correctly copy the actual theme object including the export default and surrounding curly braces from browser back to a code editor like VS Code.

I’ve also done some work on the string that is passed to the markdown source view. I’m importing the actual .mdx file that’s used in the app using the raw webpack loader and passing it straight on to CodeMirror but because it contains a bit of React and a Theme UI Box component they too appear in the “source view”. I tried to write my own regex to strip out the various parts of the string but ran out of skill so posted this on stackoverflow: Advanced RegEx Help required

I used a similar regex approach to remove the first 3 lines in that .mdx file which are importing the layout component. Now when you view the source using the little “eye” icon button you get something that’s easier to copy and past into your own project.

I’ve also added a new section to my commercial portfolio: side hussle which is an area for me to showcase things i’ve built that aren’t GitHub repos or Gatsby plugins… naturally www.skin-ui.com is on there.

It was really easy to add another source directory to the project and render the data as UI elements, and it kinda proves how flexible gatsby-theme-terminal is which makes all the hard work i did on the theme worth it!

I then came back www.skin-ui.com and have implemented Netlify Identity which, if you haven’t used is absolutely super brill brills!

I’ve done auth a few times before in React applications and it’s always such a ball ache, with Netlify Identity it was so easy and it even comes with third party auth providers like login with GitHub and Google etc… it’s mad how good Netlify are… i love it!

That’s all for today, tomorrow i need to investigate Fauna and see if i can spin up a database, this is all you can save your theme on www.skin-ui.com and is the first step towards building out a kind of user showcase gallery kinda feature.

Catch ya later!

Day 70

Mar 10 2020

Nude UI has been re-branded and … Skin UI is now live 🎉 www.skin-ui.com/

I’ve had a quite a few DM’s reporting firewalls blocking nude-ui.com on work internet connections, i also had a polite request to just change the name.

I always like to hear feedback and when suggestions are made that stand to improve matters, i’m happy to accommodate. 😊

I’ve also been working on accessibility, UX and performance improvements today all of which are going pretty well.

I get a bit hammered on the Lighthouse scores when on /editor but not because the application performs poorly but because there’s a YouTube Embed as part of the Theme UI components example… what can ya do ay!

But by far the biggest ball ache i’ve had today was trying to change the GoDaddy nameservers and adding forwarding from nude-ui.com to skin-ui.com.

I’m reliably informed by the GoDaddy tech support team that url forwarding is working although i’m still yet to see it myself, but it could take up to 48hrs so i’ll check it again over the next few days.

In the meantime my Netlify build pipeline which builds from pushes to the master branch deploys to both nude-ui and skin-ui which i’m sure will kill my build minutes but hopefully it’s only a short term thing.

There’s one or two things that i need to sort out so will probably set up a GitHub project and raise some issues, i think i need some help on one of the issues as it involves splitting MDX content and whilst have it working now it results in a shitty copy and past experience for users if they copy the source.

Also been thinking about next steps for this project and what i really wanna do is get the user auth and gallery parts set up but i don’t really know what to start. Kinda need a cheap / free db solution so if you know of one please let me know.

Day 69

Mar 9 2020

Nude UI is live! 🎉

It’s taken me a little over a week but today i launched an MVP of www.nude-ui.com/

In a nutshell Nude UI is a starting point for a few things.

  • Example markdown
  • Example Theme UI MDX Components
  • Example Theme UI theme object

I’ve found that when developing Gatsby themes i always have to hunt around to find complete examples of the above, and Nude UI amis to solve this problem.

I’m not sure at this point how people will use it but i’ve tried to include all the things that i’ve needed in the past.

Using the Editor you can quickly see the full Theme UI object and by editing it you can immediately see the effect of the changes on both markdown and Theme UI components.

You can if you like copy the theme object straight from Nude UI and paste it in to your own project and similarly if you want example markdown and Theme UI components you can access the source from the editor too.

I know there’s a few things missing and i plan on completing the theme object over the next few days but it’s a boring task and precisely why i built Nude UI but it does need to be finished.

I’m not sure what the next steps will be, i’m hoping it’ll be well received and via user feedback on twitter or through GitHub issues will probably help steer me towards phase 2.

If all goes to plan what i’d really like to do is create a gallery where users can save and showcase their “themes” and this in turn will provide yet more options for good starting points… but for that i need to go Full Stack and, well, i like the Front End of the Front End too much so i might hold off tackling that until i know if Nude UI is of use or not.

Stay nude guys and do let me know what you think @PaulieScanlon

Day 68

Mar 8 2020

Today was a game of two halves.

I’m still working on nude-ui and spent the morning implementing the remaining app functionality, this includes the ability to collapse the code editor panel and switch between the markdown / mdx preview and the source.

I did have a bit of a ball ache with parsing the mdx directly onto CodeMirror but chrisbiscardi came to my aid with a sweet little webpack trick.

import mdxString from '!!raw-loader!./thing.mdx';

This allows me to bypass the webpack loader for .mdx file types and import it as “raw” then finally pass it on to CodeMirror as a string.

I’ve also done a bit of design work today. I’ve got what i think is a pretty sweet looking hero / open graph image and have chosen a “tasteful” nude background image for the landing page.

Tomorrow i’ll focus on building out the landing page and i’ll probably start thinking about re-pointing the DNS records and setting up a Netlify build pipeline.

At some point this week i think i’ll be ready to launch!

Day 67

Mar 7 2020

For a Saturday i’ve been pretty productive.

I tackled the sidebar nav today on nude-ui. The main HTML elements were pretty easy to implement but nude-ui is becoming a bit of a position fixed-fest. The tricky part though was to extract the anchor hashes from the child .mdx and use them to populate the nav list, and then i needed to modify my scroll to anchor script in gatsby-browser.js so it only attempts to scroll to the position of the anchors in the page and not the anchors in nav.

Tomorrow i might tackle the landing page which might be a bit of a ball ache and i’ll need different layouts for the index and the editor pages. I think i’m gonna put the editor page in a folder outside pages and source it seperately then i can apply a default layout it.

i need to do some SEO and perhaps a bit of design for the open graph image then it’s time to deploy!

Day 66

Mar 6 2020

Another remarkably good day today.

nude-ui is coming together really well. I’ve finished off adding all styles for markdown and theme-ui/components and then set about adding application functionality.

I’ve added two checkboxes so the user can show / hide both the markdown and or components from the preview pain. I’ve also implemented the all important copy button, this will allow users to copy and paste the theme object in to their own projects.

I daren’t speak too soon but i think i’ve pretty much completed everything i wanted to in order to launch an MVP!

I’ll continue to tinker over the weekend and maybe try and release something Monday.

Day 65

Mar 5 2020

What a cracking day! Woke up annoyingly early but have now cracked the CodeMirror string issue.

CodeMirror if you’re not aware is the code editor that drives the likes of CodePen et al and provides code editor like behavior in the browser.

I’m using the React version by Jed Watson but it works in the same way.

The issue was for CodeMirror to display anything it needs to be provided as a string via the value prop… JSON.stringify() to the rescue!

<CodeMirror value={JSON.stringify(themeObject, null, 2)} />

but…

This will pass the the object as JSON meaning the output in CodeMirror will also be JSON and look something like this.

  "colors": {
    "primary": "#E91E63",
    "secondary": "#2196F3",
    "success": "#8BC34A",
    "warning": "#FF9800",
    "error": "#F44336",
  }

and yeap you’re right, that’s not JavaScript, and doesn’t actually represent what a theme-ui object would look like.

So we need to strip out the "" marks… but only on keys not on values and only if those values are not of type string … regex to the rescue!

JSON.stringify(themeObject, null, 2).replace(/"(\w+)"\s*:/g, '$1:');

but…

Now we need to pass the object back up to useState whenever a change occurs so it can be passed onto the <ThemeProvider />

I know what you’re thinking… JSON.parse() to the rescue!

… wrong!

<CodeMirror
  value={JSON.stringify(themeObject, null, 2).replace(/"(\w+)"\s*:/g, '$1:')}
  onChange={(event) => JSON.parse(event)}
/>

The above won’t work because JSON.parse() can’t parse this as JSON because we’ve removed the quote marks and these are what make it valid JSON…

Ahh!! so now we need to put the quotes back in … regex to the rescue again!

<CodeMirror
  value={JSON.stringify(themeObject, null, 2).replace(/"(\w+)"\s*:/g, '$1:')}
  onChange={(event) => JSON.parse(event.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": '))}
/>

Only now can we display a JavaScript object in the “editor” view and parse an object back to useState to drive theme-ui.

It was a challenge but regex really is a wonderful thing … top tip https://regex101.com/ is awesome!

Now that the editor / theme object / parsing issues are resolved i’ve set about adding the relevant key value pairs to the “example” object and have added the full list of markdown and theme-ui components to the preview so you can see the changes you’re making in the editor in real time.

Pretty sweet day i’d say!

Day 64

Mar 4 2020

Today was a jet lag day. I did a bit of work on nude-ui and am still wrestling with how to pass a JavaScript object as string to CodeMirror and then part it back out as an object to useState i think with a lot more Googleing i’ll find a solution but other than that no real updates.

Day 63

Mar 3 2020

Today was a mega travel day and i’m now back in the UK!

I did manage to sneak in a couple hours work on the flight but without internet access didn’t get very far. I continued to work on nude-ui and am trying to work out how to parse a JavaScript object in to CodeMirror as a string but i need to remove the "" using regex but i then need to pass it back out to useState as a JavaScript object… JSON.stringify and JSON.parse seem to be the obvious choices but the regex is tripping me up.

This is definitely a job for tomorrow now. It’s late and i’m tired.

Day 62

Mar 2 2020

Today i’ve started something new!

I’ve been thinking about it for a while but didn’t know if there’d be a requirement for it or if i could even do it.

So i started anyway 😎

I’ll start by explaining “the problem”, or at least some problems i’ve had in the past.

If you’re using markdown and .mdx in your blog or site and chose to expose the theme-ui/components as i have with gatsby-theme-terminal you need a pretty solid theme file. It’s got to cover everything in styles for the markdown spec, it should probably have every theme key described in the theme-ui/theme-spec and have all the relevant variants for theme-ui/components. Whilst the first two are well documented the components were a bit of a ball ache for me.

… and here’s my proposed “solution” I’ve decided to create a kind of object editor with live preview split screen so you can play around with the values for theme-ui and see the markdown and or components update right before your eyes.

The plan is to use local storage to “save” your work as you go and to provide a “copy” button so when you’re finished you can just copy the code and drop it straight into you project. Other ideas i’ve had are to be able to save your theme so others can use it. It could become a kind of marketplace resource for theme-ui but i gotta walk before i can run ay!

I’m not sure if this already exists somewhere and even if it does i’m gonna crack on anyway as it’s a good opportunity to learn something new.

As always i’ll be developing this in public and no doubt it’ll appear in a number of blog updates after today.

I’d welcome contribution on this one so if you’d like to get involved please find me on Twitter

Cheerio!

Day 61

Mar 1 2020

Today was a travel day … again! … but i have still managed to get a few hours work done.

I’ve released a new component in gatsby-theme-terminal called SourceMonths and refactored SourceDays so they both work the same way.

These components group any sourced .mdx file by year and provide some nice data points for days of the week and months of the year which could be used to create data visualizations.

With these two complete and released i think i could pretty much re-create the data viz on the dashboard of gatsby-theme-gatstats which is making me think, perhaps i should shift this blog over to using gatsby-theme-terminal?

I’ve also done a bit of house keeping and have turned off my Digital Ocean servers and deleted all but one app hosted on Heroku. Pretty much everything is now serverless and hosted on Netlify!

All in all a pretty productive Sunday!

Day 60

Feb 29 2020

I’ve had a very functional day today. I’ve been looking over the data visualization i created for gatsby-theme-gatstats and if i strip back the presentation layer (the bar charts, donut charts, etc) what i was actually doing was abstracting the data from all .mdx that had been sourced and working out some nice percentage and count values for the date fields pulled from frontmatter.

I’d like to expose this same data in gatsby-theme-terminal and have got a new component called <SourceDays /> which you can see here it’s like the other data components in this theme whereby it just returns values which you can then use to create the visual presentation layer. In the demo i’m just using the theme-ui components but i guess if you wanted to install your own charting library you could use these same values to drive any kind of data visualization.

I’ve released <SourceDays /> in 0.0.7 and started working on a component called <SourceMonths /> but realized it would probably be really handy if you could not only filter by source eg: “posts”, “projects” but also by year, this would then allow you to create a comparison chart for posts, tags used etc for multiple years.

I’m gonna keep working on this as it’s a good opportunity to work on some functional programming skills which i always struggle with but do quite enjoy!

Day 59

Feb 28 2020

What a great way to finish off the month. I’ve been overwhelmed by the likes and retweets from yesterdays announcement regarding the launch of my new theme, one chap by the name of Rob Blake even said…

Hey Paul, great work. I’ve been reading your blog and looking at some of the stuff you’ve been working on and I’m impressed. Inspired might be a better word. Thanks for sharing.

… which is music to my ears! I’ve been digging deep in to Gatsby related stuff for over a year now and it’s so good to know others find it as interesting as i do.

If you’re reading this post Rob… thanks so much for your tweet!

Other bits i’ve been up to today are writing a post about the new theme, why i built it and some methodologies i feel are important in theme development. You can read that post here

And then finally i got round to catching up on the #100DaysOfGatsby challenges and have now completed challenge, 7, 8 and 9 on my new commercial portfolio pauliescanlon.io/ … i’ve got ot be honest making it a PWA doesn’t seem that important but it’s good to know how to do it and it does impact the overall Lighthouse score which is now pretty decent! 😊

So that’s it for today. I’ve got to have a bit of a think about what to do next and with only a few days left of my trip i should think it’ll be just tying up loose ends… oh and i still need to find my next job so if you know of anything please let me know!

Day 58

Feb 27 2020

Stick a fork in me i’m done!

Yeap, today i finished off and launched my new theme gatsby-theme-terminal.

It’s been a bit of a labour of love this one, mostly because i wanted to update my commercial portfolio and turn the Digital Ocean servers off.

With Gatsby and locally sourced files and the theme sorted i’ve updated my portfolio which uses the theme… and here it is 👉 pauliescanlon.io

Now finally i get some decent SEO for my portfolio… and hopefully more work!

I think the theme can pretty much do whatever you need and i think i’m on to something with the data components and plan on creating a few more for different data sources in the next releases.

… that’s me for today!

Day 57

Feb 26 2020

Today has been brilliant and for two very good reasons.

  1. I’ve completed my new theme 🎉 but.. i’m not quite ready to announce it.
  2. To test drive new theme i’ve updated my current commercial portfolio which now uses it as a theme and it works in every possible way i hoped it would!

I feel like my new theme offers a lot more than just being a theme, and perhaps that’s what John Otander, Chris Biscardi and the rest of the Gatsby team who developed “themes” envisaged all along but for me it’s been a journey but i think i finally get what a theme really is.

When you think of themes and compare them to e.g: Wordpress Themes i think of a code base that does everything in a predetermined way and all you have to do is provide the content.

I feel that after a lot of experimentation with Gatsby themes they can be and are so much more.

My first theme gatsby-theme-gatstats took on a very motherly role and formatted everything for you and provided functionality in a certain way so long as you provided it with what it needs.

My new theme is the total opposite, yes, it does require frontmatter in a particular way but quite literally everything else is up to you.

If you want multiple pages, no problem, if you want multiple data sources, again no worries, if you want your posts list displayed in any given page / route, my new theme can do this, if you want a button a card or an avatar my new theme has got your back!

It’s yet to be decided if theme users will get on board with this approach and i’m hoping it’s not too far away from the current theme expectations and where it differs is for a good reason.

My new theme styles everything you could possibly need and provides data in nicely formatter ways to help drive your UI but the composition of the theme is entirely up to you.

I have high hopes for this one but fear my lack of followers on Twitter will be a bit of a problem.

If you’re reading this and aren’t following me please do and please share my work

Thanks in advance! 🙏

Day 56

Feb 25 2020

Absolute whirlwind of a day. Not sure if you’ve ever used BrowserStack … and it’s slow at the best times but try doing it tethered on a 4G iPhone… 😡

The reason i needed to use BrowserStack today was to test some “recipes” i’m providing in my theme docs and one is for a “Card” based flex grid arrangement which heavily relies on flex … i know from previous painful experiences that IE11 has trouble with flex so just out of curiosity i decided to see how my recipes were looking in IE11 on Win 10

… needless to say on the first attempt they looked terrible so i’ve spent about 4 hours painfully trying to debug IE11… but, pleased to report it’s now all sorted!

With that ball ache completed i’m getting very close to completing my new theme.

I’ve double checked the theme-ui/components styles and have full styles for the standard markdown spec… but,

does theme-ui work in IE11?

Day 55

Feb 24 2020

A much better day today! I’ve finished off the list of style objects for all theme-ui/components … there are one or two that i can’t seem to style but i’m not sure if it’s me or a problem with theme-ui.

I know the package is undergoing some changes so i’ll wait for a bit in case the issue is raised and or fixed with the next release.

Other bits i’ve done today include tidying up styles, further reducing the amount of theme specific components, i’m basically down to six now.

These are;

  • Logo: Which is just a placeholder ready to be “shadowed
  • Main: Which is really just a place to compose the <Nav /> and the <MDXProvider /> + all the theme-ui/components supplied via the components prop
  • Nav… you know what a Nav is right… it does compose one of my other plugins though gatsby-mdx-routes
  • Seo: Just handles the meta stuff…
  • And x2 layouts, one for Pages and one for content sourced from outside src/pages, the latter requires the <MDXRenderer />

And thats pretty much it!

The footprint of my new theme is gonna be really small and there’s very little to maintain and i really hope, very little that can go wrong.

I’ve also implemented anchor scroll to hash and theme-ui.com/packages/prism/ which if you haven’t used … is absolutely brilliant

I’m aware i’m a little behind the actual challenges so i think the next few days ought to be investigating what they are and if i can shoe horn them into my new theme.

If all goes to plan i might be able to release the theme this week!

Day 54

Feb 23 2020

Today was a travel day so i haven’t been able to do much. However, i have made a start on creating a list of all the theme-ui/components and their default objects. I think once again i’m either doing something wrong on there’s some issues with theme-ui/components.

For example in the docs for the <Badge /> component it says it’s default variant is primary, so you should be able to use it like the below and it “should” pick up styles defined in theme.badges.primary

<Badge>I'm a badge</Badge>

… but no matter what i do if i attempt to use a badge without the variant prop it defaults to the theme-ui built in styles

I’ll continue to work on this as it’s a big part of my new theme and i want the full set of components to work so i need to work out where all these components grab their styles from to make sure i’ve got them all covered.

Tomorrow is a new day, i’ll tackle it then!

Day 53

Feb 22 2020

Today has been spent mainly thinking about stuff. I did some code and have now sorted the navigation problem i was having with my new theme.

The things i’ve been thinking about today may only apply to very specific circumstances but perhaps if you’re reading this and have had similar thoughts, lets talk; @pauliescanlon

To give some context what i’m attempting to do with my new theme is provide everything that theme-ui/components offers via the use of the components prop on the MDXProvider

Here’s the setup in .js

// some-layout.js

import { MDXProvider } from "@mdx-js/react"
import * as themeUiComponents from "@theme-ui/components"

  <MDXProvider components={....themeUiComponents}>
    {children}
  </MDXProvider>

… and here’s the usage in .mdx (where <Button /> is the theme-ui/components button component)

// some-page.mdx

# Hey

Some other text

<Button>Click me</Button>

Using this approach i hope to make a zero component theme and what i mean by that is there won’t be any presentational components provided by the theme itself.

The theme will only expose what i’m currently calling data components which allow for a better level of abstraction in a theme as they only concern themselves with data, not UI.

Using this approach the theme author only needs to provide a set of data components that manage querying GraphQL and it’s up to the theme user to decide what to render.

The cool bit is all of the “things” they’ll likely want to render will have already been styled either by theme.styles or components

Here’s any example usage of a <SourceTags /> data component i’m developing.

<SourceTags>
  {source => (
    <Flex
    sx={{flexDirection: 'column'}}
    >
      {
        source.map((tag, index) => {
          const { name, count, percent } = tag
          return (<Box  key={index}>
            {`${name}  x${count}`}
            <Box mb={2}  bg='muted' sx={{width: `${percent}%`, height: 4}} />
          </Box>
        })
      }
    </Flex>
  )}
</SourceTags>

Inside the <SourceTags /> component is where i query GraphQL and also do a bit of functional JavaScript to return a nice object with the name, count and percent of each tag found in frontmatter

In this example i’m rendering a <Box /> which displays the name the count and a kind of horizontal bar chart. All of this is made using theme-ui/components NOT components provided by the theme.

The bit i’m currently stuck on is how to manage the styles for both markdown nodes and theme-ui/components

eg:

In your theme you probably have something like this

// gatsby-plugin-theme-ui/index.js

export default {
  ...
  styles: {
    p : {
      ...
    }
  }

}

But when you introduce theme-ui/components you also need

// gatsby-plugin-theme-ui/index.js

export default {
  ...
  styles: {
    p : {
      ...
    }
  },
  ...
  text : {
    ...
  }

}

The reason behind this is if your theme users write body copy it’ll get translated to a p and if they choose to use the <Text /> component it will by default render as a div unless they tell it it’s a p, <Text as='p'/> … in either case the <Text /> component will look only to the text object in the theme, not the p object in the theme.styles.

So if like me you’re planning on supporting both markdown and theme-ui/components in .mdx you’ll need to spread styles across both of those objects.

eg:

// gatsby-plugin-theme-ui/index.js

const textStyles = {
  fontFamily: 'body'
  fontSize: 1
}

export default {
  ...
  styles: {
    p : {
      ...textStyles
    }
  },
  ...
  text : {
    ...textStyles
  }

}

So step one of this process for me will be to comb over the theme-ui/components docs and construct a list of all the theme object keys the theme-ui/components look for by default.

This above <Text /> example refers to this or more specically this

Text style variants can be defined in the theme.text object.

Once i have the full list of default object keys i can begin to work out where the spreads need to occour to ensure consistent styling between markdown and .mdx

Wish me luck!

Day 52

Feb 21 2020

Felt like a bit of a slog today.

I’ve carried on themeing my new theme, got the nav / responsive nav working and got SEO hooked up and sorted the Netlify build pipeline.

I’m a little disappointed with how the nav is looking, and to be fair i didn’t actually design it i just riffed it and coded it but it’s not pretty! 😩 …might have to go back to design briefly and smarten it up.

No real problems today apart from something that’s been bothering me for a while but i’ve been working around it and that’s how VS Code / Prettier don’t ever seem to format my .mdx properly.

Might ask for help on Twitter about this one as it’s got me stumped.

Day 51

Feb 20 2020

Today i’ve continued to work on my new theme and it’s getting a bit tricky in places.

I’m using theme-ui but i have encountered a couple of things that are causing me to scratch my head.

If you’re using markdown that’s all well and good, you can use the styles.h1 object in theme-ui and set your styles for eg; h1

But..

In .mdx where of course i can still use # h1 but only if it’s not wrapped by a theme-ui component.

Let me explain…

In markdown i might wanna do this.

# Hey, i'm a header

and i'm some body copy.

![Some Image](/images/some-image.png)

But with .mdx you’re able to position the body copy and the image next to each other using a combination of <Flex /> and <Box />

For example

<Flex sx={{ flexWrap: "wrap" }}>
  <Box
    sx={{width: ['100%', '50%']}}
  >
  # Hey, i'm a header and i'm some body copy.
  <Box>
  <Box
    sx={{width: ['100%', '50%']}}
  >
  ![Some Image](/images/some-image.png)
  <Box>
</Flex>

But because both <Flex /> and <Box /> are technically React components the markdown contained within them won’t render.

Instead of using # h1 you can use the theme-ui/components <Heading as='h1' /> component…

but… it won’t by default pick up the same styles from styles.h1, instead it’s default place to look for styles is styles.headings

Which means to get the same styles applied you have to define a const elsewhere in the theme, then spread the styles into both of the style objects.

Furthermore… and i might be wrong on this but styles.headings.h1 doesn’t do anything.

One way round this is to use the heading component like this <Heading as='h1' variant='styles.h1' /> which is a bit of a faff when what you really want from a writing experience is to quickly style your content.

If i’m barking up the wrong tree on this, my apologies or if you know where i’ve gone wrong please do tweet me @pauliescanlon

Day 50

🎉 Feb 19 2020

Day 50 and i’ve posted something every day for 50 days and i’m feeling pretty pleased about that 🥳

Today started a little differently and i’ve gone a bit off piste, the reason for this side step is because during my alpha tests for gatsby-plugin-prop-shop i created a PR for theme-ui and got a lovely response from jxnblk who thought PropShop was a really cool idea… which made me very happy!

Thanks! This is a really cool idea!

He then went on to explain that @theme-ui and all of it’s packages are undergoing some changes, namely the whole repository is being Converted to TypeScript and that it might be best to wait until that work has been completed before the PR is merged in.

Upon reviewing the issue i noted that the maintainers are actively looking for help and if you wanna get involved just name the package you’d like to convert and you can claim it.

So that’s what i’ve done, i spent this morning converting theme-ui/packages/components/ to TypeScript and here’s the PR

I did get a bit stuck so have pushed my changes and asked for help then i jumped back on developing my new theme and have been continuing to work towards this minimal set components idea.

This approach seems to be working really well and i’ve even tried using render children from .mdx which works a treat!

I might write a follow up post about why i think this approach is so powerful for theme development but maybe i should finish developing the theme first ay!

Day 49

Feb 18 2020

I’ve had a very productive day today!

I really wanted to nail down how to manage dynamic .mdx sources.

To explain this a bit more, i need to reference GatStats again. In GatStats to use the theme you have to put all of your .mdx blog posts in a directory located at src/posts and the resulting URL will be

http://www.your-site/posts/some-post

However, what if you wanted to have a posts and a projects or maybe a talks directory as well?

You can’t because in the theme i’ve configured it to only source .mdx from src/posts… which sucks!

In my new theme i’m exposing a tiny bit of config in gatsby-config.js and allowing the user to tell the theme where to source .mdx from, in the example below the theme will look in both posts and projects

module.exports = {
  ...
  plugins: [
    {
      resolve: `@pauliescanlon/my-new-theme`,
      options: {
        source: [`posts`, `projects`],
      },
    },
  ],
}

This can be passed onto the gatsby-config.js in the theme.


module.exports = themeOptions => {
 const { source } = themeOptions
 ...
}

From here i’m able to first test if source is a single string or an array of strings, and then dynamically create a gatsby-source-filesystem config in the plugins array.


module.exports = themeOptions => {
  const { source } = themeOptions

  let filesystemSources = []

  const sourceFilesystemOption = name => {
    if (source) {
      return {
        resolve: `gatsby-source-filesystem`,
        options: {
          name: `${name}`,
          path: path.resolve(`src/${name}`),
        },
      }
    }
  }

  if (Array.isArray(source)) {
    for (let item of source) {
      filesystemSources.push(sourceFilesystemOption(item))
    }
  } else {
    filesystemSources.push(sourceFilesystemOption(source))
  }

  return {
    ...
    plugins: [
      ...
      ...filesystemSources,
    ],
  }
}

That’s the first part sorted, the next part was a bit tricky.

Because you’re sourcing .mdx from outside src/pages you have to use the createPage api to create a page for each file found.

Over to gatsby-node.js

First i needed to create a slug on each node, this can be done using createNodeField but… i only need to this on nodes that don’t already have a slug

Any .mdx sourced from src/pages will have this field already because i’m using my plugin gatsby-mdx-routes 😎

so in the if i check both that the node.internal.type is in fact .mdx and then i check that it’s not a file that’s already had a slug created.

exports.onCreateNode = ({ node, actions, getNode }, themeOptions) => {
  const { source } = themeOptions;

  const { createNodeField } = actions;

  if (node.internal.type === 'Mdx' && !node.internal.fieldOwners) {
    let path = source;
    const value = createFilePath({ node, getNode });

    if (Array.isArray(source)) {
      path = node.fileAbsolutePath
        .split('/')
        .filter((str) => source.includes(str))
        .toString();
    }
    createNodeField({
      node,
      name: `slug`,
      value: `/${path}${value}`,
    });
  }
};

The bit that took me a while to work out was what to use as the path.

What i want to happen is any .mdx sourced from src/posts would have a URL of,

http://www.your-site/posts/some-post

and if it’s sourced from src/projects it would have a URL of,

http://www.your-site/projects/some-project

If the source is single string that’s pretty straight forward and i can use it as is.

  let path = source
  ...
  createNodeField({
    node,
    name: `slug`,
    value: `/${path}${value}`,
  })

… but if the source is an array i need to be able to determine which source the file has been sourced from so the correct path can be added to the createNodeField value field.

I did try and loop over the array and the call onCreateNodeField from inside the loop but this won’t work because onCreateNode is itself called on a loop.

The only other part of the node that is exposed which i can use to perform this kind of logic is node.fileAbsolutePath and by using split together with filter i’m able to get at the bit i want, the posts or projects which can then be added to the createNodeField value field as before with the string.

Once that’s all sorted you can continue to follow the Gatsby docs creating-pages

I’m fairly confident this is a solid enough way to query .mdx files from any directory in the src directory, i might need to re-think this if i want to allow the theme to be able to source from anywhere…

Using a content directory seems to be a popular pattern… but it’s my theme and i think src is a good enough place to put your source files

Day 48

Feb 17 2020

Today was a travel day so i’ve only done a few hours work… but. I’ve continued to work on my new theme and it’s coming together nicely. I mentioned before about learning from the mistakes i made with GatStats and this time around i’ve gone all out with the developer experience. I’m going to try and keep custom components and config to an absolute minium in favor of exposing as much as i can though .mdx

Reason being is that with GatStats the only viable option for customization is component shadowing, and this as good as it is feels like a lot of un-doing of what a theme is supposed to provide.

I want this new theme to be as easy to customize as it is to write markdown.

To give you an example, on the home page rather than asking the user to whack a load of stuff in the config so i can query it and pass it down to a a component in .js to then fit it into a grid/column layout, i’m going to provide functionality through the MDXProvider components prop and passtheme-ui/components straight though the.mdx. There will of course be a little styling to manage so when these components are used they’ll still feel like part of the theme but the difference will be the user can decide what goes where and how it’s laid out.

eg:

<Flex sx={{ flexWrap: 'wrap' }}>
  <Box
    sx={{
      width: ['100%', '50%', '33%'],
    }}
  >
    <Heading variant='styles.h1'>contact</Heading>

    <Heading variant='styles.h2'>Email</Heading>
    <Link href='mailto:pauliescanlon@gmail.com' variant='styles.a'>
      pauliescanlon@gmail.com
    </Link>

    <Heading variant='styles.h2'>Twitter</Heading>
    <Link href='https://twitter.com/PaulieScanlon/' variant='styles.a'>
      https://twitter.com/PaulieScanlon/
    </Link>

    <Heading variant='styles.h2'>GitHub</Heading>
    <Link href='https://github.com/PaulieScanlon/' variant='styles.a'>
      https://github.com/PaulieScanlon/
    </Link>

    <Heading variant='styles.h2'>GitHub</Heading>
    <Link href='https://www.linkedin.com/in/pauliescanlon/' variant='styles.a'>
      https://www.linkedin.com/in/pauliescanlon/
    </Link>
  </Box>
</Flex>

using <Flex /> and <Box /> you can create any colum layout you like, straight from the .mdx. 🤯

You’ll also see above the use of <Heading /> etc, these are theme-ui/components and will be styled in accordance with my theme design the same way a # heading would if used in markdown.

I think it’s gonna be a sweet theme and i will definitely be using it for my commercial portfolio once it’s released!

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 Plugins 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 Plugins 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 solved 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 Styled-Components 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 submenu 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 Plugins 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.

Hey!

Leave a reaction and let me know how I'm doing.

  • 0
  • 0
  • 0
  • 0
  • 0
Powered byNeon