Building GatsbyConf 2022

Hello! Paul here and I’ve been given a new assignment!

I’ve been tasked with building the new GatsbyConf 2022 site – yikes!

It’s quite daunting, but I love it! Over the coming weeks / months I’ll be updating this blog post with my progress. I’ll be openly discussing my trials and tribulations, failures and successes… because, why not hey, we all have to face and overcome problems and I’m no different.

I’ll also be calling out folks who I’ve collaborated with internally and externally to make this site happen. There’s Power in Numbers! Keep an eye out for those Collaborator Counts on each update.

If you’d like to check up on me and see where I’m at as March 2nd & 3rd draw ever closer, bookmark this post.



Tuesday 11th January

I’ve been off-piste but I’m now back! 

Last week and a bit of this week, I’ve been focused on writing a new blog post: Performance Optimization for three.js Web Animations. I touched on the subject in my update below on Tuesday 4th January and it relates to some performance improvements we made to the three.js hero animation seen at the top of the GatsbyConf site. The post goes into a little more detail about how we addressed our particular concerns plus a little more information about how to use React.lazy / Suspense, along with some areas for consideration before adding JavaScript animation libraries to your project. 

Today’s morning task has been syncing with Molly, Flo and Laci regarding brand, illustrations and design.

Whilst the site is looking great it was only ever intended to be the MVP version so we could launch before the New Year. Now with the Design team back in the game we’ll be giving the site a little more love… but, heart on my sleeve time… I’m worried that during the meeting I may have played the role of Grim Reaper 😬 – But I have my reasons.

Allow me to explain.

At the moment, each site section is pretty much the same. The hero section and the form section are unique but all the middle sections use the same familiar content model. When Laci and I were creating the content model this was quite a deliberate move for two main reasons: 

  1. There’s a balance between giving Laci some configuration options, and giving Laci too many configuration options resulting in a somewhat cumbersome editing experience. 
  2. I will at some point be writing about content models and I’m keen to explore how much we can achieve in GatsbyConf with a pretty simple content model. 

To give you some more context. We need to create a set of “design presets” that will work for multiple sections but that can be configured easily to produce variations, so I’m specifically looking for repeatable patterns E.g.

  • Each section will have a heading
  • Each section will have a sub-heading
  • Each section will have an optional rich-text body 
  • Each section will have an optional image
  • Each section will have an optional “References many type”: E.g an Array of “Sponsor Logo”, or an Array of “Speaker Headshot”
  • Each section will have a column count option
  • Each section will have a text alignment option

When you read these back they start to feel like Acceptance Criteria — that’s because they are. This is typically how an engineering task is started but it’s not quite the same for design.

I’m mindful that whilst I’m keen to stick with repeatable patterns and a simple content model, I don’t want to be so strict that the overall site design suffers. I think I articulated my concerns clearly in the meeting and I do think Design appreciates where I’m coming from, so let’s see what happens next. 

Today’s afternoon / evening task has been to investigate what I’m currently calling “Hybrid Svg’s”. I also mentioned this on Tuesday 4th January and I don’t know if that is an official term but I’ll be explaining my approach in more detail in a separate blog post. 

The TLDR if you like is: I need to find a way to reduce the complexity of our “number people” illustrations. I could, of course, use gatsby-plugin-image and display the illustrations as bitmaps. But because I want to animate some of the elements around the illustrations, the cloud, the code icon, the little planet etc. they need to remain separate elements (rather than a flattened / merged bitmap). The trouble is, when they’re separate elements any one of the number illustrations in an Svg format can exceed 1000 lines of code – Wowsers!

This is picked up in the Lighthouse report and I’m seeing the warning for: Avoid an excessive DOM size.

My current plan of attack is to adopt a kind of hybrid  Svg / Bitmap approach where I’ll separate the surrounding elements that I do want to animate, and keep those as Svg’s. Then render the main body as a Bitmap because I won’t be to animating this. 

GatsbyConf Hybrid Svgs

The reason I’d like to keep the surrounding elements as Svg’s is because I want to randomise the colours; this should be as straightforward as randomly selecting a class name that will apply a different CSS fill colour. If I were to convert these surrounding elements to bitmap this wouldn’t be possible.

My initial test has proved pretty successful and I’ve managed to reduce one of the Svg’s from 1000 lines of code down to 500, so that’s a 50% improvement! – Brills!

Stay tuned for more on this as it’s a pretty interesting area and I’ll be sure to document my findings for whatever solution I come up with. 

Thursday 6th January

I’m taking a small breather from the site development today — but I’m not slacking, no way!

I want to write down all my finding from the three.js performance enhancements I made with Ward while they’re still fresh in my head, then write a blog post about Performance and JavaScript Animation Libraries (working title)

I Tweeted this morning and looped in another Gatsbyte, Grayson Hicks (Staff Software Engineer). Grayson works on the Customer Success Squad and you’ve probably seen him on a number of performance related Gatsby webinars, one of which is coming up on January 13th: Achieving Peak Frontend Performance with Gatsby, so if you’re interested in this topic i’d recommend tuning in for that!

I hope to have Grayson review my blog post and hopefully chip in with some of his expertise.

The main issue I’m having with the post at the moment is whilst the solution worked well for us on the GatsbyConf site, the more I think about JavaScript animation the more I think, actually, “lazy-loading” might not be a good solution for so many other scenarios… and what about the negative impacts, would SEO suffer? — probably!

Perhaps I’ll focus on the problems we faced, how we solved them and provide some further reading as this is quite a deep topic and I rather fear I could spend several weeks writing about it.

Collaboration Count: x9
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann
  • Miss Chatz
  • Alex Reed
  • Ward Peeters
  • Flo Kissling
  • Grayson Hicks

Wednesday 5th January

Today was… Flo day! 🥳. Flo Kissling is Gatsby’s Lead Product Designer and he’s back from his Christmas time off and he’s absolutely brills!

Previously I’d only briefly crossed paths with Flo when I was contracting for Gatsby working on 500 Bottles. Flo was on hand to give me a steer on my design work for both the site and the logo… but joy of joys for GatsbyConf, Flo will be over-seeing the branding and design work — phew! I know when I’ve hit my capable limits.

We had a great meeting with Molly this morning and discussed the illustrations, general art direction, how the content model in Contentful worked, what we need for social media, ads, and other supporting visual assets and discussed some exciting new features I hope to build out in the coming weeks!

Flo has tons of experience and knows the Gatsby brand much better than I do. I’m thrilled he’s on board with the project so stay tuned while we tighten things up!

Collaboration Count: x8
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann
  • Miss Chatz
  • Alex Reed
  • Ward Peeters
  • Flo Kissling

Tuesday 4th January

I started the day pondering a technique I’m currently calling “hybrid svgs”… allow me to explain. On the current GatsbyConf site we’re using the “number people” illustrations created by Miss Chatz. They’re super duper and I love them and for now I’ve created a React component for each Svg, but, in Lighthouse I see the warning: “Avoid an excessive DOM size“.

This happens because each of those Svgs contains many <g /> and <path /> elements, along with a number of <def /> and <linearGradient /> elements. One of the Svg’s is actually over 1000 lines deep. — Blast!

I’ve encountered this issue before and was able to overcome it by using the Path finder tool in Illustrator, this is quite a destructive process because when elements are merged together it’s harder to do anything other than display them. For the illustrations on GatsbyConf I plan to animate them, I’m not sure how yet but I know I will need to keep some of the elements layered.

My current thoughts on this are, I’ll go for a “hybrid approach”. The main body of the illustration, the actual number could in theory be a bitmap E.g a .png and only the elements that surrounding the number need to remain as <g /> or </path /> elements. However, trying to use position: absolute on these elements so I can animate them and keep them relative to the size of the bitmap body, which by default will scale when you change the size of your browser, is going to be tricky!

I’m wondering if I create a Data URI for the body of the number (the bitmap) and then using xlink:href on an <Svg/> <image /> element, would everything scale proportionally?

If this works it’ll mean I can drastically reduce the complexity of the Svg, which should mean the “excessive DOM size” warning goes away but I’ll still be able to keep some level of control over the elements, and animate them — Hooray!

I’ll need a little more time to experiment with this technique but if it works I’ll be sure to write something up as it would be really helpful in future when working with Svg’s.

The actual task for today was improving performance of the three.js stars animation, seen in the hero section at the top of the site.

The Problem: The problem with including three.js / @react-three-fiber is that the extra weight of these libraries causes an increase in “Total Blocking Time” as seen in the Lighthouse report. The way to resolves this is to use React.lazy and <Suspense />. This technique involves using React to delay the loading of additional JavaScript modules until after the initial JavaScript modules have loaded. However, whilst the technical implementation is pretty solid there are one or two things to consider before using this approach.

In our case on GatsbyConf, and whilst we love the star animation (we hope you do too) it’s irrelevant.

It serves no purpose other than to look “cool” — which I’m 100% ok with FYI. But, because we’re now lazy loading this component it’ll take slightly longer to appear on screen. This isn’t really problem because users aren’t missing out on any crucial information, and there’s no SEO implications since there’s nothing in the three.js scene other than graphics, and lastly it’s an HTML <canvas /> element which can’t be optimised for SEO anyway…

But, if you were using some other JavaScript animation library E.g GSAP and were wishing to animate existing HTML DOM elements would lazy loading work for you? This might mean your page loads, your DOM elements aren’t where they should be and then a few seconds later when the JavaScript loads, the page might jump around while the animation library did its thing. I suppose this might not be an issue and it entirely depends on what you’re doing with the animation library but it’s something to consider.

There’s another issue. Ward was keen to keep this site as performant as possible so along with lazy loading three.js / @react-three-fiber we also have an additional condition worked in that only attempts the lazy load if a users browser is wider than 768px, and if window.navigator.connection.saveData = false.

TLDR: Our stars animation will be lazy loaded and only loaded if we think the user is on a wifi connection on a screen larger than 768px. We feel this solution works for us because as I mentioned, the animation is incidental and serves no other purpose than looking “cool”. Your requirements will most likely be different.

The Solution: The below code snippet shows how we’re using React.lazy / <Suspense /> to lazy load the <ThreeCanvas /> component, and the useEffect is there to ensure this only runs in the browser, not on the server. (because navigator is a window object, and there’s no window on the server).

You can find some more information about this approach in the Gatsby docs: Using Client-Side Only Packages

I plan to write this up with a demo and src code at some point as I think it’s a really interesting topic. Give myself: @PaulieScanlon or @GatsbysJs a follow and we’ll Tweet something soon.

Collaboration Count: x7
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann
  • Miss Chatz
  • Alex Reed
  • Ward Peeters

Monday 3rd January

Right ho! Back to work. Today was a good day. I was mainly focussed on the hero animation. I’ve been thinking about this for a few weeks now and wanted to create some kind of data driven animation. Not data visualisation (to be clear) but I wanted to use the total number of folks registered for GatsbyConf to drive some kind of visual element.

I’ve done this kind of thing before on 500 Bottles where I used the Shopify inventory levels to create the flying shapes seen at the top of the site. For 500 Bottles I used three.js / @react-three-fiber — @react-three-fiber is great, it’s such a nice way to use three.js in React but does it come at a cost?

Ultimately, yes. Using three.js and @react-three-fiber in your project will increase the overall JavaScript bundle size. You can see the bundles sizes for here package on the below links.


Naturally, at Gatsby we’re always keen to keep sites as fast as possible and provide ways to help you optimise your build, but if you add additional JavaScript your site might suffer a little.

I’ve had multiple conversations with Ward about this and actually a lot of the work I’ll be doing over the coming days will most likely be performance related, but… sometimes adding something because it’s cool is ok, in my opinion, and especially if you have an opportunity to show people how it’s done and how things are affected.

It goes without saying that I don’t want folks to have a bad experience just because of my want to do “cool” things but I think there is a fair middle ground. I’ll continue to work with Ward on this and in the mean time here’s how it works.

Create the 3D canvas

First, I add the Canvas from @react-three-fiber and set some config, plus the camera position. Then, added as children are a number of lights and the <ThreeStars /> component which I’ll explain in a moment.


<ThreeStars />

This looks slightly more complicated than it is, but I’ll talk you through it…

Fetch The Data

Using a React useEffect I make a call to a Gatsby Serverless Function endpoint when the component “mounts”. This endpoint returns ONLY the rowCountand NOT any details about you lovely folks. This request is handled server-side for exactly that reason — it’s secure.

Add and position each star

Weirdly, I wrote this code in my head over Christmas. I was assuming that once I had an “amount” I could create a null array, map over it and return a three.js geometry and then position it randomly within the 3D scene using good old mathematics … and as luck would have it that’s exactly what I did, and it worked first time — which never usually happens!

Rotate the Scene

Since each star is added to the same <mesh /> I wondered what would happen if i rotated the entire thing… 2 for 2! That also worked first time.

Using  useFrame from @react-three-fiber, I increment the x and y rotation properties by 0.001

Theres a few other things in the snippet below, mainly to handle loading state and to ensure the useFrame doesn’t run until the <mesh /> has been returned by Jsx.

Creating The Geometry

This is, more or less how you’d create any geometry with @react-three-fiber. I’m using <sphereGeometry /> which accepts x3 arguments. You can see what they are from the three.js docs. The x,y,x passed via props from the parent component are passed on to the <mesh /> and used in the position arguments.

… And that’s it. That’s how the star field was made.

Collaboration Count: x7
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann
  • Miss Chatz
  • Alex Reed
  • Ward Peeters

Thursday 30th December

Today was actually go live day! Yesterdays DNS issues were still slightly tripping us up. We did manage to launch with but was proving to be problematic. In Gatsby Cloud we had the primary domain set as the naked url and the www url should resolve to the naked url by default, however because of some weird Google Domains DNS config this wasn’t the case. The solution in our case was to add an additional CNAME record to Google Domains that included the www — and hooray! We’re live once more!

There was more todo though. For the Open-graph image, Laci had accessibility concerns that the 2022 number illustrations were a little too dark and hard to read when they’re small against the dark background. This colour contrast isn’t so much of a problem when you visit the site as the numbers are large but on a social media sharing card they are quite small. Miss Chatz (luckily) was on hand to quickly create some “light mode” versions of the numbers and these are what’ve used in the Open-graph image.

The biggest issue I discovered though (and why does this always happen right before you’re going live?!) was React rehydration. You may or may not have run into this before but this can happen if you’re “setting state” in uncommon ways as React can become a little confused when it comes to return you DOM elements.

In my case it resulted in some very peculiar layouts. The solution was to change the useLocalStorage hook and Ward (Core team TeamLead)  was on hand to help me work this out. I wrote a blog post about it which you can read here:

Once that was resolved everything was glorious, Laci tweeted and shared the new site on the Gatsby social media accounts then we watched the registrants roll in!

Lovely stuff!

Collaboration Count: x7
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann
  • Miss Chatz
  • Alex Reed
  • Ward Peeters

Wednesday 29th December

Today was “go live” day and it’s been stressful! I first had a few issue to resolve with Svg heights on mobile not working. I think it’s something to do with when an Svg has an height of 100%… in any case adding a max-width and max-height as well as a width and height of 100% resolved the problem.

Next up was DNS. There has always been a site on and this site did exist in Gatsby Cloud somewhere, but unfortunately I didn’t have access to the Workspace where it had been configured. Alex (Senior Software Engineer) found it in a different Cloud Workspace and removed the domain so it was free to be assigned to the new GatsbyConf ’22 site. We still had issues with Google domains, though, and needed to configure A records and CNAME entries then decide if we want the “naked” url or the prefixed “www” url to be the primary….as I write this we’re still to resolve the DNS config.

Finally there was one last job. There’s a number of links to the former GatsbyConf ’22 landing page around and none of them were pointing to url so we’ve created a PR to handle redirects. Now when you visit any of the old links to the GatsbyConf temporary landing page you should be directed to the .com domain — phew.

But I’m pleased to say that we are live and we did meet the deadline. Just gotta wait for the DNS changes to propagate over night before we officially announce on social media.


Collaboration Count: x6
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann
  • Miss Chatz
  • Alex Reed

Tuesday 28th December

What a splendidly visual day I’ve had. I started with an issue we were having with the sponsor logos. Whilst Content Management Systems are great and Gatsby’s image plugin is fantastic there are times where human invention is required.

The problem was that the sponsor logos are all different from one another, namely their aspect ratio’s. Sone are square, whilst most are rectangular and no matter what I did with CSS they never really felt like they were of equal proportions… so I kicked it old school, opened up Adobe Illustrator and begun a process I refer to as “normalising”. This involves looking at all the logos side by side, changing their scales, and matching sizes up using my eyes. As luck would have it, good old fashioned design skills saved the day and after normalising and re-uploading all the sponsor logos they now feel equal.


The really exciting thing I did today was to implement the first two of our number illustrations from the brills Miss Chatz. I’ve worked with Miss Chatz before so knew I’d be getting top notch work — and she did not disappoint.

The tricky thing however, and maybe you know and maybe you don’t is rejigging Svg’s so they work in React. “Why not just inline and import?” I hear you ask. Good question. I plan to animate parts of each of the number illustrations so they need to be React components rather than “image” files (Svg’s are documents not images FYI). And if you’ve ever imported Svg markup into React you’ll immediately run into Jsx syntax issues. — but — Svgr to the rescue! This tool sorts out all those Svg attributes that throw errors when returned by Jsx.

To give you an example, this is valid markup xlink:href, but in order for this to work in Jsx it has to be xlinkHref — Changing each reference by hand would have been hugely time consuming so I’m super happy I found Svgr!

There are some other issues I spotted with the Svg’s. It looks like Miss Chatz has used some blend modes that work fine in Illustrator but perhaps don’t work as expected when the Svg is displayed in the browser. More on that when I work out what’s going on.

Here’s a sneak peek at what the hero section of the site looks like. Hopefully I’ll be able to fix up this blend mode problem before we go live!

Collaboration Count: x5
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann
  • Miss Chatz
Illustrations sneek peek

Monday 27th December

Right! Back to it, Christmas is over and this site isn’t gonna build itself. Some of today was looking over what I did last week and the rest of the day was updating quite a lot of the styles to match some new designs Molly (Product Design Manager) prepared for us.

For the most part the new styles were colours and layouts but some of the design changes require content model changes — which is fine. Or is it.

Sadly, it’s not. The way the Contentful Source plugin works means that GraphQL will error if it attempts to query a field that is either no longer there or if the field name or type have changed. I had a few scenarios where instead of using simple text fields we’re going to need to use Contentful’s Rich Text editor, this change requires the GraphQL query to change, and then later on in the Jsx I need to deal with the response of the query in a slightly different way.

Laci and I also caught up on what we’re planning to go live with on launch day and I need to have a bit more of a think about how to handle folks that have already signed up via the former GatsbyConf landing page and don’t yet have a raffle code.

I also need to make another change to the content model so that the sponsors logos can also act as links.

Not a bad day and I’m still making progress!

Collaboration Count: x4
  • Paul Scanlon
  • Laci Texter
  • Molly Misek
  • Aron Schuhmann

Monday 20th December

I did not have a good day today.

Todays’ task was to implement the registration from for the event. In the old landing page and for a number of forms used around we’ve been using Marketo. I think for a lot or reasons Marketo is a great solution, however in my case, and perhaps I’m alone in this way of thinking, it doesn’t feel very Jamstack.

To use a Marketo form you need to add a script tag to your site, then once the JavaScript has loaded it finds the a <form /> element by id and injects all the inputs and labels into the DOM.

It also has a rather unique way of dealing with the callback (E.g when the form has successfully submitted)… and I need to tap into this event because once a user is registered I need to create the raffle code and post the same data into my “raffle code” Google Spreadsheet.

This was all becoming too much so I’ve pulled out the Marketo form and will post to a custom endpoint, which Aron (Director of Growth) can use to pull the data back into Marketo.

Alls well that ends well but it was a frustrating day.

Collaboration Count: x3
  • Paul Scanlon
  • Laci Texter
  • Aron Schuhmann

Sunday 19th December

Yep, working on a weekend. Not because I have to but because I want to. Late on Friday Laci and I “did good Marketing” — We came up with a really nice idea to add a little extra bit of fun to the registration process.

We’re having a raffle! Now when you sign up you’ll be given a unique raffle code. I generate this using a Gatsby Serverless Function that randomly picks a few letters from the alphabet and tacks on the date and current time in milliseconds.

I then post this code plus the users details to a Google Spreadsheet for safe keeping. The site also now persists the state of the form. Once you’ve registered so you won’t be shown the form again, but it will show you your raffle code (in case you lose it) I achieved this using a useLocalStorage hook.

During the event, we’ll call out raffle codes which will be selected at random and ask folks to come find me on our event platform, Hubilo. I’ll then check the code against their email address to ensure there’s no cheating, and, et voilà we’ll have winners!

Prizes for the raffle are still being worked out but we’d like to offer products or vouchers from e-commerce venders who’ve built their site with Gatsby — pretty cool ay!

We’ve also started the commissioning process and sent a few emails out to illustrators whose work we liked. The full scope of the illustration brief is still a work-in-progress but it’ll be something to do with the GatsbyConf 2022 theme, “Power in Numbers”, and at some point I plan to add these custom illustrations to various sections of the site.

Collaboration Count: x2
  • Paul Scanlon
  • Laci Texter

Friday 17th December

Today was “Tailwind” day so I’ve been busy working through the sections and rejigging some of the content model to ensure that that all sections besides the hero follow the same content model. These sections do have different subsections but I’d really like to keep the “one off” rules to a minimum. I’m not a fan of having lots of little _conditions_ all around the code base. It’s kind of ok while you’re actively developing but when I came back to this in weeks to come or if someone jumps on board to help me out I don’t want to have to explain lots of little rules.

“One size fits all” is actually a really tricky thing to do, but with a bit of planning and keeping Laci in the loop, I’m sure we’ll agree on something that can work across all of the sections.

Collaboration Count: x2
  • Paul Scanlon
  • Laci Texter

Thursday 16th December

Today was “Content Model” day. Myself and Laci (Senior Brand Marketing Manager) went through each section required for the site and created an appropriate content model. We have x2 pages, “/” and “404” and each page can render a few types of “Page Blocks”.

Page Blocks

Starting at the beginning we have a Hero block which contains the following field types:

  • Logo – Media
  • Event Name – Short Text
  • Title – Short Text
  • Title Suffix – Rich Text
  • Button Text – Short Text
  • Button Hash – Short Text
  • Start Date – Date & Time
  • End Date – Date & Time

Next is a kind of generic Section block  which contains the following field types:

  • HideMe – Boolean
  • Section Name – Short Text
  • Section Image Top – Media
  • Section Body – Rich Text
  • Section Image Bottom – Media
  • Section Background Color – Short Text
  • Sponsors – References, many
  • Speakers – References, many
  • Gatsby Agency Awards – References, many

This generic Section should in theory be enough to drive each and all of the sections of the site. I really like using the References field type because it allows you define a type of field that contains other types of fields, it’s all a bit meta but totally flexible, each of those sub fields can then be constructed using a selection of generic field types such as Short Text, or Media.

Page Block Arrangement

Here’s a sneak peek at what the index page Page Block arrangement looks like. I like this approach as it clearly shows how the page will be displayed and in what order each Section will be shown.

Moreover, if Laci wants to rearrange the order, it’s no trouble since Contentful allows you to drag and drop these Page blocks and so long as I do my bit correctly on the code side, the order should be respected when the content pops out the other side.

Today was a big day but I’m pleased with the progress we made and now we have a Content Model in place I can begin to work on the code. This next part is all me so Laci can continue to work on the actual content and with a bit of luck when we reconvene next week we should be in a really good place.


Collaboration Count: x2
  • Paul Scanlon
  • Laci Texter
GatsbyConf - Content Model

Wednesday 15th December

I’m currently returning to the working world after being struck down with a spot of the old “man flu” — awful business and it knocked me out for three days. I have, however, just about mustered up the energy to complete my initial commit for the new GatsbyConf site.

Typically on my initial commit, I’ll get all the “knowns” installed and working. For this site that includes all my tooling, husky and commitlint and of course prettier. Then I popped in my old chum TailwindCSS, made a default index page and a temporary 404 page and that’s pretty much me good to go now.

I’ve deployed to Gatsby Cloud right away as I’ll need to share the WIP link with my “client” (Laci from the Marketing team) — no doubt she’ll also be keen to keep an eye on what I’m up to. But just at the moment sadly, I won’t be sharing the link with you lovely folks.


Collaboration Count: x1
  • Paul Scanlon