Explore My Notes

Let a website be a worry stone | Ethan Marcotte

While things were changing, I kept working. After a few weeks tinkering with this redesign, I realized I wasnโ€™t working on a website, not really: it was a worry stone.

There's a lot to love in Ethan's thoughts. I saw his tweet weeks ago but found myself returning to it time and time again in my mind, what with, well, everything right now. It's great to see that expanded into a full piece (I actually don't know which came first). Plus, obviously, I can relate. So excuse me; I think there's something about "reviews" that needs working on ๐Ÿ˜‰ After all:

Thatโ€™s not to say any of these things are done, mind you. But theyโ€™re done until I come back to them: until I find something else to revisit, to sand down, to turn over and over and over.

Oh, embed! | adactio

YouTube embeds can be expensive on page load metrics, but what alternative is there? How about loading a thumbnail that hot-swaps itself for an <iframe> when clicked? Sounds great, but wouldn't that mean you have to create custom thumbnails for each video?ย Nope, YouTube has a bunch of weird and wonderful hidden features in its API that will give you everything you need:

  1. Get the URL of the video you want to upload;
  2. Ping the oEmbed endpoint like so: https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=-eiqhVmSPcs
  3. Pull out the thumbnail URL from the returned JSON (quick tip: you can actually skip the first two steps and just use the ID for this instead)
  4. Add it to some markup:
<a class="videoimglink" href="'.$url.'">
    <img width="100%" loading="lazy"
        src="https://i.ytimg.com/vi/'.$id.'/default.jpg"
        alt="'.$response['title'].'"
        srcset="
            https://i.ytimg.com/vi/'.$id.'/mqdefault.jpg 320w,
            https://i.ytimg.com/vi/'.$id.'/hqdefault.jpg 480w,
            https://i.ytimg.com/vi/'.$id.'/maxresdefault.jpg 1280w
    ">
</a>
  1. Add an onClick event to swap it out with an iframe (tip: use the youtube-nocookie URL for increased user privacy)

Done. Responsive, progressively enhanced, and much more performant. Great tip ๐Ÿ‘

A guide to getting onto the IndieWeb | IndieWebify.Me

IndieWebify.Me is the main service I've been using to get my site set up with IndieWeb technologies. It's a great, step-by-step tutorial on how to get involved and helps you easily test your implementation. I've still got a bit Iย need to do but it would have taken a lot longer without this resource.

๐Ÿ“† 14 May 2020  |  ๐Ÿ”—

  • Frontend, 
  • IndieWebify.Me, 
  • indie web, 
  • authentication, 
  • IndieAuth, 
  • tutorial 

The random link in the age of static sites | Heydon Works

Heydon has been working on Ga11ery, a neat image portfolio site generator that's ideal for webcomics. But it's built on the Jamstack using 11ty and Netlify, which means it isn't so simple to implement a "random image" button. However, because static site generators start with a collection/array of elements to make into pages during build time, you can use the array's index to effectively mock previous/next pages (something I'd like to do here, actually).

Introduce a little bit of Math.random and you have a decent random link, but it's still generated at build time, so every user gets the same random pathway (and you can get loops). Heydon uses some client-side JS to install a second level of randomisation to get around that. It's a clever little trick and, as he says, is likely more performant than the traditional PHP/API query method:

Build-rendered beats server-rendered beats client-rendered.

Accessible emoji tweaked | Adrian Roselli

A neat little extrapolation of the normal a11y approach to emojis which adds tooltip behaviours using the aria-label attribute. Particularly useful for those emoji which aren't fully compatible with all devices, an issue which is then neatly highlighted with some screenshots of Tim Cook trying to use the Apple-only emoji on Twitter ๐Ÿคฆโ€โ™‚๏ธ

Till the cows come home | Getaway

When I rewilding farming schemes I don't think of the Karoo. The Landmark Foundation are trying to get that to change. The idea is simple enough: the Karoo grassland has evolved to persist around giant migrations of springbok and other ruminants, as well as droughts and fires. So if you replicate that kind of shock grazing with long recovery periods, you play into the evolutionary tactics of the plants themselves. By combining farms, removing fences, and using more traditional shepherding, semi-nomadic techniques, they've been able to go four years without having to buy feed. Even though those four years include the worst drought in history for the region; that's huge!

Not only does the use of herding mimic the pattern of wild grazing, the overnight kraals used as the herd is moved around actually help break up the soil and spread seeds. You can actually see green patches where kraals were located in the past, and these act as reseeding islands that slowly spread out, counteracting overgrazing that is normal in fenced farms.

There's also a huge amount of really interesting facts in this article:

  • Despite the widespread use of gin traps, 10% of sheep in the Karoo are lost annually to predators. With shepherds, the farms have eliminated predation loss;
  • South Africa is the second-most fenced area of land on the planet after Texas, as a result of historic grants that aimed to reduce farm labour (why?);
  • It's cost-neutral to remove fences as the materials can be resold for more than the cost of labour to remove them;
  • A claim is made that the use of planned grazing (which is what they're doing here, that allows grassland to recover between grazing sessions) improves CO2 and water capture in the soil enough that, if it were used on half the world's arable grassland, we could sequester sufficient carbon to reach pre-industrial levels, even if you tripled the animal stock.ย Not sure I believe that but it's a fascinating idea.

How to add Netlify redirects to Gatsby | Konstantin Mรผnster

On the surface, Netlify has very simply redirect functionality. In principle, I tripped up twice trying to set it up ๐Ÿ˜… Konstantin helped set me right: I needed to move the _redirects file to the static folder and also implement the gatsby-plugin-netlify dependency. Plus, he points out that you can also use Gatsby's inbuilt createRedirect function, which could be useful in the future.

Mailbrew email digests (affiliate link) | Mailbrew

Disclaimer: The title link is an affiliate link, which means I get credit if you use it to sign up. Not really why I made this post, but figured why not ๐Ÿคทโ€โ™‚๏ธ

Mailbrew is a service I've been meaning to check out for a while. Because it's a paid service (no free tier) I'm not sure it's something I would invest inย right now, but I like the idea so Iย wanted to try it out. Initial thoughts are that it's simple to use and has some really neat design ideas, butย dear lord I wish it allowed bulk editing. I just spent 30 minutes inputting about 20 Twitter feeds to one "brew"ย (their name for an email) because I had to manually edit each one to set it to be "two columns; two tweets". If I could have just saved that template it would have been perfect.

As it is, the system was still very easy to search for accounts on Twitter, find them, and add them to my own little feed. I also through in an RSS to see how that worked and it was just as simple. I've created a brew that contains all the frontend sources I like, but don't want to commit to subscribing too. That's a lot of people on Twitter, as well as huge feeds like CSSย Tricks. I used to use Twitter's own suggested/curated feeds feature to keep up with most of these people, but since they destroyed that system and replaced it with one which is overloaded with spam and meaningless nonsense, I've been wanting something to fill the void. Right now I'll get the feed weekly, but it's the kind of thing which could be handy to check daily. If I like it I may even look into spinning up something similar, just for my own use, as email is a fine-enough delivery method but it's not really my preference. We'll see. For now, I've made the brew public: frontend twitterings.

Update 09/06/20: Having used Mailbrew for the allotted trial period, I've just let it lapse. As a result, I don't think the affiliate link is really worthwhile so I've removed the coded part and just left the homepage URL. I liked the service, but ultimately I found it didn't fit in my routine. I don't actuallyย like newsletters; I prefer content feeds. So I never moved anything from RSS there, it was basically just Twitter accounts that I like but don't want to follow. Unfortunately, what I've discovered is that people's most popular tweets are rarely their best. They tend to be humorous or controversial. Neither is particularly useful. What's more, getting the brew daily was way too much; I don't even check my emails once a day, so it would just build up. Once a week was manageable, but made it feel like a chore (even if I invariably enjoyed reading it when I got around to it). I don't need to pay for a service that gives me chores. So yeah, a decent service but not for me.

The landscapes of South England | Ross Hoddinott

Whilst archiving an old copy ofย Digital Photographer I came across a profile of North Devon photographer Ross Hoddinott. His work stood out as just exceptional landscapes from areas I love and he's clearly still going strong. Here are some of my favourites (click to see the high-res originals on Ross' site):

Wooden groyne looking out to sea with a metal rod at the end, very symettrical and moody.
View out to sea along a groyne at Swanage Bay. I love the moodiness, contrast, and symmetry here.
Looking over the sea to an island with a castle on top, colourful skies, and calm waters.
St Michael's Mount is a personal favourite location but this adds a real sense of place and fantasy to it.
A small waterfall in a mountain stream with stone cross leaning to one side in the background at sunset.
The Windy Post in Dartmoor is a great location and whilst the image is a bit over-processed for me the framing is spot on.
A small clump of reeds is silhouetted against a misty lake and sunrise with beautiful but cold colours and the hint of a shoreline in the distance.
There's no denying how lovely this view of Lower Tamar Lake in Cornwall is, though it was actually a different but similar photo I was trying to find from the magazine. Still, this captures the colours and stillness so well!
Two adorable harvest mice sitting on an ear of corn bending under their weight, tails wrapping around the stalk, as one sniffs the air.
So. Damn. Adorable ๐Ÿ˜๐Ÿญ Harvest mice are very photogenic, but there's something even more captivating than usual here, so perfectly focused.

๐Ÿ“† 10 May 2020  |  ๐Ÿ”—

  • People & Places, 
  • Natural World, 
  • harvest mouse, 
  • groyne, 
  • sea, 
  • ocean, 
  • long exposure, 
  • atmosphere, 
  • sunrise, 
  • sunset, 
  • symettry, 
  • contrast, 
  • St Michael's Mount, 
  • Cornwall, 
  • Devon, 
  • Dartmoor, 
  • waterfall, 
  • castle, 
  • lake, 
  • silhouette, 
  • inspiration, 
  • Swanage Bay, 
  • wildlife, 
  • Britain, 
  • Lower Tamar Lake 

Jamstack full course | freeCodeCamp

A solid introduction to the Jamstack, including full build tutorials for an initial SSG setup with Eleventy and Netlify, integrations with the News API service and Open Weather, geolocation checks and content localisation, Netlify functions for API requests, and even some mention of SSL on localhost.

๐Ÿ“† 04 May 2020  |  ๐Ÿ”—

  • Frontend, 
  • JavaScript, 
  • Jamstack, 
  • Netlify, 
  • Netlify functions, 
  • serverless, 
  • lambda, 
  • tutorial, 
  • Open Weather API, 
  • Eleventy, 
  • SSG, 
  • progressive enhancement, 
  • localisation 

Storage for the web | Peter LePage

A detailed overview of the various methods available to locally store website or web app data.ย Overall, the recommendation is:

  • For critical resources (images, content, scripts etc.) use a service worker, specifically the Cache Storage API;
  • For all other data, use IndexedDB (though adding an additional service which allows you to use that API with promises can also be very beneficial).

These processes have wide browser support, are well maintained, and have a low user impact. They're also better at persisting. For example, SessionStorage is locked to that browser tab, LocalStorage is now quite outdated and actively blocks the main thread, and cookies are constantly refreshed so bloat your HTTP request size. Other APIs are either deprecated (WebSQL, Application Cache), lack widespread support (File System API), or require explicit user permission (bad UX โ€“ Native File System API) so should be avoided.

You can use the StorageManager API to check how much space you're using and set limits, but most modern browsers now allow such large limits it should never be an issue (the article has an explicit example of how to use that API as well as what to do if you run up against storage quotas).

It can be worth explicitly setting your data to be considered persistent storage so that browsers don't delete it when they need more device spaceย (but obviously use this cautiously and don't abuse it).

I'd be interested to see whether IndexedDB could be used with search blobs from Algolia, even if only on a local instance based on user permission.

๐Ÿ“† 04 May 2020  |  ๐Ÿ”—

  • Frontend, 
  • PWA, 
  • service worker, 
  • IndexedDB, 
  • Cache Storage API, 
  • cookies, 
  • SessionStorage, 
  • LocalStorage, 
  • Native File System API, 
  • API, 
  • offline, 
  • data store, 
  • StorageManager API, 
  • browser, 
  • search 

@property | Chris Coyier

Looks like CSS is getting extensibility built-in with a new @property element (works like @media โ€“ also looks like we're getting CSS.registerProperty() in JavaScript ๐Ÿค”).

It'll work as below, and let you extend existing CSS functions with a similar syntax to CSS variables. Not 100% sure about how useful it will be, but it's always nice to see added flexibility and certainly the gradient animation use case provided in the example would have its purposes.

@property --my-property {
    syntax: '<color>';
    initial-value: green;
    inherits: false;
}