Silly Site Challenge
BumHub The cheekiest way to explore GitHub
Go Go Go
Nov 23 2020
Iām at it again šŗ
If you followed along when I did my 100 Days Of Gatsby youāll know I have a tendency to write way too much about very little š„
ā¦ but because 100 Days Of Gatsby was an absolute tray of cakes Iām super excited to be doing it again for the recently announced Silly Site Challenge
If youād like to know more about the challenge hosted by Gatsby have a read here and be sure to follow GatsbyJS on Twitter or search for the hashtag #SillySiteChallenge
This time round Iāll be doing things a little differently because updating a blog post every day for 100 days was, as youād imagineā¦ an absolute ball ache!
Instead iāll update less frequently but with more significant informationā¦ deal?
Greatā¦ see you around!
Update 1
Nov 24 2020
I donāt wanna give the game away so hereās a little teaser about whatāll iāll be working on.
I've made good progress on phase 1 of my idea for the @GatsbyJS #SillySiteChallenge... I don't wanna reveal too much too soon but... it's gonna be cheeky! š
— Paul Scanlon (@PaulieScanlon) November 24, 2020
If you'd like to get silly too sign up here: https://t.co/CZTfcFnKNo pic.twitter.com/CWcGbry4Yr
Update 2
Nov 26 2020
Update 2 of my progress with the @GatsbyJS #SillySiteChallenge
— Paul Scanlon (@PaulieScanlon) November 26, 2020
Today I 'm dabbling in copywriting and art direction. This is always my least favourite part of any side project š
If you wanna get silly with me, sign up here: https://t.co/CZTfcFnKNo pic.twitter.com/vyBy4a7IKA
I thought this update might dive into my process a bit. I still donāt want to give the game away by sharing too many visuals but there were a number of things I needed to work on before I announced iād be taking part in the Silly Site Challenge
The reason for this is because the idea I have largely depends on two key things.
-
- Can I get my pea brain around the GitHub REST API docs
-
- Can the GitHub REST API return data I can use?
Iāve spent about a week investigating this and I suppose in agile terms this might be known as a Spike.
If youāre not familiar with agile ways of working a spike can be used where the outcome of a thing is uncertain and needs to be investigated before everyone gets too excited and starts presenting ideas to stakeholders.
Now, granted my puny Twitter following is hardly the same as having commercial stakeholders but the theory is the same. I didnāt want to announce I was going to do something until I was sure I could deliver.
Iām pleased to report that I have been able to understand the GitHub REST API docs and it can return data I can use to bring my idea to life.
There was also a second spike required for my ideaā¦ and try to follow along as my mind unravels.
As you might know Gatsby recently announced the new Routes API and I was going to write a blog post about that and perhaps provide a working demo link and repositoryā¦ but then I thought to myself;
No Paul, thatās not good enoughā¦ write an entire application, develop it in public and somehow weave it into the #SillySiteChallenge
So thatās what iāve been doing. The new Routes API is amazing, and I have already seen a few Tweets and posts from folks explaining how it worksā¦ however, and this isnāt to knock anyoneās hard work, these examples all seem to be regurgitations of the the Gatsby docsā¦ and because I like to make my life difficult I started to think about ways to make my demo of the Routes API a bit different. Then it hit me.
Thereās a section in the docs that says the following:
Use the File System Route API when you want to programmatically create pages from your GraphQL data, e.g. to create individual blog post pages for your blog. With this API you can control the file path and queried data by adding some extra notation to the names of your files without touching or creating gatsby-node.js whatsoever.
The key part is this bit āwithout touching or creating gatsby-node.js whatsoeverā. This statement is 100% accurate but
it only applies if you already have the nodes in the GraphQL layer. This would be possible if you had a load of pages as
actual files on disk, eg. .js
, | .tsx
| .md
| .mdx
butā¦
What if your āsite contentā doesnāt exist on disk? What if your āsite contentā comes from a remote source, a CMS for
example, or in my case a RESTful API. In this scenario you will absolutely need gatsby-node.js
ā¦ and therein lies an
angle for my silly site idea.
Iāll be using a remote RESTful API to source data using gatsby-node.js
which creates the nodes in the GraphQL layer
and THEN I can use the new Routes API to create pages from those nodesā¦ simple eh!
But when I conjured up this elaborate plan I wasnāt sure if it would workā¦ hence the second spike.
Ok cool, so now the idea is coming together, I can create pages from remotely source data at build time and iāll be able to do something with itā¦ but what data? all I want to say at the moment is it has something to do with the word ābumsāā¦ because bums are silly!
Naturally ābumsā might be considered offensiveā¦ I donāt know how exactly, but It would be prudent to tread carefully so Iāve now entered into the art direction phase of the project.
I need something that looks and feels funā¦ just like a bum. Iāll be honest my designer days are long behind me but I do still have an eye for it so I spent a few days researching illustrators on dribbble and found this cheeky little ghost by the wonderful Miss_ChatZ so Iāve gone ahead and commissioned her to create a logo and some ancillary character illustrations.
The reason for this is thereās another twist to my silly site idea. Since iāve decided to develop in public iād like to start sharing a dev link of my progress butā¦ to keep you all interested the site will automatically and progressively get more interesting throughout December, Iāll say no more for now.
Then lastly. Because Gatsby is predominantly a static site generator (it can do much much more FYI) it is by itās very nature quite Eco-Friendly and by this I mean because the grunt work is handled server side at build time rather than by each and every browser that visits your site at run time much less of the worlds power is used up. Much less power means much less CO2, and much less CO2 makes for a healthier planet.
I should point out here iām not attempting to say āIām making the world a better placeāā¦ iāll leave that to the tedious Twitter rock stars and the writers of Silicon Valley who made it into a very funny joke!
Instead I plan to surface some of this Eco-Friendly data by leveraging statistics provided by EcoPingā¦ This one is a bit up in the air at the moment but Iām in discussions with the makers and hope to have some firmed up answers soon.
So there you go, as promised a slightly more in depth update and I hope iāve piqued your interest.
If youāre interested in taking part in the #SillySiteChallenge hereās the sign up link again. www.gatsbyjs.com/silly-site-challenge
Stay silly everyone š
Update 3
Dec 2 2020
They call me Mr BUMbastic! š ...
— Paul Scanlon (@PaulieScanlon) December 2, 2020
Update 3 of my #SillySiteChallenge hosted by @GatsbyJS, and there "might" be a link to the WIP build in my blog post!
Did someone say clickbait? šŗ
Illustrations by the fantastic @Miss_ChatZ https://t.co/V9UXemdawo pic.twitter.com/SOsFqYMH1V
I feel like iām really making progress now, so much so iām now happy to share a link šŗ
Iāve continued to work with the magnificent Miss_ChatZ whoās delivered the first of the characters iāll be using on BumHub, aptly named Pants Down and Pants Up which are used in the Advent Calendar cards.
Pants Down is used when an Advent card is click-able which is determined by working out if itās the current day or if the day has passed.
Pants Up is used when an Advent card is disabled which is determined by working out if the day number is in the future.
Iāve also added the custom components to the Bum UI page where you cam see how the components look and how they can be configured with props.
The current date
is provided by my
api so you wonāt be able to cheat it
by changing your system clock! In the short term though this might cause a bit of a hiccup.
The data required to populate the Advent Cards is actually sourced at build time so in theory no JavaScript is required for these to render on the page butā¦ because this is an Advent Calendar I only want to reveal a card when itās the current day therefore JavaScript is required to make the api call to get the current server date. I think iāll leave this as is for now as itās part of the charm of an Advent Calendar but, after Dec 25 thereās no need to disabled any of the cards so Iāll remove the api call so this page will continue to work even if JavaScript is disabled.
Iāve also added a bit of pure CSS animation to the starburst seen behind the main logo. This was achieved using some fun
nth-of-type
selectors and animation-delay
durations. You can see the src
here. I hadnāt actually
tried to use animation keyframes in Theme UI before but having had a look at the
src
I could see how Theme
UI have achieved this in the <Spinner />
component.
Iām hoping to tackle the EcoBum section next. I have it on good authority that EcoPing are in the final stages of testing the special endpoint required to calculate BumHubs carbon usageā¦ in human farts no less!
Usually I donāt love the art direction part of my side projects but this time round iām really enjoying seeing what Miss_ChatZ creates and when I add them to the design it suddenly springs to life.
Iām also really happy I completed the two spikes as mentioned before because iām now 100% sure that I can work with the data Iām receiving which makes the UI development an absolute breeze!
Stay tuned and iāll update this again when iāve completed the next phase of development.
Update 4
Dec 3 2020
"Holy double curly brackets Batman" š¦
— Paul Scanlon (@PaulieScanlon) December 3, 2020
The new @GatsbyJS Routes API really is as good as I hoped it would be! š
Update 4 of my #SillySiteChallenge is here šhttps://t.co/V9UXemdawo pic.twitter.com/5HiRhqUdOz
I had a good hack on BumHub last night and dusted off my PhotoShop skills and designed the /bums/-name-of-repo
page
template.
This is the part of BumHub that uses Gatsbyās new Routes API.
As mentioned below, the docs say you no longer
need to touch gatsby-node
to create pages butā¦
In my case because iām sourcing the data at build time I still need gatsby-node
to create the GraphQL layer from the
GitHub REST response but, once the data is in āGatsby worldā the new Routes API takes over.
You can see the src here,
youāll notice the name of this file is {adventBums.name}.tsx
, the bit between the curly brackets is a node from the
GraphQL layer I create in gatsby-node
followed by .name
which is a key in the response object.
This NASA level regex is how the Gatsby engineers allow us to create pages from nodes, or in my case nodes that are repository names sourced from GitHub. Thanks Gatsby engineers, this is some top shelf tekkers!
The Jsx in the āpage templateā is populated by using a good old fashioned Gatsby page query plus the node $id
, that
part is actually old school Gatsby but I do really like the new Routes API, using createPages
in gatsby-node
was
always a bit of faff.
This latest feature completes my rather ambitious goal of weaving multiple ideas together to form one entity worthy of a#SillySiteChallenge submission and the Routes API was always at the core of this so iām pleased it works, itās styled and is out there for all to see. šŗš»
Update 5
Dec 8 2020
Ever wondered if it was possible to measure your websites carbon usage in human farts?... of course you haven't, why would you! š¤·āāļø
— Paul Scanlon (@PaulieScanlon) December 8, 2020
Well I did and hereās the result š¤
Update 5 of my @GatsbyJs #SillySiteChallengešhttps://t.co/V9UXemdawo
Illustrations by @Miss_ChatZ pic.twitter.com/iNYB29iAJ6
This update is a bit of A Tale of two Cities. A city called client side and a city called server side.
Letās start with the client side.
I normally use the Fetch API, in fact I love Fetch, itās native to modern / non crappy browsers (IE iām talking about you!) and from what I gather pretty lightweight and lastly, it gets the job done. Butā¦
Fetch runs in / on the Window object and it canāt be used server side to make HTTP requests.
So what about server side?
The server side equivalent is Nodeās http module which is built in to Node and does indeed also get the job done.
ā¦but this want to use native functionality poses a problem for the Jamstack developer. If like me youāre in a situation where you have a requirement to make both client and server side http requests do you opt to keep things native or do you opt for a solution that works consistently across the stack?
For BumHub iāve gone for consistency.
Iāve chosen to use axios.
I wouldnāt normally choose this but it can run both client and server side which means my http requests can be written in a consistent fashion. For me on this project, this matters.
Jamstack development requires the humble Front End Developer to be many things and quite frankly itās sometimes too much for my pea brain to take. I feel like I have enough to worry about just making sure my CSS works across the million and one screen sizes that exist. I donāt need to be worrying about really dweeby http request methods. If axios can do what it does in the same way when running in Node (server side) as it can in browser (client side) and can be written the same in my project on both sides of the stack then iām happy to let sleeping dogs lie and crack on with the good stuff.
Thatās my opinion there are many other valid ones.
That said I now need to do a bit of refactoring to my
<MrFetchy />
component as it currently
uses fetch not axios.
The reason for this quandary is that in this update iāve implemented the EcoBum section which utilizes a special end point created for me by my pals at EcoPing. This endpoint is still experimental so exposing it client side might cause some headaches. Instead, iām making the request server side and storing the request address in an environment variable so it stays a secretā¦ for now, and because Iām making the request server side I need some kind of http request methodā¦ actually this update is quite dweeby, sorry about that.
Anyway, thereās now a Bum on the index page farting and some lovely eco friendly stats about BumHubās carbon usage.
Enjoy.
Update 6
Dec 10 2020
Update 6 of my #SillySiteChallenge hosted by @GatsbyJS
— Paul Scanlon (@PaulieScanlon) December 10, 2020
Whether it's apps i'm building or bums i'm styling Theme UI by @jxnblk it the absolute best! https://t.co/V9UXemdawo pic.twitter.com/Xgsz9r7htC
Not a major update here butā¦ Iāve been playing around with ways to document the components used in BumHub.
For now at least I have a kind of style guide page which lists each component from BumHub and itās props.
Further down the page iāve started to do the same with the components that ship with Theme UI
If you havenāt used Theme UI before iād recommend giving it a go. It is IMO the original and best take yet on CSS-in-Js
not just because it thankfully moves us away from class
namesā¦ and we all know namings things is hard but because
it blows my mind the way Brent Jackson re-imagined style systemsā¦ and the best of all
these new school methods is what I refer to as the [Responsive Array Syntax](https://paulie.dev/posts/2020/08/Styled
Components-responsive-array-syntax/).
With Theme UI you get all this goodness out of the box, in the above blog post I explain how you can achieve a similar thing using styled-components but it does seem like a faff to roll your own when Theme UI gives it up for free.
Iām not sure how popular Theme UI is amongst React Devs, I see a lot of chatter about Tailwind but because I know CSS Iāve never felt it was a good fit for me. Theme UI on the other hand provides just the right amount of opinions and restrictions. Iāve built loads of sites/apps/blogs with Theme IU in the last couple of years and so far iāve not found anything it canāt do.
In any case, youāre free to choose whichever CSS solution youāre most comfortable with but for me iām a 100% Theme UI fan boi!
Thanks Jackson, youāre the best!
Update 7
Dec 14 2020
Update 7 for my #SillySiteChallenge š¤Ŗ
— Paul Scanlon (@PaulieScanlon) December 14, 2020
š Bum Search provides "app like" functionality to search, filter and sort all the Bums, and if you didn't already know...
If #React can do it, @GatsbyJS can do it šŗ
Have a read here šhttps://t.co/V9UXemdawo pic.twitter.com/5L7ZHBMvLz
Bum Search section is done ā
When I first started thinking about an idea for the #SillySiteChallenge I wanted to demonstrate what I would refer to as āapp likeā functionality, purely because I regularly see comments on Twitter suggesting that Gatsby is just for blogs. Iāve never understood this.
From the very start of my love affair with Gatsby Iāve understood Gatsby is React. Iām not sure how this point gets missed, perhaps Gatsby donāt make a strong enough point about it or perhaps thereās not enough examples of applications built with Gatsby.
Iām not sure for the reason but itās my hope by creating the Bum Search page itāll at least go some way to voicing my opinion that Gatsby is React.
The Bum Search section features a fully functioning Search input, with a Select to change which value from the data you want to filter on, along with table column sorting functionality so users can explore the full data set returned by GitHub.
Arguably in BumHub this kind of functionality isnāt all that useful but it does, as mentioned above demonstrate that itās possible to do such things with Gatsby plus it demonstrates my ability to use array methodsā¦ hopefully that second point might allow me to swerve pointless tech tests when applying for future jobs or contracts. šŗ
This latest update pretty much completes my āMVPā but iāve had another idea, itās again grounded in my desire to demonstrate Gatsby is React and can do all the things that a straight up React App can do so stay tuned and iāll be back with another update in a week or so.
Update 8
Dec 21 2020
šØ BRAND NEW FEATURE ALERT šØ
— Paul Scanlon (@PaulieScanlon) December 21, 2020
I've been busy tinkering with my #SillySiteChallenge hosted by @GatsbyJS and am now pleased to present...
Bum Bum Maker
... customise a bum, download, then share šŗ
Link and explanation in the post šhttps://t.co/V9UXemdawo pic.twitter.com/bg1j3bY84M
šØ BRAND NEW FEATURE ALERT šØ
Pleased to present Bum Bum Maker and cooorrr blimey guvānor this was a lot of work!
As I mentioned in Update 7 I wanted to make a bit more of a point regarding what you can do with Gatsby, and the TLDR version isā¦ anything you damn well please. Gatsby is built on top of React so if you can do it with React you can do it with Gatsby.
Bum Bum Maker is an interactive character chooser tool, and it works like this.
I have a React component called
<MakerBum />
which
receives a config array which looks a bit like the below
iāve removed some of the options for brevity FYI
// src/plages/bum-bum-maker.tsx
export const bumBumConfig = [
{
name: 'face',
...
options: [
...
{
label: 'beard',
value: 'beard',
checked: true,
meta: {
type: 'image',
value: '',
},
},
],
},
{
name: 'miscellaneous',
...
options: [
...
{
label: 't-shirt',
value: 'tshirt',
checked: false,
meta: {
type: 'image',
value: '',
},
},
],
},
{
name: 'head',
...
options: [
...
{
label: 'glasses',
value: 'glasses',
checked: false,
meta: {
type: 'image',
value: '',
},
},
],
},
{
name: 'accessories',
...
options: [
...
{
label: 'coffee',
value: 'coffee',
checked: false,
meta: {
type: 'image',
value: '',
},
},
],
},
{
name: 'tone',
...
options: [
...colors.tone
.map((item): string => item.mid)
.map(
(item: string, index: number): IMakerConfigOption => {
return {
label: `${index}`,
value: `${index}`,
checked: index === 3,
meta: {
type: 'swatch',
value: item,
},
}
},
),
],
},
] as IMakerConfigItem[]
Thereās a couple of reasons for this. Firstly and, this is quite common in āapp likeā development, the UI is usually
driven by data, Bum Bum Maker is no different. I have a list of Radio buttons grouped together for each part of the
bum, eg. Head, Face, etc and using a top level name
key means I can leverage normal HTML Radio behavior by grouping
them together thus only allowing one Radio from each part to be selected at any given time.
The individual options themselves accept a label
, value
, and a default value for checked
. Iāve also added a meta
key. This is how I determine if the list items are to have a little graphic of the value or a tone swatch.
The tone hex reference comes from the tone key in Theme UIās color object. The reason for directly referencing the color object in this way means that if I were to add a new tone to the theme the list would automatically display a Radio button for itās given valueā¦ nice ey!
Using a config object like this is great for the Bum Bum Maker page elements but itās a bit verbose to drive the SVG
conditional <g>
renderingā¦ allow me to explain.
By using my old chum
Array.prototype.reduce
and
Array.prototype.filter
I can āloopā over the items in the bumBumConfig
array and reduce the array down so it only contains the names of the
options that have checked: true
// src/components/maker-bum.tsx
const getCheckedProperties = (config: IMakerConfigItem[]) => {
return config.reduce((items, item) => {
items.push(item.options.filter((option) => option.checked).map((option) => option.value)[0]);
return items;
}, []);
};
This results in a new array of strings for each option that is checked eg
// (results array)
['beard', 'noMiscellaneous', 'headphones', 'laptopStickers', '3'];
Then I can use these values to pick a key from a properties dispatch tableā¦
again iāve removed a lot from the below example for brevity
// src/components/maker-bum.tsx
const properties = (property: string, tone: number) => {
const config = {
['beard'] :(
<g>...</g>
)
['headphones'] :(
<g>...</g>
)
['laptopStickers'] :(
<g>...</g>
)
}
return config[property] ? config[property] : null
}
export const MakerBum: FunctionComponent<IMakerBumProps> = ({ config }) => {
return (
<svg
version="1.0"
x="0px"
y="0px"
viewBox="0 0 550 410"
width="100%"
height="100%"
>
{getCheckedProperties(config).map(property => properties(property, tone))}
</svg>
)
}
For the values contained within the new array I return the SVG <g>
element(s) and for values that arenāt I return
null
. This allows me to conditionally render all SVG <g>
elements that together form the SVG you see in browser.
If you open up your developer tools and find the SVG element, then click around on the Radio buttons youāll see the SVG
re-renders itās child <g>
elements according to the checked values provided by the Radio buttons. I typically use this
approach in my day job to build complex web applications for companies that make bazillions that no one cares about but
here iām using the same approach to conditionally render an SVG Bum graphic which really puts the fun into Functional
Programming.
The fruits of this labour intensive task result in a fun UI with an added treat for the user allowing them to download their custom bum graphic as a bitmap in 16:9 aspect ratio, perfect for sharing on Twitter.
This feature was a bit of a last minute idea but iām pretty pleased with the outcome. Itās purely luck that all the separate parts of the illustrations work together in any given order as this wasnāt part of my original brief to Miss_ChatZ
Having reviewed the Pre-submission checklist iāve also been working on accessibility and performance and one thing I noticed on the home page was a warning about maximum DOM depth, this was due to the amount of Pants Up / Pants Down bums iām rendering for the advent calendar. A relatively quick fix for this was to limit the amount of Advent Cards to render on initial page load.
Iāve achieved this by utilizing
Array.prototype.slice.
Hereās the code but in short depending on
if the state value isAdventExpanded
is true
or false
I either render the full array or slice the array from -2
indexes from the current day + 2 indexes which gives me a day before the current day and 2 days after the current day or
simply just x4 Advent Cards. This has improved the lighthouse scores too.
An added bonus to this fix is that the UX has slightly improved because the user now doesnāt need to scroll quite so far to see the other sections in the page, Bum Search, Bum UI etc.
I also popped a little useLocalStorage hook in for the isAdventExpanded
value. This is so the page remembers if you were or werenāt in the expanded state when you navigate to and from the
index page.
Iām not sure thereās anything left to do now so dare I say itā¦ but, I think iām done! šŗ
Update 9
Dec 23 2020
A small update to my #SillySiteChallenge project but...
— Paul Scanlon (@PaulieScanlon) December 23, 2020
A big shout out to all my internet friends š¤@spences10 @studio_hungry @raae @FabioRosado_ @nohinder https://t.co/V9UXemdawo
Today iāve pushed a couple of small changes. BumHub now has a footer section outlining roles and responsibilities on the project along with a shout out to my internet friends.
Because I use Theme UI this kind of UI work literally takes seconds. Itās actually more work to
create a git branch and a PR than it is to create two new sectionsā¦ well a <section />
and a <footer />
if weāre
to be semantically correct.
ā¦ and I canāt think of anything to say about todays update.