Archive: May, 2019

153

sparkline
                    5th                     10th                     15th                     20th                     25th                     30th     
12am  
4am                
8am                                          
12pm                                            
4pm                              
8pm            

Friday, May 31st, 2019

Medium | Stackbit

This is very handy! Export your data from Ev’s blog and then import it into a static site generator of your choice.

You may have noticed the recent movement of people looking to get off Medium. Most of us are motivated by a desire to own our content, have data portability and get more control over how/where our content is displayed and monetized. Most importantly many of us consider our blog/site to be a core part of our online identity and while Medium offers a fantastic writing experience it sacrifices other important values. Luckily there’s a modern approach to running your blog which aligns with these ideals, its called the JAMstack and its all around us.

W3C TAG Ethical Web Principles

  • There is one web
  • The web should not cause harm to society
  • The web must support healthy community and debate
  • The web is for all people
  • Security and privacy are essential
  • The web must enable freedom of expression
  • The web must make it possible for people to verify the information they see
  • The web must enhance individuals’ control and power
  • The web must be an environmentally sustainable platform
  • The web is transparent
  • The web is multi-browser, multi-OS and multi-device
  • People should be able to render web content as they want

Who’d like to be head of front-end development at Clearleft?

https://adactio.com/journal/15126

Is it you?

https://clearleft.com/team/jobs/head-of-front-end-development

The World-Wide Work

I’ve been to a lot of events and I’ve seen a lot of talks. I find that, even after all this time, I always get something out of every presentation I see. Kudos to anyone who’s got the guts to get up on stage and share their thoughts.

But there are some talks that are genuinely special. When they come along, it’s a real privilege to be in the room. Wilson’s talk, When We Build was one of those moments. There are some others that weren’t recorded, but will always stay with me.

Earlier this year, I had the great honour of opening the New Adventures conference in Nottingham. I definitely felt a lot of pressure, and I did my utmost to set the scene for the day. The final talk of the day was delivered by my good friend Ethan. He took it to another level.

Like I said at the time:

Look, I could gush over how good Ethan’s talk was, or try to summarise it, but there’s really no point. I’ll just say that I felt the same sense of being present at something genuinely important that I felt when I was in the room for his original responsive web design talk at An Event Apart back in 2010. When the video is released, you really must watch it.

Well, the video has been released and you really must watch it. Don’t multitask. Don’t fast forward. Set aside some time and space, and then take it all in.

The subject matter, the narrative structure, the delivery, and the message come together in a unique way.

If, having watched the presentation, you want to dive deeper into any of Ethan’s references, check out the reading list that accompanies the talk.

I mentioned that I felt under pressure to deliver a good opener for New Adventures. I know that Ethan was really feeling the pressure too. He needn’t have worried. He delivered one of the best conference talks I’ve ever seen.

Thank you, Ethan.

Goblin of Fire

Goblin of Fire

Thursday, May 30th, 2019

Replying to a tweet from @Lady_Ada_King

Looks great!

Welcoming @rem to Homebrew Website Club Brighton.

Welcoming @rem to Homebrew Website Club Brighton.

OH: “H.P. Lovecraft? I thought you said PHP Lovecraft.”

Characteristics of a Strong Performance Culture | TimKadlec.com

Tim looks at the common traits of companies that have built a good culture of web performance:

  1. Top-down support
  2. Data-driven
  3. Clear targets
  4. Automation
  5. Knowledge sharing
  6. Culture of experimentation
  7. User focused, not tool focused

Few companies carry all of these characteristics, so it’s important not to get discouraged if you feel you’re missing a few of them. It’s a process and not a quick one. When I’ve asked folks at companies with all or most of these characteristics how long it took them to get to that point, the answer is typically in years, rarely months. Making meaningful changes to culture is much slower and far more difficult than making technical changes, but absolutely critical if you want those technical changes to have the impact you’re hoping for.

Indie web events in Brighton

Homebrew Website Club is a regular gathering of people getting together to tinker on their own websites. It’s a play on the original Homebrew Computer Club from the ’70s. It shares a similar spirit of sharing and collaboration.

Homebrew Website Clubs happen at various locations: London, San Francisco, Portland, Nuremberg, and more. Usually there on every second Wednesday.

I started running Homebrew Website Club Brighton a while back. I tried the “every second Wednesday” thing, but it was tricky to make that work. People found it hard to keep track of which Wednesdays were Homebrew days and which weren’t. And if you missed one, then it would potentially be weeks between attending.

So I’ve made it a weekly gathering. On Thursdays. That’s mostly because Thursdays work for me: that’s one of the evenings when Jessica has her ballet class, so it’s the perfect time for me to spend a while in the company of fellow website owners.

If you’re in Brighton and you have your own website (or you want to have your own website), you should come along. It’s every Thursday from 6pm to 7:30pm ‘round at the Clearleft studio on 68 Middle Street. Add it to your calendar.

There might be a Thursday when I’m not around, but it’s highly likely that Homebrew Website Club Brighton will happen anyway because either Trys, Benjamin or Cassie will be here.

(I’m at Homebrew Website Club Brighton right now, writing this. Remy is here too, working on some very cool webmention stuff.)

There’s something else you should add to your calendar. We’re going to have an Indie Web Camp in Brighton on October 19th and 20th. I realise that’s quite a way off, but I’m giving you plenty of advance warning so you can block out that weekend (and plan travel if you’re coming from outside Brighton).

If you’ve never been to an Indie Web Camp before, you should definitely come! It’s indescribably fun and inspiring. The first day—Saturday—is a BarCamp-style day of discussions to really get the ideas flowing. Then the second day—Sunday—is all about designing, building, and making. The whole thing wraps up with demos.

It’s been a while since we’ve had an Indie Web Camp in Brighton. You can catch up on the Brighton Indie Web Camps we had in 2014, 2015, and 2016. Since then I’ve been to Indie Web Camps in Berlin, Nuremberg, and Düsseldorf, but it’s going to be really nice to bring it back home.

Indie Web Camp UK attendees Indie Web Camp Brighton group photo IndieWebCampBrighton2016

The event will be free to attend, but I’ll set up an official ticket page on Ti.to to keep track of who’s coming. I’ll let you know when that’s up and ready. In the meantime, you can register your interest in attending on the 2019 Indie Webcamp Brighton page on the Indie Web wiki.

Replying to a tweet from @ambrwlsn90

Kaffeeklatsch!

Is CSS Turing Complete? | Lara Schenck

This starts as a good bit of computer science nerdery, that kind of answers the question in the title:

Alone, CSS is not Turing complete. CSS plus HTML plus user input is Turing complete!

And so the takeaway here is bigger than just speculation about Turing completeness:

Given that CSS is a domain-specific language for styling user interface, this makes a lot of sense! CSS + HTML + Human = Turing complete.

At the end of that day, as CSS developers that is the language we really write. CSS is incomplete without HTML, and a styled interface is incomplete without a human to use it.

Replying to a tweet from @KenjiBaheux

I wish that websites would put that sentence right next to their “sign up now!” call to action:

Every project eventually dies, effectively or in practice.

Then, people would be informed about what they’re getting into.

Replying to a post on xavierroy.com

Alas, no! It’s a shame—I really liked that Hack Farm project. 😔

Decimal Clock

If we had ten hours in a day, instead of 24, and if each of these hours had 100 minutes instead of 60, and if every minute had 100 seconds, our clocks would look like this…

Replying to a tweet from @Una

As always, it depends, but I find that for many sites (e.g. publishing sites) a framework would be overkill. Unless complex state management is a requirement, vanilla JavaScript is more than up to the task of sprinkling in interactivity.

Replying to a tweet from @triblondon

None of these are “surely a good thing” if you look at them from the perspective of a user:

https://ourincrediblejourney.tumblr.com/

https://indieweb.org/site-deaths

Replying to a tweet from @triblondon

Only if you tell people in advance, when they’re signing up to use your product, that this is what’s going to happen.

The mismatch in expectations should definitely not be applauded.

Wednesday, May 29th, 2019

This pub dog is gettin’ good scritches.

This pub dog is gettin’ good scritches.

Checked in at Jolly Brewer. Midweek session — with Jessica map

Checked in at Jolly Brewer. Midweek session — with Jessica

Patterns Day is now sold out …but if you missed out on tickets, there’s one way you can still make it to the event: your company can sponsor it.

https://adactio.com/journal/15241

Sponsor Patterns Day

Patterns Day 2 is sold out! Yay!

I didn’t even get the chance to announce the full line-up before all the tickets were sold. That was meant to my marketing strategy, see? I’d announce some more speakers every few weeks, and that would encourage more people to buy tickets. Turns out that I didn’t need to do that.

But I’m still going to announce the final two speakers here becuase I’m so excited about them—Danielle Huntrods and Varya Stepanova!

Danielle is absolutely brilliant. I know this from personal experience because I worked alongside her at Clearleft for three years. Now she’s at Bulb and I can’t wait for everyone at Patterns Day to hear her galaxy brain thoughts on design systems.

And how could I not have Varya at Patterns Day? She lives and breathes design systems. Whether it’s coding, writing, speaking, or training, she’s got years of experience to share. Ever used BEM? Yeah, that was Varya.

Anyway, if you’ve got your ticket for Patterns Day, you’re in for a treat.

If you didn’t manage to get a ticket for Patterns Day …sorry.

But do not despair. There is still one possible way of securing an elusive Patterns Day ticket: get your company to sponsor the event.

We’ve already got one sponsor—buildit @ wipro digital—who are kindly covering the costs for teas, coffees, and pastries. Now I’m looking for another sponsor to cover the costs of making video recordings of the talks.

The cost of sponsorship is £2000. In exchange, I can’t offer you a sponsor stand or anything like that—there’s just no room at the venue. But you will earn my undying thanks, and you’ll get your logo on the website and on the screen in between talks on the day (and on the final videos).

I can also give you four tickets to Patterns Day.

This is a sponsorship strategy that I like to call “blackmail.”

If you were really hoping to bring your team to Patterns Day, but you left it too late to get your tickets, now’s your chance. Convince your company to sponsor the event (and let’s face it, £2000 is a rounding error on some company’s books). Then you and your colleagues need not live with eternal regret and FOMO.

Drop me a line. Let’s talk.

Cake or death: AMP and the worrying power dynamics of the web | Andrew Betts

Andrew looks at AMP from a technical, UX, and commercial perspective. It looks pretty bad in all three areas. And the common thread is the coercion being applied to publishers.

But casting the web aside and pushing a new proprietary content format (which is optional, but see coercion) seems like an extraordinarily heavy handed way to address it. It’s like saying I see you have a graze on your knee so let’s chop off and replace your whole leg. Instead, we could use the carrot of a premium search result position (as AMP has done) and make it only possible to be there if your site is fast.

He’s absolutely right about how it sounds when the AMP team proudly talk about how many publishers are adopting their framework, as if the framework were actually standing on its own merits instead of being used to blackmail publishers:

It is utterly bizarre to me, akin to a street robber that has convinced himself that people just randomly like giving him their money and has managed to forget the fact that he’s holding a gun to their head.

Photo Editor : Pixlr.com - free image editing online

This is quite nifty: a fully-featured photo editing tool right in the browser, with no log-in or registration required.

Reducing motion with the picture element

Here’s a clever tiny lesson from Dave and Brad: you can use prefers-reduced-motion in the media attribute of the source element inside picture.

Tuesday, May 28th, 2019

Plotters, pantsers, and user onboarding | Krystal Higgins

Krystal compares two styles of writing and applies them to onboarding.

Reading Resilient Management by Lara Hogan.

Opinion | It’s 2059, and the Rich Kids Are Still Winning - The New York Times

The New York Times is publishing science-fictional op-eds. The first one is from Ted Chiang on the Gene Equality Project forty years in our future:

White supremacist groups have claimed that its failure shows that certain races are incapable of being improved, given that many — although by no means all — of the beneficiaries of the project were people of color. Conspiracy theorists have accused the participating geneticists of malfeasance, claiming that they pursued a secret agenda to withhold genetic enhancements from the lower classes. But these explanations are unnecessary when one realizes the fundamental mistake underlying the Gene Equality Project: Cognitive enhancements are useful only when you live in a society that rewards ability, and the United States isn’t one.

Obama’s Presidential Library Should Be Digital-First - The Atlantic

Given its origins and composition, the Obama library is already largely digital. The vast majority of the record his presidency left behind consists not of evocative handwritten notes, printed cable transmissions, and black-and-white photographs, but email, Word documents, and JPEGs. The question now is how to leverage its digital nature to make it maximally useful and used.

W3C and WHATWG to work together to advance the open Web platform | W3C Blog

It’s Armistice Day in the world of HTML:

WHATWG maintains the HTML and DOM Living Standards.

W3C stops independent publishing of a designated list of specifications related to HTML and DOM and instead will work to take WHATWG Review Drafts to W3C Recommendations.

It feels like the loop is finally being closed on what I wrote about in the opening chapter of HTML5 For Web Designers back in 2010.

I know that “bot” is meant to be short for “robot”, but I can’t help reading it as being short for “bottom”

e.g.

“Chatbottoms are the next big thing.”

or

“Optimise your website for searchbottoms.”

Evolution of Webdesign

Funny because it’s true.

How Ireland became Europe’s data watchdog - BBC News

The coming GDPR storm:

Ireland’s Data Protection Commissioner, Helen Dixon, is expected to circulate her decisions on some cases by July or August, with final rulings made by the end of the year.

(That’s my sister-in-law, that is.)

Monday, May 27th, 2019

Replying to a tweet from @ambrwlsn90

Nice! I really like the look of the reading section.

Bullet Time

Bullet comments, or 弹幕 (“danmu”), are text-based user reactions superimposed onto online videos: a visual commentary track to which anyone can contribute.

A fascinating article by Christina Xu on this overwhelming collaborative UI overlaid on Chinese video-sharing sites:

In the West, the Chinese internet is mostly depicted in negative terms: what websites and social platforms are blocked, what keywords are banned, what conversations and viral posts are scrubbed clean from the web overnight. This austere view is not inaccurate, but it leaves out what exactly the nearly 750 million internet users in China do get up to.

Take a look at bullet comments, and you’ll have a decent answer to that question. They represent the essence of Chinese internet culture: fast-paced and impish, playfully collaborative, thick with rapidly evolving inside jokes and memes. They are a social feature beloved by a generation known for being antisocial. And most importantly, they allow for a type of spontaneous, cumulative, and public conversation between strangers that is increasingly rare on the Chinese internet.

Plain Text vs. HTML Emails: Which Is Better? [New Data]

Spoiler: it’s plain text. Every time.

Nothing boosts opens and clicks as well as an old school, plain-text email.

I feel vindicated.

People say they prefer HTML emails ..but they actually prefer plain-text.

This seems like a plausable explanation:

Think about how you email colleagues and friends: Do you usually add images or use well-designed templates? Probably not, and neither does your audience. They’re used to using email to communicate in a personal way, so emails from companies that look more personal will resonate more.

Now get off my lawn, you pesky HTML-email lovin’ kids.

Hidden Heroines of Chaos: Ellen Fetter and Margaret Hamilton | Quanta Magazine

Before leading the software project that put men on the moon, Margaret Hamilton worked on the equations that led to chaos theory, followed by Mount Holyoke graduate, Ellen Fetter.

Sunday, May 26th, 2019

Eating toast with a fried egg on patatas con chorizo (with beet tops). 🍳

Eating toast with a fried egg on patatas con chorizo (with beet tops). 🍳

Friday, May 24th, 2019

Replying to a tweet from @Una

Technically, that would be a felony, but I’ll see what I can do.

Petting this lovely doggo at the bus stop.

Petting this lovely doggo at the bus stop.

Replying to a tweet from @andybelldesign

It has been an absolute pleasure, Andy! Thank you for your excellent work!

Documenting the latest addition to the @beerleft line at the @clearleft studio.

Documenting the latest addition to the @beerleft line at the @clearleft studio.

Night Mode with Mix Blend Mode: Difference

Here’s a clever shortcut to creating a dark mode by using mix-blend-mode: difference.

The Bit Player

Ooh! A documentary on Claude Shannon—exciting!

I just finished reading A Mind At Play, the (very good) biography of Claude Shannon, so this film feels very timely.

Mixing contemporary interviews, archival film, animation and dialogue drawn from interviews conducted with Shannon himself, The Bit Player tells the story of an overlooked genius who revolutionized the world, but never lost his childlike curiosity.

Thursday, May 23rd, 2019

Checked in at The Skiff. Codebar monthly map

Checked in at The Skiff. Codebar monthly

Homebrew Website Club Brighton.

Homebrew Website Club Brighton.

Beyond

After a fun and productive Indie Web Camp, I stuck around Düsseldorf for Beyond Tellerand. I love this event. I’ve spoken at it quite a few times, but this year it was nice to be there as an attendee. It’s simultaneously a chance to reconnect with old friends I haven’t seen in a while, and an opportunity to meet lovely new people. There was plenty of both this year.

I think this might have been the best Beyond Tellerrand yet, and that’s saying something. It’s not just that the talks were really good—there was also a wonderful atmosphere.

Marc somehow manages to curate a line-up that’s equal parts creativity and code; design and development. It shouldn’t work, but it does. I love the fact that he had a legend of the industry like David Carson on the same stage as first-time speaker like Dorobot …and the crowd loved ‘em equally!

During the event, I found out that I had a small part to play in the creation of the line-up…

Three years ago, I linked to a video of a talk by Mike Hill:

A terrific analysis of industrial design in film and games …featuring a scene-setting opening that delineates the difference between pleasure and happiness.

It’s a talk about chairs in Jodie Foster films. Seriously. It’s fantastic!

Marc saw my link, watched the video, and decided he wanted to get Mike Hill to speak at Beyond Tellerrand. After failing to get a response by email, Marc managed to corner Mike at an event in Amsterdam and get him on this year’s line-up.

Mike gave a talk called The Power of Metaphor and it’s absolutely brilliant. It covers the monomyth (the hero’s journey) and Jungian archetypes, illustrated with the examples Star Wars, The Dark Knight, and Jurassic Park:

Under the surface of their most celebrated films lies a hidden architecture that operates on an unconscious level; This talk is designed to illuminate the techniques that great storytellers use to engage a global audience on a deep and meaningful level through psychological metaphor.

The videos from Beyond Tellerrand are already online so you can watch the talk now.

Mike’s talk was back-to-back with a talk from Carolyn Stransky called Humanising Your Documentation:

In this talk, we’ll discuss how the language we use affects our users and the first steps towards writing accessible, approachable and use case-driven documentation.

While the talk was ostensibly about documentation, I found that it was packed full of good advice for writing well in general.

I had a thought. What if you mashed up these two talks? What if you wrote documentation through the lens of the hero’s journey?

Think about it. When somone arrives at your documentation, they’ve crossed the threshold to the underworld. They are in the cave, facing a dragon. You are their guide, their mentor, their Obi-Wan Kenobi. You can help them conquer their demons and return to the familiar world, changed by their journey.

Too much?

I think this evening’s Homebrew Website Club Brighton in @68MiddleSt will start and end a bit early so that we can head over to @TheSkiff for the excellent @CodebarBrighton talks.

Playdate. A New Handheld Gaming System

Well, this is interesting. Panic, the little software company that could, are making a handheld gaming device. This is like the hardware equivalent of the indie web.

Wednesday, May 22nd, 2019

map

Checked in at Jolly Brewer. Session — with Jessica

Replies

Last week was a bit of an event whirlwind. In the space of seven days I was at Indie Web Camp, Beyond Tellerrand, and Accessibility Club in Düsseldorf, followed by a train ride to Utrecht for Frontend United. Phew!

Indie Web Camp Düsseldorf was—as always—excellent. Once again, Sipgate generously gave us the use of their lovely, lovely space for the weekend. We had one day of really thought-provoking discussions, followed by a day of heads-down hacking and making.

I decided it was time for me to finally own my replies. For a while now, I’ve been posting notes on my own site and syndicating to Twitter. But whenever I replied to someone else’s tweet, I did from Twitter. I wanted to change that.

From a coding point of view, it wasn’t all that tricky. The real challenges were to do with the interface. I needed to add another field for the URL I’m replying to …but I didn’t want my nice and minimal posting interface to get too cluttered. I ended up putting the new form field inside a details element with a summary of “Reply to” so that the form field would be hidden by default, and toggled open by hitting that “Reply to” text:

<details>
    <summary>
        <label for="replyto">Reply to</label>
    </summary>
    <input type="url" id="replyto" name="replyto">
</details>

I sent my first test reply to a post on Aaron’s website. Aaron was sitting next to me at the time.

Once that was all working, I sent my first reply to a tweet. It was a response to a tweet from Tantek. Tantek was also sitting next to me at the time.

I spent most of the day getting that Twitter syndication to work. I had something to demo, but I foolishly decided to risk it all by attempting to create a bookmarklet so that I could post directly from a tweet page (instead of hopping back to my own site in a different tab). By canabalising the existing bookmarklet I use for posting links, I just about managed to get it working in time for the end of day demos.

So I’m owning my replies now. At the moment, they show up in my home page feed just like any other notes I post. I’m not sure if I’ll keep it that way. They don’t make much sense out of context.

Then again, I kind of like how wonderfully random and out-of-context they look. You can browse through all my replies so far.

I’m glad I got this set up. Now when Andy posts stuff on Twitter, I’m custodian of my responses:

@AndyBudd: Who are your current “Design Heroes”?

adactio.com: I would say Falcor from Neverending Story, the big flying dog.

Bruce Lawson’s personal site  : Structured data and Google

Bruce wonders why Google seems to prefer separate chunks of JSON-LD in web pages instead of interwoven microdata attributes:

I strongly feel that metadata that is separated from the user-visible data associated with it highly susceptible to metadata partial copy-paste necrosis. User-visible text is also developer-visible text. When devs copy/ paste that, it’s very easy to forget to copy any associated metadata that’s not interleaved, leading to errors.

Complexity Explorables

A cornucopia of interactive visualisations. You control the horizontal. You control the vertical. Networks, flocking, emergence, diffusion …it’s all here.

Accessible Icon Buttons — Sara Soueidan – Freelance-Front-End UI/UX Developer

Sara runs through the many ways of providing an accessible name to an icon button, backed up with Scott’s testing.

Our intern program is returning for 2019 | Clearleft

Know any graduates who’d like to take part in a fun (paid) three month scheme at Clearleft? Send ‘em our way.

brb. Forming a crime-fighting duo with my partner @ZachLeat. ( Photo by Juliane Schütz https://julieannenoying.com )

brb. Forming a crime-fighting duo with my partner @ZachLeat.

( Photo by Juliane Schütz https://julieannenoying.com )

Making Future Interfaces: Custom Properties - YouTube

Heydon cracks me up—his Patterns Day is going to have you crying with laughter; guaranteed!

Here he is talking about custom properties in CSS as part of his Making Future Interfaces video series.

Tuesday, May 21st, 2019

Replying to a tweet from @Minette_78

Whachya readin’?

Replying to a tweet from @franco_scarpa92

I don’t know. Good question.

Picture 1 Picture 2

1st course: asparagus with bagna cauda.

2nd course: gnocchi sardi with pork ragu.

Checked in at Community Base. Cooking masterclass with Jamie from Cin Cin — with Jessica map

Checked in at Community Base. Cooking masterclass with Jamie from Cin Cin — with Jessica

Can “Indie” Social Media Save Us? | The New Yorker

This is a really great, balanced profile of the Indie Web movement. There’s thoughtful criticism alongside some well-deserved praise:

If we itemize the woes currently afflicting the major platforms, there’s a strong case to be made that the IndieWeb avoids them. When social-media servers aren’t controlled by a small number of massive public companies, the incentive to exploit users diminishes. The homegrown, community-oriented feel of the IndieWeb is superior to the vibe of anxious narcissism that’s degrading existing services.

Take Back Your Web - Tantek Çelik on Vimeo

Tantek’s barnstorming closing talk from Beyond Tellerrand. This is well worth 30 minutes of your time.

Own your domain. Own your content. Own your social connections. Own your reading experience. IndieWeb services, tools, and standards enable you to take back your web.

The Training Commission

Coming to your inbox soon:

The Training Commission is a speculative fiction email newsletter about the compromises and consequences of using technology to reckon with collective trauma. Several years after a period of civil unrest and digital blackouts in the United States, a truth and reconciliation process has led to a major restructuring of the federal government, major tech companies, and the criminal justice system.

Replying to a tweet from @KevinSimler

This is my new favourite web page!

Going Critical — Melting Asphalt

This is an utterly fascinating interactive description of network effects, complete with Nicky Case style games. Play around with the parameters and suddenly you can see things “going viral”:

We can see similar things taking place in the landscape for ideas and inventions. Often the world isn’t ready for an idea, in which case it may be invented again and again without catching on. At the other extreme, the world may be fully primed for an invention (lots of latent demand), and so as soon as it’s born, it’s adopted by everyone. In-between are ideas that are invented in multiple places and spread locally, but not enough so that any individual version of the idea takes over the whole network all at once. In this latter category we find e.g. agriculture and writing, which were independently invented ~10 and ~3 times respectively.

Play around somewhere and you start to see why cities are where ideas have sex:

What I learned from the simulation above is that there are ideas and cultural practices that can take root and spread in a city that simply can’t spread out in the countryside. (Mathematically can’t.) These are the very same ideas and the very same kinds of people. It’s not that rural folks are e.g. “small-minded”; when exposed to one of these ideas, they’re exactly as likely to adopt it as someone in the city. Rather, it’s that the idea itself can’t go viral in the countryside because there aren’t as many connections along which it can spread.

This really is a wonderful web page! (and it’s licensed under a Creative Commons Zero licence)

We tend to think that if something’s a good idea, it will eventually reach everyone, and if something’s a bad idea, it will fizzle out. And while that’s certainly true at the extremes, in between are a bunch of ideas and practices that can only go viral in certain networks. I find this fascinating.

What Does it Mean to Be “Full Stack”? | CSS-Tricks

I’m not trying to convince anyone they aren’t a full-stack developer or don’t deserve that particular merit badge — just that the web is a big place with divergent needs and ever-morphing stacks that all require different sets of skills.

Delighted to announce that @Varya_en and @DHuntrods will both be speaking at Patterns Day!

https://patternsday.com/

Hope you got your ticket, ’cause if you didn’t …you’re too late (unless maybe your company can sponsor the event).

Replying to a tweet from @samdbeckham

No, your conferences are the best!

Aaaaand Patterns Day is sold out!

If you got a ticket, I’ll see you in Brighton on June 28th: https://patternsday.com

(I haven’t even announced the full line-up yet.)

Monday, May 20th, 2019

Accessible Color Generator – Learn UI Design

This looks like a really useful tool for generating accessibile colour combinations from a starting colour.

Science Fiction Doesn’t Have to Be Dystopian | The New Yorker

Ted Chiang has new collection out‽ Why did nobody tell me‽

Okay, well, technically this is Joyce Carol Oates telling me. In any case …woo-hoo!!!

Web Bloat Score Calculator

Page web bloat score (WebBS for short) is calculated as follows:

WebBS = TotalPageSize / PageImageSize

Yes, this is a tongue-in-cheek somewhat arbitrary measurement, but it’s well worth reading through the rationale for it.

How can the image of a page be smaller than the page itself?

Replying to a tweet from @lottejackson

You are amazing, Charlotte!

Sunday, May 19th, 2019

Replying to a tweet from @iceMagic

You’re too kind—thank you very much!

map

Checked in at The Bugle Inn. Tunes — with Jessica

map

Checked in at British Airways Galleries Lounge. Homeward bound.

Saturday, May 18th, 2019

Replying to a tweet from @frankmeeuwsen

I wish I could! But I’m leaving very early tomorrow. Hope it went well today. Enjoy hacking tomorrow!

Picture 1 Picture 2 Picture 3

Going for a stroll in Utrecht at dusk.

Checked in at Kimmade. Pho 🍲 map

Checked in at Kimmade. Pho 🍲

Replying to a tweet from @katharinabrx

Yay! 🎉

Friday, May 17th, 2019

Eintrag “Take back your web – Tantek Çelik @ Beyond Tellerrand Conference, Düsseldorf 2019” beim Webrocker

Tom shares his thoughts on Tantek’s excellent closing talk at Beyond Tellerrand this week:

Yes, the message of this rather sombre closing talk of this year’s Beyond Tellerrand Conference Düsseldorf is important. Watch it. And then go out, take care of yourself and others, away from the screen. And then come back and publish your own stuff on your own site. Still not convinced? ok, then, please read Matthias Ott’s great article (published on his own site btw), and then start using your own site.

Replying to a tweet from @andybudd

I would say Falcor from Neverending Story, the big flying dog.

I would say Falcor from Neverending Story, the big flying dog.

Replying to a tweet from @CamBirch

I’m pretty sure the talk was recorded so once the video is online, you’ll be able to get the full context.

In the meantime…

🙄

Replying to a tweet from @psd

I’d give the saddle a good wipe-down before sitting on it, if I were you.

Replying to a tweet from @CamBirch

I don’t think you’re missing anything …other than the entire context of what you’re commenting on.

Replying to a tweet from @RowdyRabouw

🙌

Hmmm. Yes. Thought-provoking talk by @Vasilis. @StephenHay and I approve.

Hmmm. Yes. Thought-provoking talk by @Vasilis. @StephenHay and I approve.

Replying to a tweet from @bopp

Chrome on iOS is just a skinned version of Safari …minus some low-level features.

Personally, I think it’s anti-competitive of Apple not to allow other rendering engines in the App Store.

Getting ready to kick off @FrontendUnited in Utrecht.

Getting ready to kick off @FrontendUnited in Utrecht.

Thursday, May 16th, 2019

Replying to a tweet from @sarah_edo

  • webinar

Replying to a tweet from @andybelldesign

One potential upside to Edge switching to Chromium is that Edge and Chrome could now compete on ambient badging design while maintaining feature parity.

Replying to a tweet from @frontendunited

Drinks sound great! …but I think I would gnaw my own arm off during Eurovision.

Josephine the cat is keeping me company in this charming Dutch bar.

Josephine the cat is keeping me company in this charming Dutch bar.

Checked in at Café Derat. Hello, Utrecht. map

Checked in at Café Derat. Hello, Utrecht.

Replying to a tweet from @katharinabrx

It was lovely to meet you, Katharina!

Today is Global Accessibility Awareness Day.

Here are some links related to accessibility that I’ve recently shared: https://adactio.com/links/tags/a11y

TIL (Today I learned) - Manuel Matuzović

At Clearleft, we’re always saying “Everything is a tiny lesson!”, so I love, love, love this bit of Manuel’s website where notes down short code snippets of little things he learns.

Lighthouse | Eric Bailey

What if accessibility were a ranking signal for Google search results?

Here’s a thought: what if Google put its thumb on the scale again, only this time for accessibility? What if it treated the Lighthouse accessibility score as a first-class ranking metric?

Welcome to Acccessible App | Accessible App

A very welcome project from Marcus Herrmann, documenting how to make common interaction patterns accessible in popular frameworks: Vue, React, and Angular.

Going to Utrecht. brb

Picture 1 Picture 2

Auf Wiedersehen, Düsseldorf!

Wednesday, May 15th, 2019

Currywurst und Rothaus.

Currywurst und Rothaus.

Checked in at Curry. Post-A11yClub currywurst. — with aaronpk, Joschi, Tantek map

Checked in at Curry. Post-A11yClub currywurst. — with aaronpk, Joschi, Tantek

A report from the AMP Advisory Committee Meeting – Terence Eden’s Blog

I completely agree with every single one of Terence’s recommendations here. The difference is that, in my case, they’re just hot takes, whereas he has actually joined the AMP Advisory Committee, joined their meetings, and listened to the concerns of actual publishers.

He finds:

  • AMP isn’t loved by publishers
  • AMP is not accessible
  • No user research
  • AMP spreads fake news
  • Signed Exchanges are not the answer

There’s also a very worrying anti-competitive move by Google Search in only showing AMP results to users of Google Chrome.

I’ve been emailing with Paul from the AMP team and I’ve told him that I honestly think that AMP’s goal should be to make itself redundant …the opposite of the direction it’s going in.

As I said in the meeting - if it were up to me, I’d go “Well, AMP was an interesting experiment. Now it is time to shut it down and take the lessons learned back through a proper standards process.”

I suspect that is unlikely to happen. Google shows no sign of dropping AMP. Mind you, I thought that about Google+ and Inbox, so who knows!

Good point!

Humanizing Your Documentation - Full Talk - Speaker Deck

The slides from Carolyn’s talk at Beyond Tellerrand. The presentation is ostensibly about writing documentation, but I think it’s packed with good advice for writing in general.

Columbia & Elm; Fairfield & Gloucester. — Ethan Marcotte

Coffee talk with Ethan Marcotte. Today’s special: inclusivity.

I want to get there: to have nuanced discussions about text descriptions; I want to read poetry in alt text; to have our work’s success measured by how broadly it can be accessed; to create moving, beautiful experiences for people who may not use the web like I do.

Tuesday, May 14th, 2019

Feeling thoroughly inspired after an excellent @BTconf—great talks from start to finish.

I think this may have been the best one yet (which is understandable, given that I wasn’t speaking this time).

Well done, @MarcThiele!

Picture 1 Picture 2

Ramen and gyoza.

Replying to a tweet from @zachleat

Don’t fuck it up, Zach. :-|

Replying to a tweet from @natlburns

Thank you—good to know!

Replying to a tweet from @harrybr

Pass the phone to me, Harry. I got this.

Monday, May 13th, 2019

Replying to a tweet from @Minette_78

One. Of. Us! One. Of. Us!

Hangin’ with my @BTconf gang, @zachleat and @sonniesedge.

Hangin’ with my @BTconf gang, @zachleat and @sonniesedge.

It warms my heart that @MarcThiele got Mike Hill to speak at this year’s @BTconf because of a link on my site three years ago: https://adactio.com/links/10052

Shoutout to @LauraKalbag in @CarolStran’s excellent @BTconf talk on writing clear, accessible documentation (which turns out to be great advice on good writing in general).

Shoutout to @LauraKalbag in @CarolStran’s excellent @BTconf talk on writing clear, accessible documentation (which turns out to be great advice on good writing in general).

Sunday, May 12th, 2019

IndieWebCamp Düsseldorf 2019 | 2 | Flickr

Today was a good day …and here are the very good photos.

IMG_2295

Replying to a tweet from @sonniesedge

Thanks to @aaronpk, I think I’ve also found a way to post replies without having to preface it with the at-username.

Into the Personal-Website-Verse · Matthias Ott – User Experience Designer

There is one alternative to social media sites and publishing platforms that has been around since the early, innocent days of the web. It is an alternative that provides immense freedom and control: The personal website. It’s a place to write, create, and share whatever you like, without the need to ask for anyone’s permission.

A wonderful and inspiring call to arms for having your own website—a place to express yourself, and a playground, all rolled into one.

Building and maintaining your personal website is an investment that is challenging and can feel laborious at times. Be prepared for that. But what you will learn along the way does easily make up for all the effort and makes the journey more than worthwhile.

Replying to a tweet from @ppk

@ppk See you soon!

Replying to a tweet from @sonniesedge

@sonniesedge Live demos? Don’t talk to me about live demos!

Replying to a tweet from @t

@t Looking good!

Replying to a post on aaronparecki.com

@aaronpk I’m testing my replies’n’stuff.

Replying to a post on aaronparecki.com

Tables are weird!

Brendan Dawes - Permission to Write Stuff

A beautiful post by Brendan, comparing the ease of publishing on the web to the original Flip camera:

Right now there’s a real renaissance of people getting back to blogging on their own sites again. If you’ve been putting it off, think about the beauty and simplicity of that red button, press it, and try and help make the web the place it was always meant to be.

Saturday, May 11th, 2019

Checked in at sipgate GmbH. Indie Web Camp — with Tantek, aaronpk, Joschi, Rosemary map

Checked in at sipgate GmbH. Indie Web Camp — with Tantek, aaronpk, Joschi, Rosemary

Friday, May 10th, 2019

Checked in at wagamama map

Checked in at wagamama

Reading Inferior: The True Power Of Women and the Science that Shows It by Angela Saini.

Going to Düsseldorf. brb

Checking out the beautiful venue for Patterns Day—this is going to be glorious! https://patternsday.com

Checking out the beautiful venue for Patterns Day—this is going to be glorious!

https://patternsday.com

HTML Symbols, Entities, Characters and Codes

For all your copying and pasting needs:

A delightful reference for HTML Symbols, Entities and ASCII Character Codes

Thursday, May 9th, 2019

Head’s role

I have a bittersweet feeling today. Danielle is moving on from Clearleft.

I used to get really down when people left. Over time I’ve learned not to take it as such a bad thing. I mean, of course it’s sad when someone moves on, but for them, it’s exciting. And I should be sharing in that excitement, not putting a damper on it.

Besides, people tend to stay at Clearleft for years and years—in the tech world, that’s unheard of. So it’s not really so terrible when they decide to head out to pastures new. They’ll always be Clearlefties. Just look at the lovely parting words from Harry, Paul, Ellen, and Ben:

Working at Clearleft was one of the best decisions I ever made. 6 years of some work that I’m most proud of, amongst some of the finest thinkers I’ve ever met.

(Side note: I’ve been thinking about starting a podcast where I chat to ex-Clearlefties. We could reflect on the past, look to the future, and generally just have a catch-up. Would that be self indulgent or interesting? Let me know what you think.)

So of course I’m going to miss working with Danielle, but as with other former ‘lefties, I’m genuinely excited to see what happens next for her. Clearleft has had an excellent three years of her time and now it’s another company’s turn.

In the spirit of “one door closes, another opens,” Danielle’s departure creates an opportunity for someone else. Fancy working at Clearleft? Well, we’re looking for a head of front-end development.

Do you remember back at the start of the year when we were hiring a front-end developer, and I wrote about writing job postings?

My first instinct was to look at other job ads and take my cue from them. But, let’s face it, most job ads are badly written, and prone to turning into laundry lists. So I decided to just write like I normally would. You know, like a human.

That worked out really well. We ended up hiring the ridiculously talented Trys Mudford. Success!

So I’ve taken the same approach with this job ad. I’ve tried to paint as clear and honest a picture as I can of what this role would entail. Like it says, there are three main parts to the job:

  • business support,
  • technical leadership, and
  • professional development.

Now, I could easily imagine someone reading the job description and thinking, “Nope! Not for me.” Let’s face it: There Will Be Meetings. And a whole lotta context switching:

Within the course of one day, you might go from thinking about thorny code problems to helping someone on your team with their career plans to figuring out how to land new business in a previously uncharted area of technology.

I can equally imagine someone reading that and thinking “Yes! This is what I’ve been waiting for.”

Oh, and in case you’re wondering why I’m not taking this role …well, in the short term, I will for a while, but I’d consider myself qualified for maybe one third to one half of the required tasks. Yes, I can handle the professional development side of things (in fact, I really, really enjoy that). I can handle some of the technical leadership stuff—if we’re talking about HTML, CSS, JavaScript, accessibility, and performance. But all of the back-of-the-front-end stuff—build tools, libraries, toolchains—is beyond me. And I think I’d be rubbish at the business support stuff, mostly because that doesn’t excite me much. But maybe it excites you! If so, you should apply.

I can picture a few scenarios where this role could be the ideal career move…

Suppose you’re a lead developer at a product company. You enjoy leading a team of devs, and you like setting the technical direction when it comes to the tools and techniques being used. But maybe you’re frustrated by always working on the same product with the same tech stack. The agency world, where every project is different, might be exactly what you’re looking for.

Or maybe you’re an accomplished and experienced front-end developer, freelancing and contracting for years. Perhaps you’re less enamoured with being so hands-on with the code all the time. Maybe you’ve realised that what you really enjoy is solving problems and evaluating techologies, and you’d be absolutely fine with having someone else take care of the implementation. Moving into a lead role like this might be the perfect way to make the best use of your time and have more impact with your decisions.

You get the idea. If any of this is sounding intriguing to you, you should definitely apply for the role. What do you have to lose?

Also, as it says in the job ad:

If you’re from a group that is under-represented in tech, please don’t hesitate to get in touch.

Distinguishing cached vs. network HTML requests in a Service Worker | Trys Mudford

Less than 24 hours after I put the call out for a solution to this gnarly service worker challenge, Trys has come up with a solution.

Type in the digital era is a mess

Marcin explains why line height works differently in print and the web. Along the way, he hits upon this key insight about CSS:

Web also took away some of the control from typesetters. What in the print era were absolute rules, now became suggestions.

Remember that every line of CSS you write is a suggestion to the browser.

Wednesday, May 8th, 2019

Checked in at Jolly Brewer. Tunes — with Jessica map

Checked in at Jolly Brewer. Tunes — with Jessica

Timing out

Service workers are great for creating a good user experience when someone is offline. Heck, the book I wrote about service workers is literally called Going Offline.

But in some ways, the offline experience is relatively easy to handle. It’s a binary situation; either you’re online or you’re offline. What’s more challenging—and probably more common—is the situation that Jake calls Lie-Fi. That’s when technically you’ve got a network connection …but it’s a shitty connection, like one bar of mobile signal. In that situation, because there’s technically a connection, the user gets a slow frustrating experience. Whatever code you’ve got in your service worker for handling offline situations will never get triggered. When you’re handling fetch events inside a service worker, there’s no automatic time-out.

But you can make one.

That’s what I’ve done recently here on adactio.com. Before showing you what I added to my service worker script to make that happen, let me walk you through my existing strategy for handling offline situations.

Service worker strategies

Alright, so in my service worker script, I’ve got a block of code for handling requests from fetch events:

addEventListener('fetch', fetchEvent => {
        const request = fetchEvent.request;
    // Do something with this request.
});

I’ve got two strategies in my code. One is for dealing with requests for pages:

if (request.headers.get('Accept').includes('text/html')) {
    // Code for handling page requests.
}

By adding an else clause I can have a different strategy for dealing with requests for anything else—images, style sheets, scripts, and so on:

if (request.headers.get('Accept').includes('text/html')) {
    // Code for handling page requests.
} else {
    // Code for handling everthing else.
}

For page requests, I’m going to try to go the network first:

fetchEvent.respondWith(
    fetch(request)
    .then( responseFromFetch => {
        return responseFromFetch;
    })

My logic is:

When someone requests a page, try to fetch it from the network.

If that doesn’t work, we’re in an offline situation. That triggers the catch clause. That’s where I have my offline strategy: show a custom offline page that I’ve previously cached (during the install event):

.catch( fetchError => {
    return caches.match('/offline');
})

Now my logic has been expanded to this:

When someone requests a page, try to fetch it from the network, but if that doesn’t work, show a custom offline page instead.

So my overall code for dealing with requests for pages looks like this:

if (request.headers.get('Accept').includes('text/html')) {
    fetchEvent.respondWith(
        fetch(request)
        .then( responseFromFetch => {
            return responseFromFetch;
        })
        .catch( fetchError => {
            return caches.match('/offline');
        })
    );
}

Now I can fill in the else statement that handles everything else—images, style sheets, scripts, and so on. Here my strategy is different. I’m looking in my caches first, and I only fetch the file from network if the file can’t be found in any cache:

caches.match(request)
.then( responseFromCache => {
    return responseFromCache || fetch(request);
})

Here’s all that fetch-handling code put together:

addEventListener('fetch', fetchEvent => {
    const request = fetchEvent.request;
    if (request.headers.get('Accept').includes('text/html')) {
        fetchEvent.respondWith(
            fetch(request)
            .then( responseFromFetch => {
                return responseFromFetch;
            })
            .catch( fetchError => {
                return caches.match('/offline');
            })
        );
    } else {
        caches.match(request)
        .then( responseFromCache => {
            return responseFromCache || fetch(request);
        })
    }
});

Good.

Cache as you go

Now I want to introduce an extra step in the part of the code where I deal with requests for pages. Whenever I fetch a page from the network, I’m going to take the opportunity to squirrel it away in a cache. I’m calling that cache “pages”. I’m imaginative like that.

fetchEvent.respondWith(
    fetch(request)
    .then( responseFromFetch => {
        const copy = responseFromFetch.clone();
        try {
            fetchEvent.waitUntil(
                caches.open('pages')
                .then( pagesCache => {
                    return pagesCache.put(request, copy);
                })
            )
        } catch(error) {
            console.error(error);
        }
        return responseFromFetch;
    })

You’ll notice that I can’t put the response itself (responseFromCache) into the cache. That’s a stream that I only get to use once. Instead I need to make a copy:

const copy = responseFromFetch.clone();

That’s what gets put in the pages cache:

fetchEvent.waitUntil(
    caches.open('pages')
    .then( pagesCache => {
        return pagesCache.put(request, copy);
    })
)

Now my logic for page requests has an extra piece to it:

When someone requests a page, try to fetch it from the network and store a copy in a cache, but if that doesn’t work, show a custom offline page instead.

Here’s my updated fetch-handling code:

addEventListener('fetch', fetchEvent => {
    const request = fetchEvent.request;
    if (request.headers.get('Accept').includes('text/html')) {
        fetchEvent.respondWith(
            fetch(request)
            .then( responseFromFetch => {
                const copy = responseFromFetch.clone();
                try {
                    fetchEvent.waitUntil(
                        caches.open('pages')
                        .then( pagesCache => {
                            return pagesCache.put(request, copy);
                        })
                    )
                } catch(error) {
                    console.error(error);
                }
                return responseFromFetch;
            })
            .catch( fetchError => {
                return caches.match('/offline');
            })
        );
    } else {
        caches.match(request)
        .then( responseFromCache => {
            return responseFromCache || fetch(request);
        })
    }
});

I call this the cache-as-you-go pattern. The more pages someone views on my site, the more pages they’ll have cached.

Now that there’s an ever-growing cache of previously visited pages, I can update my offline fallback. Currently, I reach straight for the custom offline page:

.catch( fetchError => {
    return caches.match('/offline');
})

But now I can try looking for a cached copy of the requested page first:

.catch( fetchError => {
    caches.match(request)
    .then( responseFromCache => {
        return responseFromCache || caches.match('/offline');
    })
});

Now my offline logic is expanded:

When someone requests a page, try to fetch it from the network and store a copy in a cache, but if that doesn’t work, first look for an existing copy in a cache, and otherwise show a custom offline page instead.

I can also access this ever-growing cache of pages from my custom offline page to show people which pages they can revisit, even if there’s no internet connection.

So far, so good. Everything I’ve outlined so far is a good robust strategy for handling offline situations. Now I’m going to deal with the lie-fi situation, and it’s that cache-as-you-go strategy that sets me up nicely.

Timing out

I want to throw this addition into my logic:

When someone requests a page, try to fetch it from the network and store a copy in a cache, but if that doesn’t work, first look for an existing copy in a cache, and otherwise show a custom offline page instead (but if the request is taking too long, try to show a cached version of the page).

The first thing I’m going to do is rewrite my code a bit. If the fetch event is for a page, I’m going to respond with a promise:

if (request.headers.get('Accept').includes('text/html')) {
    fetchEvent.respondWith(
        new Promise( resolveWithResponse => {
            // Code for handling page requests.
        })
    );
}

Promises are kind of weird things to get your head around. They’re tailor-made for doing things asynchronously. You can set up two parameters; a success condition and a failure condition. If the success condition is executed, then we say the promise has resolved. If the failure condition is executed, then the promise rejects.

In my re-written code, I’m calling the success condition resolveWithResponse (and I haven’t bothered with a failure condition, tsk, tsk). I’m going to use resolveWithResponse in my promise everywhere that I used to have a return statement:

addEventListener('fetch', fetchEvent => {
    const request = fetchEvent.request;
    if (request.headers.get('Accept').includes('text/html')) {
        fetchEvent.respondWith(
            new Promise( resolveWithResponse => {
                fetch(request)
                .then( responseFromFetch => {
                    const copy = responseFromFetch.clone();
                    try {
                        fetchEvent.waitUntil(
                            caches.open('pages')
                            then( pagesCache => {
                                return pagesCache.put(request, copy);
                            })
                        )
                    } catch(error) {
                        console.error(error);
                    }
                    resolveWithResponse(responseFromFetch);
                })
                .catch( fetchError => {
                    caches.match(request)
                    .then( responseFromCache => {
                        resolveWithResponse(
                            responseFromCache || caches.match('/offline')
                        );
                    })
                })
            })
        );
    } else {
        caches.match(request)
        .then( responseFromCache => {
            return responseFromCache || fetch(request);
        })
    }
});

By itself, rewriting my code as a promise doesn’t change anything. Everything’s working the same as it did before. But now I can introduce the time-out logic. I’m going to put this inside my promise:

const timer = setTimeout( () => {
    caches.match(request)
    .then( responseFromCache => {
        if (responseFromCache) {
            resolveWithResponse(responseFromCache);
        }
    })
}, 3000);

If a request takes three seconds (3000 milliseconds), then that code will execute. At that point, the promise attempts to resolve with a response from the cache instead of waiting for the network. If there is a cached response, that’s what the user now gets. If there isn’t, then the wait continues for the network.

The last thing left for me to do is cancel the countdown to timing out if a network response does return within three seconds. So I put this in the then clause that’s triggered by a successful network response:

clearTimeout(timer);

I also add the clearTimeout statement to the catch clause that handles offline situations. Here’s the final code:

addEventListener('fetch', fetchEvent => {
    const request = fetchEvent.request;
    if (request.headers.get('Accept').includes('text/html')) {
        fetchEvent.respondWith(
            new Promise( resolveWithResponse => {
                const timer = setTimeout( () => {
                    caches.match(request)
                    .then( responseFromCache => {
                        if (responseFromCache) {
                            resolveWithResponse(responseFromCache);
                        }
                    })
                }, 3000);
                fetch(request)
                .then( responseFromFetch => {
                    clearTimeout(timer);
                    const copy = responseFromFetch.clone();
                    try {
                        fetchEvent.waitUntil(
                            caches.open('pages')
                            then( pagesCache => {
                                return pagesCache.put(request, copy);
                            })
                        )
                    } catch(error) {
                        console.error(error);
                    }
                    resolveWithResponse(responseFromFetch);
                })
                .catch( fetchError => {
                    clearTimeout(timer);
                    caches.match(request)
                    .then( responseFromCache => {
                        resolveWithResponse(
                            responseFromCache || caches.match('/offline')
                        );
                    })
                })
            })
        );
    } else {
        caches.match(request)
        .then( responseFromCache => {
            return responseFromCache || fetch(request)
        })
    }
});

That’s the JavaScript translation of this logic:

When someone requests a page, try to fetch it from the network and store a copy in a cache, but if that doesn’t work, first look for an existing copy in a cache, and otherwise show a custom offline page instead (but if the request is taking too long, try to show a cached version of the page).

For everything else, try finding a cached version first, otherwise fetch it from the network.

Pros and cons

As with all service worker enhancements to a website, this strategy will do absolutely nothing for first-time visitors. If you’ve never visited my site before, you’ve got nothing cached. But the more you return to the site, the more your cache is primed for speedy retrieval.

I think that serving up a cached copy of a page when the network connection is flaky is a pretty good strategy …most of the time. If we’re talking about a blog post on this site, then sure, there won’t be much that the reader is missing out on—a fixed typo or ten; maybe some additional webmentions at the end of a post. But if we’re talking about the home page, then a reader with a flaky network connection might think there’s nothing new to read when they’re served up a stale version.

What I’d really like is some way to know—on the client side—whether or not the currently-loaded page came from a cache or from a network. Then I could add some kind of interface element that says, “Hey, this page might be stale—click here if you want to check for a fresher version.” I’d also need some way in the service worker to identify any requests originating from that interface element and make sure they always go out to the network.

I think that should be doable somehow. If you can think of a way to do it, please share it. Write a blog post and send me the link.

But even without the option to over-ride the time-out, I’m glad that I’m at least doing something to handle the lie-fi situation. Perhaps I should write a sequel to Going Offline called Still Online But Only In Theory Because The Connection Sucks.

CSS-only chat

A truly monstrous async web chat using no JS whatsoever on the frontend.

This is …I mean …yes, but …it …I …

Just had a chat with @craftui about her Patterns Day talk, and Oh. Em. Gee!—I am soooo excited about it!

You won’t want to miss this, trust me…

https://patternsday.com/

Tuesday, May 7th, 2019

Unraveling The JPEG

A deep, deep, deep dive into the JPEG format. Best of all, it’s got interactive explanations you can tinker with, a la Nicky Case or Bret Victor.

Test the impact of ads and third party scripts

This is a very useful new feature in Calibre, the performance monitoring tool. Now you can get data about just how much third-party scripts are affecting your site’s performance:

The best way of circumventing fear and anxiety around third party script performance is to capture metrics that clearly articulate their performance impact.

JavaScript pedalboard

Effects pedals in the browser, using the Web Audio API. Very cool!

Be sure to read Trys’s write-up too.

Monday, May 6th, 2019

A Full Life - MIT Technology Review

A cli-fi short story by Paolo Bacigalupi.

Friday, May 3rd, 2019

A Conspiracy To Kill IE6

This is a fascinating story of psychological manipulation and internal politics. It leaves me feeling queasy about the amount of power wielded by individuals in one single organisation.

Create a responsive grid layout with no media queries, using CSS Grid - Andy Bell

CSS grid and custom properties really are a match made in heaven.

Thursday, May 2nd, 2019

I’ll be homebrewing my website in @68MiddleSt from 6pm to 7:30pm this evening. You can join the club.

https://indieweb.org/HomebrewWebsiteClub#Brighton

Frameworking

There are many reasons to use a JavaScript framework like Vue, Angular, or React. Last year, Nicole asked for some of those reasons. Her question received many, many answers from people pointing out the benefits of using a framework. Interesingly, though, not a single one of those benefits was for end users.

(Mind you, if the framework is being used on the server to pre-render pages, then it’s a moot point—in that situation, it makes no difference to the end user whether you use a framework or not.)

Hidde recently tried using a client-side JavaScript framework for the first time and documented the process:

In the last few months I built my very first framework-based front-end, in Vue.js. I complemented it with a router, a store and a GraphQL library, in order to have, respectively, multiple (virtual) pages, globally shared data and a smart way to load new data in my templates.

It’s a very even-handed write-up. I highly recommend reading it. He describes the pros and cons of using a framework and using vanilla JavaScript:

I am glad I tried a framework and found its features were extremely helpful in creating a consistent interface for my users. My hope is though, that I won’t forget about vanilla. It’s perfectly valid to build a website with no or few dependencies.

Speaking of vanilla JavaScript… the blogging machine that is Chris Ferdinandi also wrote a comparison post recently, asking Why do people choose frameworks over vanilla JS? Again, it’s very even-handed and well worth a read. He readily concedes that if you’re working at scale, a framework is almost certainly a good idea:

If you’re building a large scale application (literally Facebook, Twitter, QuickBooks scale), the performance wins of a framework make the overhead worth it.

Alas, I’ve seen many, many framework-driven sites that are most definitely not that operating at that scale. Trys speaks the honest truth here:

We kid ourselves into thinking we’re building groundbreakingly complex systems that require bleeding-edge tools, but in reality, much of what we build is a way to render two things: a list, and a single item. Here are some users, here is a user. Here are your contacts, here are your messages with that contact. There ain’t much more to it than that.

Just the other day, I saw a new site launch that was mostly a marketing site—the home page weighed over five megabytes, two megabytes of which were taken up with JavaScript, and the whole thing required JavaScript to render text to the screen (I’m not going to link to it because I don’t want to engage in any kind of public shaming and finger-wagging).

I worry that all the perfectly valid (developer experience) reasons for using a framwork are outweighing the more important (user experience) reasons for avoiding shipping your dependencies to end users. Like Alex says:

If your conception of “DX” doesn’t include it, or isn’t subservient to the user experience, rethink.

And yes, I am going to take this opportunity to link once again to Alex’s article The “Developer Experience” Bait-and-Switch. Please read it if you haven’t already. Please re-read it if you have.

Anyway, my main reason for writing this is to point you to thoughtful posts like Hidde’s and Chris’s. I think it’s great to see people thoughtfully weighing up the pros and cons of choosing any particular technology—I’m a bit obsessed with the topic of evaluating technology.

If you’re weighing up the pros and cons of using, say, a particular JavaScript library or framework, that’s wonderful. My worry is that there are people working in front-end development who aren’t putting that level of thought into their technology choices, but are instead using a particular framework because it’s what they’re used to.

To quote Grace Hopper:

The most dangerous phrase in the language is, ‘We’ve always done it this way.’

The Simplest Ways to Handle HTML Includes | CSS-Tricks

Chris looks at all the different ways of working around the fact that HTML doesn’t do transclusion. Those ways include (hah!) Scott’s super clever technique and Trys’s little Sergey.

The Web Developer’s Guide to DNS | RJ Zaworski

At Codebar the other night, I was doing an intro chat with some beginners. At one point I touched on DNS. This explanation is great for detailing what’s going on under the hood.

The Elements of Content Strategy — A Book Apart

Erin’s classic book is now available to read online for free!

AMP as your web framework – The AMP Blog

The bait’n’switch is laid bare. First, AMP is positioned as a separate format. Then, only AMP pages are allowed ranking in the top stories carousel. Now, let’s pretend none of that ever happened and act as though AMP is just another framework. Oh, and those separate AMP pages that you made? Turns out that was all just “transitional” and you’re supposed to make your entire site in AMP now.

I would genuinely love to know how the Polymer team at Google feel about this pivot. Everything claimed in this blog post about AMP is actually true of Polymer (and other libraries of web components that don’t have the luxury of bribing developers with SEO ranking).

Some alternative facts from the introduction:

AMP isn’t another “channel” or “format” that’s somehow not the web.

Weird …because that’s exactly how it was sold to us (as a direct competitor to similar offerings from Apple and Facebook).

It’s not an SEO thing.

That it outright false. Ask any company actually using AMP why they use it.

It’s not a replacement for HTML.

And yet, the article goes on to try convince you to replace HTML with AMP.