<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>localghost.dev</title>
  <subtitle>A feed of the latest posts from localghost.dev.</subtitle>
  <link href="https://localghost.dev/feed.xml" rel="self"/>
  <link href="https://localghost.dev/"/>
  <updated>2022-12-14T00:00:00Z</updated>
  <id>https://localghost.dev/</id>
  <author>
    <name>Sophie Koonin</name>
    <email>sophie@localghost.dev</email>
  </author>
  
  <entry>
    <title>Preparing for conferences</title>
    <link href="https://localghost.dev/blog/preparing-for-conferences/"/>
    <updated>2022-12-14T00:00:00Z</updated>
    <id>https://localghost.dev/blog/preparing-for-conferences/</id>
    <content type="html">&lt;p&gt;I&#39;ve been speaking at conferences and meetups on and off for nearly five years now, and a few people have asked me what the process is for preparing a talk. So I thought I&#39;d share how I approach it.&lt;/p&gt;
&lt;p&gt;For me, the talk process is a circle:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/circle-of-talks.png&quot; alt=&quot;A circular flow diagram. The top box says &amp;quot;YEAH LET&#39;S DO A TALK!&amp;quot;, which flows to a box that says &amp;quot;Oh no, I have to prepare the talk.&amp;quot;. That box flows to one that says &amp;quot;This is the worst. I hate this. Why did I agree to this?&amp;quot;. The one after that says &amp;quot;Okay! Ready! Let&#39;s do this!&amp;quot;, and the box after that says &amp;quot;THAT WAS AMAZING! I want to do it again!&amp;quot;. That box points back round to the first box, in a circle.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;It&#39;s the circle of talks.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;It repeats around and around forever. There is &lt;em&gt;always&lt;/em&gt; a point at which I hate my talk and wish I&#39;d never done it, but there is also always a point where I&#39;m having the time of my life. Giving talks is great fun, but it&#39;s also hard work.&lt;/p&gt;
&lt;p&gt;(As a sort-of aside: that hard work is why you should never speak at a conference that isn&#39;t at &lt;em&gt;least&lt;/em&gt; paying for your travel/accommodation or taking you to dinner. Your time is worth money.)&lt;/p&gt;
&lt;p&gt;I&#39;ll break my process down into a set of steps, but the &lt;abbr title=&quot;too long; didn&#39;t read&quot;&gt;tl;dr&lt;/abbr&gt; is: &lt;strong&gt;practise&lt;/strong&gt;. Your audience deserve to watch a talk that you&#39;ve rehearsed and aren&#39;t just making up on the spot. Not only will it show if you haven&#39;t practised, you&#39;re much more likely to run over time as well. The practise part isn&#39;t optional!&lt;/p&gt;
&lt;p&gt;The timelines are super rough, but generally I&#39;d start around 2-2.5 months before the talk. I&#39;ve done talks in shorter timeframes than that, but I wouldn&#39;t recommend it – taking longer means I don&#39;t have to dedicate all of my free time to it, I can space the work out a lot more.&lt;/p&gt;
&lt;h2 id=&quot;initial-planning%3A-about-8-10-weeks-before-the-conference&quot; tabindex=&quot;-1&quot;&gt;Initial planning: about 8-10 weeks before the conference&lt;/h2&gt;
&lt;p&gt;To begin with: identify the overarching theme(s) of the talk. What are the main points I want to convey? No more than 3 or 4.&lt;/p&gt;
&lt;p&gt;I make short-form notes for content ideas – bullet points or post-it notes – jotting down any ideas that come to mind, and sorting them into themes afterwards.&lt;/p&gt;
&lt;p&gt;Previously, I&#39;ve used notecards blue-tacked to the wall with ideas on, so I can shuffle them around and group them.&lt;/p&gt;
&lt;p&gt;At this point, I&#39;ll also do research. Depending on the topic, I might read blog posts, articles, I even read someone&#39;s PhD thesis once. I might pull out some good quotes, or just write down some general ideas from those.&lt;/p&gt;
&lt;h2 id=&quot;content%3A-about-6-8-weeks-before&quot; tabindex=&quot;-1&quot;&gt;Content: about 6-8 weeks before&lt;/h2&gt;
&lt;p&gt;Taking my notes, and writing more detail for each point in a Notion doc. What do I have to say about each of these ideas? Sometimes I spot how they flow into each other, or I might find that one of them doesn&#39;t fit with the others any more after I&#39;ve written some blurb.&lt;/p&gt;
&lt;p&gt;I treat it a bit like a blog post at this point, writing as if I&#39;m talking to someone. It helps me to solidify my ideas as a talk rather than just random sentences.&lt;/p&gt;
&lt;h2 id=&quot;slides%3A-about-4-6-weeks-before&quot; tabindex=&quot;-1&quot;&gt;Slides: about 4-6 weeks before&lt;/h2&gt;
&lt;p&gt;Depending on my needs, I&#39;ll either use Keynote or Google Slides. I prefer Keynote, but if I need to be able to switch to a browser quickly, Google Slides is better. I used Reveal once which was useful for code and embeds, but it took me ages to build the slides so I probably won&#39;t use it very often.&lt;/p&gt;
&lt;p&gt;The first version of the slides always has the notes containing the full sentences from the content planning stage, because I&#39;ll use these for the first few run-throughs.&lt;/p&gt;
&lt;p&gt;If my talk needs any code snippets, I&#39;ll screenshot them from VSCode so they look pretty (or, if I&#39;m using Reveal, I&#39;ll put them straight in the slides).&lt;/p&gt;
&lt;p&gt;This part is also about editing, editing, editing. Especially for shorter talks, it&#39;s as much about what you leave out as it is what you put in.&lt;/p&gt;
&lt;p&gt;Not gonna lie: at this point I start to hate my talk. I&#39;ll come around to it again, but right now I&#39;ll be fed up with it and full of regret. It&#39;s really hard work, and I find making slides pretty tedious. Prepare to have some moments like this – it will get better, though!&lt;/p&gt;
&lt;h2 id=&quot;run-throughs%3A-from-3-4-weeks-before&quot; tabindex=&quot;-1&quot;&gt;Run-throughs: from 3-4 weeks before&lt;/h2&gt;
&lt;p&gt;Early on, I&#39;ll run my slides through with my husband who&#39;s usually pretty good at spotting things that don&#39;t fit, or things I can leave out. I always recommend doing a run-through with a partner, friend or colleague!&lt;/p&gt;
&lt;p&gt;I sometimes run talks at work as well – we have a weekly slot for engineering talks that anyone can give. If you don&#39;t have that, perhaps you could introduce it at your company?&lt;/p&gt;
&lt;p&gt;I&#39;ll do three or four run-throughs a week, after work, where I shut myself in our little office and just deliver the talk to nobody. When we have a dog staying, it&#39;s a bit easier as I can give the talk to him. (He&#39;s never particularly interested in what I have to say, though.)&lt;/p&gt;
&lt;h2 id=&quot;the-week-of-the-conference&quot; tabindex=&quot;-1&quot;&gt;The week of the conference&lt;/h2&gt;
&lt;p&gt;I don&#39;t tend to practise my talk in the days leading up to the conference. Often it&#39;s because I&#39;m travelling or busy in the evening with a speakers&#39; dinner. But I also think it&#39;d just stress me out. By the time the conference arrives, I&#39;ve practised it enough that I feel happy with it.&lt;/p&gt;
&lt;h2 id=&quot;delivering-the-talk&quot; tabindex=&quot;-1&quot;&gt;Delivering the talk&lt;/h2&gt;
&lt;p&gt;I&#39;m not going to go into a huge amount of detail here – the &lt;a href=&quot;https://localghost.dev/blog/things-experienced-speakers-wish-they-d-known&quot;&gt;post I wrote when I was preparing for my first conference in 2018&lt;/a&gt; covers a lot of that ground – but the main thing I&#39;ve learned is that I get super nervous as I&#39;m waiting to go on stage, and then when I get on stage it just goes away and I have a great time.&lt;/p&gt;
&lt;p&gt;If you&#39;ve practised enough, you shouldn&#39;t need to stare at your speaker notes – just glance at them for a prompt. Sometimes you&#39;ll find you won&#39;t need to look at them at all.&lt;/p&gt;
&lt;p&gt;Afterwards, you&#39;ll probably feel amazing and want to do more talks, and thus the cycle starts again. (Conference organisers: I&#39;m at my most suggestible in the week after I&#39;ve just given a talk.)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Building a website like it&#39;s 1999... in 2022</title>
    <link href="https://localghost.dev/blog/building-a-website-like-it-s-1999-in-2022/"/>
    <updated>2022-10-23T00:00:00Z</updated>
    <id>https://localghost.dev/blog/building-a-website-like-it-s-1999-in-2022/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;Note: This is a written version of a talk I gave at State of the Browser 2022 in October 2022!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Motion warning&lt;/strong&gt;: This page contains quite a few animations, but if you have reduced motion turned on, they won&#39;t play.&lt;/p&gt;
&lt;h2 id=&quot;the-web-used-to-be-weirder&quot; tabindex=&quot;-1&quot;&gt;The web used to be weirder&lt;/h2&gt;
&lt;p&gt;I&#39;m on a bit of a mission this year to bring back the spirit of the old web. The creativity and flair of the late 90s and early 2000s. Back then, there were no rules – you put whatever you wanted on a webpage, because it was your space to do as you please.&lt;/p&gt;
&lt;p&gt;And for a whole generation of internet users, having a website was the cool thing to do. It&#39;s just what you did back then. We&#39;re talking pre-social media, pre-web 2.0 – the good old fashioned static personal home page.&lt;/p&gt;
&lt;p&gt;Sites like Geocities, Angelfire, Tripod and Expage offered free static hosting for all, and the number of personal websites boomed. Some hosts offered drag-and-drop website builders so you didn&#39;t even have to learn HTML.&lt;/p&gt;
&lt;p&gt;We might look back on these websites now and laugh – they look ridiculous compared to the sleek and minimalist sites we&#39;re used to nowadays. But I actually think we&#39;ve gone too far in the other direction, and now so many websites look the same. These old personal websites were a reflection of yourself.&lt;/p&gt;
&lt;p&gt;Some of these websites were for family to share photos and updates...&lt;/p&gt;
&lt;figure&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/geocities1.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/geocities1.png&quot; alt=&quot;A brightly coloured website that says &#39;Welcome to Tom &amp; Sherry&#39;s Proud Grandparents page. The Proud Grandparents page was created to show pictures of our grandchildren to family and friends, and an occasional Web surfer. The grandkids, our pride and joy, and their parents have made us very proud. Okay, let&#39;s see the pictures!&#39;&quot; /&gt;
&lt;/picture&gt;
&lt;figcaption&gt;&lt;a href=&quot;https://geocities.restorativland.org/Heartland/Ridge/1217/&quot;&gt;The Proud Grandparents Page&lt;/a&gt;
&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;...while others were full of graphics to share and use on your own site...&lt;/p&gt;
&lt;figure&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/geocities2.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/geocities2.png&quot; alt=&quot;Lisa&#39;s graphics&quot; /&gt;
&lt;/picture&gt;
&lt;figcaption&gt;&lt;a href=&quot;https://www.oocities.org/siliconvalley/haven/1520/&quot;&gt;Lisa&#39;s Graphics&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;...and some were fansites. Look at those frames! I got this screenshot mid-&lt;code&gt;&amp;lt;marquee&amp;gt;&lt;/code&gt;-scroll as well.&lt;/p&gt;
&lt;figure&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/geocities3.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/geocities3.png&quot; alt=&quot;A Final Fantasy fansite&quot; /&gt;
&lt;/picture&gt;
&lt;figcaption&gt;&lt;a href=&quot;https://www.oocities.org/hcdohl/&quot;&gt;Mognet Central&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I played a game a couple of years ago called &lt;a href=&quot;https://www.hypnospace.net/&quot;&gt;Hypnospace Outlaw&lt;/a&gt;, which is a completely bonkers game where you&#39;re a moderator of a version of the 90s web that you access in your sleep. The homepages in this game were directly inspired by Geocities websites (there&#39;s a &lt;a href=&quot;https://noclippodcast.net/episodes/2021/5/22/noclip-pocket-e42-big-winrar-energy-hypnospace-outlaw&quot;&gt;really good episode of Noclip&lt;/a&gt; about it) and it made me so nostalgic. I really recommend it if you haven&#39;t played it already! It really captures the spirit of the time – the personality and weirdness that made these sites so special.&lt;/p&gt;
&lt;figure&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/hypnospace.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/hypnospace.png&quot; alt=&quot;A screenshot from the video game Hypnospace Outlaw, with a website called &#39;Linda&#39;s Library of Weird&#39;.&quot; /&gt;
&lt;/picture&gt;
&lt;figcaption&gt;&lt;a href=&quot;https://www.hypnospace.net/&quot;&gt;Hypnospace Outlaw&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;let&#39;s-bring-back-the-weird&quot; tabindex=&quot;-1&quot;&gt;Let&#39;s bring back the weird&lt;/h2&gt;
&lt;p&gt;I&#39;d love to see this spirit return today – the experimental and fun side of the web. My goal is to show you how we can be just as creative today but using &lt;strong&gt;modern and accessible methods&lt;/strong&gt;. Because, as fun as they were, old websites were a &lt;em&gt;nightmare&lt;/em&gt; for accessibility. We didn&#39;t really use semantic HTML, we used tables for &lt;em&gt;layouts&lt;/em&gt; (instead of, y&#39;know, tabular data), everything was constantly flashing and moving. Luckily for us, the modern web allows us to be just as creative while still considering the user at the other end of the browser.&lt;/p&gt;
&lt;p&gt;So naturally, I built a &lt;a href=&quot;https://sophie-sotb22.neocities.org/&quot;&gt;90s-style website&lt;/a&gt;, with some of my favourite old web tropes. I used as much modern HTML, CSS and JS as I could. Let&#39;s take a look through some of the features and how we might recreate them!&lt;/p&gt;
&lt;figure&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/site.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/site.png&quot; alt=&quot;A screenshot of my 90s-style website&quot; /&gt;
&lt;/picture&gt;
&lt;figcaption&gt;&lt;a href=&quot;https://sophie-sotb22.neocities.org/&quot;&gt;Sophie&#39;s Homepage&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;animated-gifs&quot; tabindex=&quot;-1&quot;&gt;Animated GIFs&lt;/h2&gt;
&lt;p&gt;GeoCities sites were absolutely littered with GIFs. Flames, construction workers, dividers, even animated bullet points. Animations were a lot of fun, and almost an art form to squeeze so much into such a tiny filesize.&lt;/p&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/cameronsworld.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/cameronsworld.png&quot; alt=&quot;A screenshot of cameronsworld.net featuring many space-themed GIFs&quot; /&gt;
&lt;/picture&gt;
&lt;p&gt;This is a screenshot from &lt;a href=&quot;https://cameronsworld.net/&quot;&gt;cameronsworld.net&lt;/a&gt;, which is a beautiful archive of GeoCities GIFs, and an artwork in itself.&lt;/p&gt;
&lt;p&gt;Nowadays it&#39;s easier than ever to put animations on our sites, whether that&#39;s still the humble GIF (internet is so much faster these days), more modern formats like &lt;code&gt;webm&lt;/code&gt; and &lt;code&gt;gifv&lt;/code&gt;, or even SVG animation with CSS or libraries like GreenSock. But we can do better still.&lt;/p&gt;
&lt;p&gt;The standard code to include an image hasn&#39;t changed much since the olden days:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;IMG&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;SRC&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;flames.gif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
 &lt;picture&gt;
    &lt;source srcset=&quot;https://localghost.dev/img/geocities/flames.gif&quot; media=&quot;(prefers-reduced-motion: no-preference)&quot; /&gt;
     &lt;img src=&quot;https://localghost.dev/img/geocities/static/flames.png&quot; alt=&quot;Animated flames&quot; /&gt;
&lt;/picture&gt;
&lt;p&gt;In those days, of course, we wrote all our HTML in capitals because that was what you did for some reason. XHTML, maybe? Anyway, the consequence of this is that everyone sees the GIF whether they like it or not. For people with epilepsy, vestibular disorders, or anything where motion causes sickness, autoplaying GIFs are a big problem. Luckily, wcan fix this today, with something we didn&#39;t have back then!&lt;/p&gt;
&lt;h3 id=&quot;the-prefers-reduced-motion-media-query&quot; tabindex=&quot;-1&quot;&gt;The &lt;code&gt;prefers-reduced-motion&lt;/code&gt; media query&lt;/h3&gt;
&lt;p&gt;Using this media query, we can only play the GIF if the user doesn&#39;t have reduced motion turned on on their computer – so everyone can enjoy our trash website, regardless of their access needs.&lt;/p&gt;
&lt;h3 id=&quot;harnessing-media-queries-with-the-picture-element&quot; tabindex=&quot;-1&quot;&gt;Harnessing media queries with the &lt;code&gt;picture&lt;/code&gt; element&lt;/h3&gt;
&lt;p&gt;The HTML5 &lt;code&gt;picture&lt;/code&gt; element allows us to specify an image, and then potential alternative sources for it.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;source&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;srcset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;underconstruction.gif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;(prefers-reduced-motion: no-preference)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;underconstruction.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Under construction&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;picture&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above code snippet, we&#39;ve got the &lt;code&gt;img&lt;/code&gt; tag as before, but this time it&#39;s showing a &lt;em&gt;still&lt;/em&gt; version of the GIF, which I made by opening the GIF in Preview, pulling out the first frame and saving it as a PNG. The &lt;code&gt;source&lt;/code&gt; tag contains the URL of the GIF, and will only kick in if its &lt;code&gt;media&lt;/code&gt; attribute is satisfied. So if you don&#39;t have reduced motion enabled, the source of the image will be replaced by the animated GIF version. Magic!&lt;/p&gt;
 &lt;picture&gt;
    &lt;source srcset=&quot;https://localghost.dev/img/geocities/consbar.gif&quot; media=&quot;(prefers-reduced-motion: no-preference)&quot; /&gt;
     &lt;img src=&quot;https://localghost.dev/img/geocities/static/consbar.png&quot; alt=&quot;Under construction&quot; /&gt;
&lt;/picture&gt;
&lt;h2 id=&quot;text-effects&quot; tabindex=&quot;-1&quot;&gt;Text effects&lt;/h2&gt;
&lt;p&gt;Remember &lt;code&gt;&amp;lt;marquee&amp;gt;&lt;/code&gt;? It made text scroll across the screen, like ticker tape.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;marquee-wrapper&quot;&gt;&lt;span class=&quot;marquee&quot;&gt;Wheee!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Or those of you with Netscape would have had the infamous &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tag, which makes text blink in and out of view...&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;blink&quot;&gt;This is awful&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ultimately, text effects like this don&#39;t belong in body text. Even if you don&#39;t have any access needs to speak of, it makes reading text really hard. There&#39;s a good reason they were both deprecated.&lt;/p&gt;
&lt;p&gt;Instead, I thought, why not have fun with headers? In days of yore we&#39;d make cool text-based headers in whatever graphics programs we could get our hands on – or even just MS Word. Text with flames, rainbow fonts, you name it.&lt;/p&gt;
&lt;p&gt;These days we can recreate this magic using CSS instead of using an image! And the great news is, because it&#39;s normal text with CSS doing the heavy lifting, it&#39;s still totally accessible.&lt;/p&gt;
&lt;p&gt;For my next trick, I&#39;m drawing inspiration from an OG 90s classic: Microsoft WordArt.&lt;/p&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/wordart-99.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/wordart-99.jpeg&quot; alt=&quot;MS WordArt selection gallery&quot; /&gt;
&lt;/picture&gt;
&lt;h3 id=&quot;wordart%2C-but-make-it-css&quot; tabindex=&quot;-1&quot;&gt;WordArt, but make it CSS&lt;/h3&gt;
&lt;p&gt;While not strictly from the 90s web, WordArt for me harks back to the aesthetic of 90s maximalism, and definitely fits aesthetically with what I&#39;m trying to do.&lt;/p&gt;
&lt;p&gt;I&#39;m going to show you how to recreate two of my classic favourite WordArt styles using modern CSS.&lt;/p&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/wordart-purple.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/wordart-purple.png&quot; alt=&quot;The word &#39;wordart&#39; in Impact font, skewed to point up and to the right, filled in with a purple gradient and a light purple drop shadow&quot; /&gt;
&lt;/picture&gt;
&lt;h4 id=&quot;gradient-fill-text-with-background-clip&quot; tabindex=&quot;-1&quot;&gt;Gradient-fill text with &lt;code&gt;background-clip&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;You can&#39;t colour text with a gradient (yet) in CSS, but you &lt;em&gt;can&lt;/em&gt; give an element a gradient fill &lt;em&gt;background&lt;/em&gt;. Using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip&quot;&gt;&lt;code&gt;background-clip&lt;/code&gt;&lt;/a&gt; property we can control where the background shows. Specifically, we can set &lt;code&gt;background-clip: text&lt;/code&gt; to make the background only show wherever there&#39;s text in the element.&lt;/p&gt;
&lt;p&gt;Then, if we make the actual text transparent, only the gradient background will show through.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;183deg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; #6000CA 10%&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; #CA00CD 70%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Impact&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;purple-wordart-base&quot;&gt;WordArt&lt;/p&gt;
&lt;p&gt;Pretty!&lt;/p&gt;
&lt;p&gt;Then let&#39;s add a &lt;code&gt;transform&lt;/code&gt; property to make it look a bit more like the real deal.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;skewY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;-8deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1.3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0.8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;purple-wordart-base purple-wordart-skewed&quot;&gt;WordArt&lt;/p&gt;
&lt;h4 id=&quot;adding-the-drop-shadow&quot; tabindex=&quot;-1&quot;&gt;Adding the drop shadow&lt;/h4&gt;
&lt;p&gt;Now we need to add the light purple drop shadow. But if we try to use the &lt;code&gt;text-shadow&lt;/code&gt; property, it shows up on top of the text!&lt;/p&gt;
&lt;p class=&quot;purple-wordart-base purple-wordart-skewed purple-wordart-text-shadow&quot;&gt;WordArt&lt;/p&gt;
&lt;p&gt;This is because we&#39;re really looking at the background – the actual text is transparent and sitting on top. If I change the colour of the text to the body colour, you&#39;ll see what I mean:&lt;/p&gt;
&lt;p class=&quot;purple-wordart-base purple-wordart-skewed purple-wordart-text-shadow purple-wordart-text-black&quot;&gt;WordArt&lt;/p&gt;
&lt;p&gt;To get around this, we&#39;ll need a wrapper element that contains the shadow, so it appears behind the text-shaped gradient background.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;purple-wordart-wrapper&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;purple-wordart&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;WordArt&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;ll add a &lt;strong&gt;drop-shadow filter&lt;/strong&gt; to the wrapper element. This adds a drop-shadow the same shape as the element&#39;s children, and because the background is clipped to the text in the child &lt;code&gt;span&lt;/code&gt;, the drop-shadow will follow that shape too!&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.wordart-wrapper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;drop-shadow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;2px 2px 0px &lt;span class=&quot;token function&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;130&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 140&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 251&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 0.8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result:&lt;/p&gt;
&lt;span class=&quot;purple-wordart-wrapper&quot;&gt;
&lt;span class=&quot;purple-wordart-base purple-wordart-skewed&quot;&gt;WordArt&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Uncanny!&lt;/p&gt;
&lt;p&gt;For my second WordArt recreation, I&#39;m bringing back my old childhood favourite – the rainbow one. I remember using this one all over my primary school homework.&lt;/p&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/wordart-rainbow.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/wordart-rainbow.png&quot; alt=&quot;MS Wordart screenshot, the word &#39;WordArt&#39; written in rainbow gradient text with a grey 3D shadow.&quot; /&gt;
&lt;/picture&gt;
&lt;p&gt;We&#39;ve got another gradient fill here, so we&#39;ll use &lt;code&gt;background-clip: text&lt;/code&gt; again to get the same effect, and chuck on a &lt;code&gt;transform&lt;/code&gt; to get the right shape.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;linear-gradient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  90deg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #9c00ff&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #ff0000&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #ff8800&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #ffff00&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #02be02&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #0000ff&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #4f00ff&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  #9c00ff&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;-webkit-background-clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Arial Black&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1.5&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0.6&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;transform-origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; left&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span class=&quot;rainbow constrain-width&quot;&gt;WordArt&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We&#39;ll use a wrapper element to create the shadow again, but this time it&#39;s a little different. This has more of a 3D effect, where the shadow kind of flattens and goes to the left, as if we&#39;re looking at the WordArt from the front.&lt;/p&gt;
&lt;p&gt;CSS can do that!&lt;/p&gt;
&lt;h4 id=&quot;getting-some-perspective&quot; tabindex=&quot;-1&quot;&gt;Getting some perspective&lt;/h4&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.wrapper&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Arial Black&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; inline-block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;perspective&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 150px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;perspective-origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bottom center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use the &lt;code&gt;perspective&lt;/code&gt; property to put us into a kind of &amp;quot;3D mode&amp;quot;. It tells the browser, &amp;quot;act as though I&#39;m standing this far away from the element&amp;quot;. In our case, 150px.&lt;/p&gt;
&lt;p&gt;We then set the &lt;code&gt;perspective-origin&lt;/code&gt; property to determine what position we&#39;re looking at the element from. I want it to seem like we&#39;re in front of it, at the bottom.&lt;/p&gt;
&lt;p&gt;What this will do is change the way that transformations apply to the element, taking into account the perspective to manipulate it along the Z-axis as well as X and Y.&lt;/p&gt;
&lt;p&gt;To create a shadow effect I&#39;ll target the &lt;code&gt;wrapper::before&lt;/code&gt; pseudoelement, and set its content to &amp;quot;WordArt&amp;quot; to mirror the text. This will make the &amp;quot;shadow&amp;quot; text appear behind the rainbow gradient. Then I&#39;ll apply some transformations to skew the &amp;quot;shadow&amp;quot; – that &lt;code&gt;perspective&lt;/code&gt; property on the &lt;code&gt;wrapper&lt;/code&gt; element will change the way it rotates and skews.&lt;/p&gt;
&lt;p&gt;(This one needs a bit more hacky wrangling when you change the font size, and I use fluid typescales so I&#39;m going to embed a Codepen a bit further down instead of rendering it inline!)&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.wrapper::before&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;WordArt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #000&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -2rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;35%&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rotateX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;60deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;skewX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;65deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;scaleY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;2.8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0.9&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;transform-origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bottom right&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Right now, the CSS is hardcoded to have a shadow that says &amp;quot;WordArt&amp;quot;. If we want to use this text style for other things too, how can we dynamically set the shadow text content? With the CSS &lt;code&gt;attr()&lt;/code&gt; function!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;attr()&lt;/code&gt; gets the content of a given attribute for an element. I&#39;ve called mine &lt;code&gt;data-content&lt;/code&gt;. So, in our &lt;code&gt;wrapper::before&lt;/code&gt; rule, &lt;code&gt;content: &#39;WordArt&#39;&lt;/code&gt; becomes &lt;code&gt;content: attr(data-content)&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.wrapper::before&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data-content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #000&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rotateX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;60deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;skewX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;60deg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;scaleY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;2.8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;scaleX&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0.8&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;transform-origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bottom right&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And render the HTML with the attribute:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;rainbow-wrapper&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Rainbow&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;rainbow&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Rainbow&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can write different words!&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;265&quot; data-theme-id=&quot;dark&quot; data-default-tab=&quot;result&quot; data-user=&quot;sophiekoonin&quot; data-slug-hash=&quot;qBKmzmR&quot; data-preview=&quot;true&quot; data-pen-title=&quot;Rainbow text&quot;&gt;
  &lt;span&gt;See the Pen 
    &lt;a href=&quot;https://codepen.io/sophiekoonin/pen/qBKmzmR&quot;&gt;
      Rainbow text&lt;/a&gt; by &lt;a href=&quot;https://codepen.io/sophiekoonin&quot;&gt;@sophiekoonin&lt;/a&gt;
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;It&#39;s not perfect, but I think that looks good enough for a throwback site header!&lt;/p&gt;
&lt;h2 id=&quot;music&quot; tabindex=&quot;-1&quot;&gt;Music&lt;/h2&gt;
&lt;p&gt;In 2001, I had a NeoPets shop. As soon as you loaded the page, you&#39;d be greeted with the dulcet tones of Teenage Dirtbag, in MIDI form.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;EMBED&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;SRC&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mysong.mid&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;HIDDEN&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;yes&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;volume&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;10&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autostart&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Autoplay, naturally, and looping. Definitely hidden, so the music was just &lt;em&gt;there&lt;/em&gt;. But it was super distracting, quite disorientating, and you couldn&#39;t turn it off.&lt;/p&gt;
&lt;p&gt;Modern browsers block autoplaying audio, for good reason. It&#39;s extremely annoying. Thankfully, the HTML5 &lt;code&gt;audio&lt;/code&gt; element gives us a bit more control.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;audio&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-label&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Play music&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;controls&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/soundtrack.webm&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;audio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can still have audio on your website! Just make it &lt;em&gt;opt-in&lt;/em&gt;. If it&#39;s part of the experience you want to create, that&#39;s totally fine, as long as your viewer is okay with it playing.&lt;/p&gt;
&lt;p&gt;&lt;audio aria-label=&quot;Play music&quot; controls=&quot;&quot; src=&quot;https://localghost.dev/extras/soundtrack.webm&quot;&gt;&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;Make sure to add a label – whether external or &lt;code&gt;aria-label&lt;/code&gt; – to tell the user what it does.&lt;/p&gt;
&lt;p&gt;The controls that show up are the browser default – what&#39;s rendered above will look different depending on whether you&#39;re in Chrome, Firefox, etc. But you can use the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_API#controlling_sound&quot;&gt;Web Audio API&lt;/a&gt; to customise the controls, by rendering some pretty buttons and using JavaScript to make them control playing audio.&lt;/p&gt;
&lt;h2 id=&quot;cursor-trails&quot; tabindex=&quot;-1&quot;&gt;Cursor trails&lt;/h2&gt;
&lt;h3 id=&quot;then%3A-dynamic-html&quot; tabindex=&quot;-1&quot;&gt;Then: Dynamic HTML&lt;/h3&gt;
&lt;p&gt;Back in the day, a cursor trail was a real flex. It said, &amp;quot;look at what I can do with JavaScript!&amp;quot;. (Or in my case, what &lt;a href=&quot;https://dynamicdrive.com/&quot;&gt;dynamicdrive.com&lt;/a&gt; could do with JavaScript.)&lt;/p&gt;
&lt;p&gt;This was known as Dynamic HTML: not necessarily a technology in its own right, but a collection of technologies (a bit like we use the term JAMstack now). HTML, CSS and JavaScript – but a very old version of JavaScript. Everything was client-side at this time, because we didn&#39;t have AJAX/client HTTP requests yet. And the implementations differed significantly between the two major browsers of the time, Internet Explorer and Netscape. (This is a period known as the &#39;Browser Wars&#39;, and there&#39;s a &lt;a href=&quot;https://thehistoryoftheweb.com/browser-wars/&quot;&gt;good summary of it on The History Of The Web&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;It led to stuff like this, from a &lt;a href=&quot;https://www.dynamicdrive.com/dynamicindex13/star.htm&quot;&gt;Dancing Stars animated cursor trail&lt;/a&gt;. This cursor adds a trail of seven 3px-wide yellow &amp;quot;stars&amp;quot; (tiny squares) that appear to follow your cursor around. I can&#39;t show you a preview, because the script doesn&#39;t work any more.&lt;/p&gt;
&lt;p&gt;First we had to check whether the script was running in IE, or Netscape, because the implementation would be completely different. In IE, we&#39;d check for the existence of &lt;code&gt;document.all&lt;/code&gt;, a function which returned all the elements in the DOM.&lt;/p&gt;
&lt;p&gt;If this was present, we&#39;d then call &lt;code&gt;document.write&lt;/code&gt; (a function we also &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Document/write&quot;&gt;shouldn&#39;t use any more&lt;/a&gt;) to insert several little 3px &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; squares into the DOM.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;all&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#39;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div id&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;starsDiv&quot;&lt;/span&gt; &lt;br /&gt;  style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;position:absolute;top:0px;left:0px&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&#39;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;xy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; xy &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; xy&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#39;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&quot;position&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;relative&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;3px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;height&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;3px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;background&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;#&lt;span class=&quot;token constant&quot;&gt;FFFF00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    font&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;size&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;2px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;visibility&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;visible&quot;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&#39;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&amp;lt;/div&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Netscape didn&#39;t have &lt;code&gt;div&lt;/code&gt;s, it had &lt;code&gt;LAYER&lt;/code&gt;s. This is basically the same thing with a different name, because browser creators at the time liked causing pain.&lt;/p&gt;
&lt;p&gt;(Side note, this is why some people used to refer to &lt;code&gt;divs&lt;/code&gt; as &amp;quot;div layers&amp;quot; – it encompasses both elements.)&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;LAYER&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;a0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;LEFT&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;10&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;TOP&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;10&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;VISIBILITY&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;SHOW&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;BGCOLOR&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#FFFF00&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;CLIP&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0,0,3,3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;LAYER&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;document.layers&lt;/code&gt; returned something, we knew we were in Netscape, and could do Netscape things. In this case:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;layers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;captureEvents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MOUSEMOVE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The full script is available at &lt;a href=&quot;http://www.dynamicdrive.com/dynamicindex13/star.htm&quot;&gt;DynamicDrive.com&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;now%3A-canvas-and-requestanimationframe&quot; tabindex=&quot;-1&quot;&gt;Now: Canvas and &lt;code&gt;requestAnimationFrame&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://tholman.com/cursor-effects&quot;&gt;Tim Holman&lt;/a&gt; has done the hard work for us here, and recreated 90s-style cursor effects with modern JavaScript and HTML.&lt;/p&gt;
&lt;video controls=&quot;&quot;&gt;
 &lt;source src=&quot;https://localghost.dev/img/blog/build-1999/star-cursor.webm&quot; type=&quot;video/webm&quot; /&gt;
    Video of a cursor trail with many small coloured stars following the cursor.
    &lt;a href=&quot;https://localghost.dev/img/blog/build-1999/star-cursor.webm&quot;&gt;Download the video as .webm&lt;/a&gt;
&lt;/video&gt;
&lt;p&gt;Tim&#39;s cursors use canvas, which is much more performant than rendering individual elements into the DOM. You also get much more fine-grained control over how elements are positioned. Can you imagine trying to render this many stars into the DOM in the old script? Using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API&quot;&gt;canvas API&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame&quot;&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt;&lt;/a&gt; – the function that allows us to batch up animations and efficiently update them before the browser&#39;s next repaint – we can render lots of little stars, making them fade in and out in lovely ways.&lt;/p&gt;
&lt;h3 id=&quot;media-queries-work-in-javascript%2C-too!&quot; tabindex=&quot;-1&quot;&gt;Media queries work in JavaScript, too!&lt;/h3&gt;
&lt;p&gt;Of course, cursor trails mean animations, and not everyone wants to see those. The good news is, we can use media queries in JS, just like we do in CSS and HTML &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; prefersReducedMotionQuery &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;br /&gt;	window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;matchMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;prefers-reduced-motion&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;prefersReducedMotionQuery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matches&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	cursor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By calling &lt;code&gt;window.matchMedia&lt;/code&gt; with the name of the query we&#39;re interested in (&lt;code&gt;prefers-reduced-motion&lt;/code&gt;), we can check the value of the user&#39;s motion settings and only init the cursor if they &lt;em&gt;don&#39;t&lt;/em&gt; have reduced motion enabled.&lt;/p&gt;
&lt;p&gt;You can even add an event listener to the media query, so that when its value changes we can dynamically initialise or destroy the cursor accordingly.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;prefersReducedMotionQuery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;change&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prefersReducedMotionQuery&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matches&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		cursor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		cursor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;webrings&quot; tabindex=&quot;-1&quot;&gt;Webrings&lt;/h2&gt;
&lt;p&gt;In the days before search engines were particularly good, how did you find similar websites? Webrings, of course. A webring is a collection of websites based around a shared interest or topic. Webrings offered a sense of belonging to a community, and gave you a fancy plaque to put on your website.&lt;/p&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/webring.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/webring.png&quot; alt=&quot;A webring plaque for Calvin and Hobbes-themed sites, with links to previous, next and random sites in the ring, and links to the index page.&quot; /&gt;
&lt;/picture&gt;
&lt;p&gt;Each site in the webring would have a plaque like this so you could navigate the ring, and there&#39;d be a backend somewhere (probably written in Perl) that did all the hard work of calculating which site came where in the ring.&lt;/p&gt;
&lt;p&gt;I built my own &lt;a href=&quot;https://sotb22-webring.neocities.org/&quot;&gt;webring for State of the Browser 2022 attendees&lt;/a&gt;, with a Google Sheets backend (for time-saving/live demo reasons) and a Cloudflare Worker on top of that to work out which site to send people to. It checks the value of &lt;code&gt;request.referrer&lt;/code&gt; to see where the call is coming from, looks up that URL in the list of sites, and returns the next or previous one accordingly.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pathname &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchAndParseCsv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; referrer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;referrer&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For something a little more permanent/professional, I recommend checking out &lt;a href=&quot;https://mxb.dev/blog/webring-kit/&quot;&gt;Max Böck&#39;s webring kit&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;guestbooks&quot; tabindex=&quot;-1&quot;&gt;Guestbooks&lt;/h2&gt;
&lt;p&gt;Last but not least, the humble guestbook! In the days before social media, this was how we showed our appreciation for webmasters. Rather than just building a guestbook I thought I&#39;d do something a little different for the talk. It&#39;s a guestbook all right, but it&#39;s powered by Twitter!&lt;/p&gt;
&lt;figure&gt;
&lt;picture&gt;
&lt;source srcset=&quot;https://localghost.dev/img/blog/build-1999/guestbook.webp&quot; type=&quot;image/webp&quot; /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/build-1999/guestbook.png&quot; alt=&quot;A screenshot of my guestbook, with messages from conference attendees.&quot; /&gt;
&lt;/picture&gt;
&lt;figcaption&gt;&lt;a href=&quot;https://sophie-sotb22.neocities.org/guestbook&quot;&gt;View the guestbook&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Instead, I used a technology called &lt;strong&gt;webmentions&lt;/strong&gt;: a protocol to notify a website when someone else links to them, such as on their own website or on Twitter. Webmentions are collected as a feed (a bit like RSS) and associated with a domain name or host. I put meta tags in the &lt;code&gt;head&lt;/code&gt; of my site to indicate that I&#39;m on the lookout for webmentions.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://webmention.io/&quot;&gt;webmention.io&lt;/a&gt; to collect those webmentions for me, though it&#39;s totally possible to set up your own server to do so. On this website (localghost) I collect webmentions at build time and publish them underneath the pages, but on the demo website for this talk I have a client-side script to fetch mentions as I wanted to be able to demo them live.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://brid.gy/&quot;&gt;brid.gy&lt;/a&gt; to collect mentions from Twitter and send them to &lt;a href=&quot;http://webmention.io/&quot;&gt;webmention.io&lt;/a&gt;, and then my site queries &lt;a href=&quot;http://webmention.io/&quot;&gt;webmention.io&lt;/a&gt; to get the feed of mentions.&lt;/p&gt;
&lt;h2 id=&quot;go-forth-and-build-weird-stuff!&quot; tabindex=&quot;-1&quot;&gt;Go forth and build weird stuff!&lt;/h2&gt;
&lt;p&gt;The web is an amazing platform brimming with opportunities to be creative and experimental. I&#39;d love to see what you build – if you mention this page on your own site or Twitter, the webmentions will appear below, or tag me &lt;code&gt;@type__error&lt;/code&gt;!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Everything I googled in a week as a senior software engineer</title>
    <link href="https://localghost.dev/blog/everything-i-googled-in-a-week-as-a-senior-software-engineer/"/>
    <updated>2022-10-15T00:00:00Z</updated>
    <id>https://localghost.dev/blog/everything-i-googled-in-a-week-as-a-senior-software-engineer/</id>
    <content type="html">&lt;p&gt;Three years ago I wrote a post called &lt;a href=&quot;https://localghost.dev/blog/everything-i-googled-in-a-week-as-a-professional-software-engineer/&quot;&gt;Everything I googled in a week as a professional software engineer&lt;/a&gt;, and it clearly resonated with people, because it went pretty viral. It &lt;em&gt;still&lt;/em&gt; gets most of the pageviews on this website.&lt;/p&gt;
&lt;p&gt;Well, a lot has changed in three years: I got promoted and I&#39;m now a senior engineer and lead the web engineering discipline at &lt;a href=&quot;https://monzo.com/&quot;&gt;Monzo&lt;/a&gt;. But one thing hasn&#39;t changed: I still google a lot, every single day. Here&#39;s what I googled in a week, 2022 edition.&lt;/p&gt;
&lt;p&gt;Obvious disclaimer: this is slightly edited as I&#39;ve removed most of the non-work-related ones.&lt;/p&gt;
&lt;p&gt;Some of these search terms might make you laugh and think &amp;quot;how did you not know that?&amp;quot;. Well, there are several reasons you might not know something (choose all that apply):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you&#39;ve never used it before&lt;/li&gt;
&lt;li&gt;you&#39;ve used it before but can&#39;t remember&lt;/li&gt;
&lt;li&gt;it&#39;s changed since the last time you used it&lt;/li&gt;
&lt;li&gt;you&#39;re tired&lt;/li&gt;
&lt;li&gt;you&#39;re distracted&lt;/li&gt;
&lt;li&gt;you&#39;re human&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More than ever, we&#39;re constantly surrounded by new information. It&#39;s impossible to remember everything all of the time.&lt;/p&gt;
&lt;p&gt;I hope this makes you feel a bit better if you ever feel bad that you have to google something &amp;quot;obvious&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;monday&quot; tabindex=&quot;-1&quot;&gt;Monday&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;slack channel bookmarks&lt;/em&gt; – trying to find some documentation on where to find channel bookmarks on mobile, as my friend couldn&#39;t find them.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;carbonara&lt;/em&gt; – my manager made the very lofty claim in standup that his carbonara was the best, so I googled a picture to make a &amp;quot;carbonara king&amp;quot; emoji of him&lt;/p&gt;
&lt;p&gt;&lt;em&gt;directory tree cli&lt;/em&gt; - how to render a directory tree in a CLI&lt;/p&gt;
&lt;p&gt;&lt;em&gt;react-toastify&lt;/em&gt; - a useful notification library&lt;/p&gt;
&lt;p&gt;&lt;em&gt;anchor dataset&lt;/em&gt; - accessing data attributes in JS&lt;/p&gt;
&lt;p&gt;&lt;em&gt;mdn element dataset&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;waitfornextupdate&lt;/em&gt; - trying to remember if this testing-library function was just for hooks. (It is.)&lt;/p&gt;
&lt;p&gt;The next few are a direct result of the fact that in JS you still can&#39;t automatically download a file in a cross-browser way without creating an anchor element. There&#39;s the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/downloads/download&quot;&gt;downloads API&lt;/a&gt;, but Safari doesn&#39;t support it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;jest how to test detached elements&lt;/em&gt; – &lt;code&gt;jest-dom&lt;/code&gt; can only see what&#39;s in the DOM under test, so if an element is detached from the DOM, it&#39;s not going to be able to test it. But this didn&#39;t immediately occur to me.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;document.createElement(&#39;a&#39;)&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;document.createElement(&#39;a&#39;)&lt;/code&gt; detached&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;react-hook-form&lt;/em&gt; - we&#39;re trying to add this to some of our web properties, as they don&#39;t have any form management and &lt;code&gt;react-hook-form&lt;/code&gt; is a really nice abstraction.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;spread types may only be created from object types&lt;/em&gt; - I kept getting this error and I couldn&#39;t work out why, and it turns out we had an old version of &lt;code&gt;react-hook-form&lt;/code&gt; installed in a different app (just monorepo things) which had different return types&lt;/p&gt;
&lt;p&gt;&lt;em&gt;react-hook-form &amp;quot;spread types may only be created from object types&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;tuesday&quot; tabindex=&quot;-1&quot;&gt;Tuesday&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;slack channel links in API&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;gilts&lt;/em&gt; – they were &lt;a href=&quot;https://www.ftadviser.com/investments/2022/10/10/boe-to-expand-gilt-intervention-as-obr-confirms-forecast-date/&quot;&gt;in the news&lt;/a&gt; and I didn&#39;t actually know what they were.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;js accessing nested object key&lt;/em&gt; – I momentarily couldn&#39;t remember whether you could access nested object keys like &lt;code&gt;myObj[&#39;key1.key2&#39;]&lt;/code&gt;. (you can&#39;t, because the entire string is interpreted as one key)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;intensifies emoji maker&lt;/em&gt; – I went with &lt;a href=&quot;https://makeemoji.com/&quot;&gt;MakeEmoji&lt;/a&gt; which has a pleasing number of options&lt;/p&gt;
&lt;p&gt;&lt;em&gt;modal accessibility&lt;/em&gt; – I was having a discussion with someone about why modals aren&#39;t accessible. It turns out there is some nuance to it, and that they aren&#39;t necessarily completely inaccessible, but they require a fair bit of work to make them accessible.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;modal window accessibility&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I hope you can feel the frustration in the next few search queries, in which I struggle with Storybook and then find that my problem isn&#39;t actually documented. I knew that there was a world in which you can write JSDoc comments above a component, and have them show up in Storybook docs, because we did that at my previous job. The docs don&#39;t seem to mention this at all, and it wasn&#39;t working for some reason. It turns out that it doesn&#39;t work with default export components, for some reason, but this isn&#39;t documented anywhere.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;storybook docs markdown comments&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;storybook story description&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;storybook docs&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;storybook comments&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;storybook comment&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;storybook JSdoc&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;wednesday&quot; tabindex=&quot;-1&quot;&gt;Wednesday&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;mark hoppus&lt;/em&gt; – I mentioned that I was trying to get blink-182 tickets (I failed) and we were debating how old they are now.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;lofi girl&lt;/em&gt; – during retro we put music on while people are writing their Retrium tickets, and I thought this was the appropriate vibe.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;apollo query oncompleted&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;useLazyQuery&lt;/em&gt; – trying to figure out if this returns the return value, or &lt;code&gt;void&lt;/code&gt;. Turns out the latest version returns the return value, and the version we&#39;re on doesn&#39;t :(&lt;/p&gt;
&lt;p&gt;&lt;em&gt;sentry github&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&#39;RequestSessionStatus&#39; is not exported from &#39;@sentry/types&#39;&lt;/em&gt; – this turned out to not be a problem with the Sentry lib, but actually a yarn.lock mismatch (just monorepo things).&lt;/p&gt;
&lt;h2 id=&quot;thursday&quot; tabindex=&quot;-1&quot;&gt;Thursday&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;document.write&lt;/em&gt; – I knew this was deprecated, but I wanted to find something to back up my PR comment.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;apollo server request size&lt;/em&gt; – Getting 412s from our apollo server and trying to figure out how to bump the max request size.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;apollo-server-koa&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;apollo server request size site:stackoverflow.com&lt;/em&gt; - a useful tip for googling is that you can restrict searches to a particular site using the &lt;code&gt;site:&lt;/code&gt; param.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;mdn element dataset&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;open new window and set inner html&lt;/em&gt; – trying to find a suitable replacement for &lt;code&gt;document.write&lt;/code&gt; for the person who requested it. We went for &lt;code&gt;window.open()&lt;/code&gt; and &lt;code&gt;myWindow.document.documentElement.innerHTML = myHtml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;mock clock golang&lt;/em&gt; – figuring out the best way to mock the &lt;code&gt;time.Now()&lt;/code&gt; function in Go. There are various ways of doing it across our codebase, I wasn&#39;t sure which one was the most up-to-date way, but I figured it out eventually.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;graphql server request entity too large&lt;/em&gt; – still trying to fix the apollo server request limit&lt;/p&gt;
&lt;p&gt;&lt;em&gt;doggo ipsum&lt;/em&gt; – my &lt;a href=&quot;https://doggoipsum.com/&quot;&gt;favourite ipsum generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;apollo server body parser config&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;apollo server body parser config koa&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;koa&lt;/em&gt; - I finally realised we need to set the body parser config on the server itself, not the apollo-server wrapper.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;koa request size&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;britney spears albums&lt;/em&gt; – trying to find as many Britney track titles as possible to cram into a pun-filled gratitude post for my colleague who helped us out.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ronseal&lt;/em&gt; – I like to google pictures of &lt;a href=&quot;https://ronseal.com/&quot;&gt;Ronseal&lt;/a&gt; and put them in PR descriptions when the title describes exactly what the PR does (i.e. it &lt;a href=&quot;https://en.wikipedia.org/wiki/Does_exactly_what_it_says_on_the_tin&quot;&gt;does what it says on the tin&lt;/a&gt;). I think I got this habit from &lt;a href=&quot;https://b3ta.com/dictionary/define/Ronseal/&quot;&gt;b3ta&lt;/a&gt; back in the day.&lt;/p&gt;
&lt;h2 id=&quot;friday&quot; tabindex=&quot;-1&quot;&gt;Friday&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;read a symbolic link&lt;/em&gt; – I&#39;m so shit at symbolic links lolol&lt;/p&gt;
&lt;p&gt;&lt;em&gt;npm service status&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;apollo async oncompleted&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;window.history&lt;/em&gt; – looking for the arguments for &lt;code&gt;history.push&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I think the next few are particularly amusing given that I &lt;em&gt;literally gave a conference talk&lt;/em&gt; on &lt;code&gt;redux-saga&lt;/code&gt; in 2018, but it&#39;s been so long since I touched any code containing sagas that I completely forgot how they work:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;saga execute non-saga function&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;saga execute non-redux function&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;redux-saga effects&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;More ipsum generators, because my colleagues enjoyed doggo ipsum:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://cupcakeipsum.com/&quot;&gt;cupcake ipsum&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://www.loremipsums.nl/lorem-ipsum-origineel/veggie-ipsum/&quot;&gt;veggie ipsum&lt;/a&gt;&lt;/em&gt; – I &lt;em&gt;love&lt;/em&gt; that I also googled this in the previous post as well, I promise it&#39;s a coincidence&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ts-command-line-args&lt;/em&gt; - onto some CLI building now!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;node.js interactive shell&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;node.js interactive shell select&lt;/em&gt; – I was looking for a CLI library that lets you select different options with the arrow keys. I found &lt;a href=&quot;https://github.com/SBoudrias/Inquirer.js&quot;&gt;inquirer.js&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;types/inquirer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ts-command-line-args&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;should you symlink from destination&lt;/em&gt; – I can never remember what order to do symlinks in&lt;/p&gt;
&lt;p&gt;&lt;em&gt;TS2464&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;next-images&lt;/em&gt; - checking that some of our plugins are still relevant.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;nextjs document&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;react-hook-form radio buttons&lt;/em&gt; - sometimes you just need a good example. Turns out it was easier than I thought, and I just needed to forward a ref to our radio button component.&lt;/p&gt;
&lt;h2 id=&quot;looking-back&quot; tabindex=&quot;-1&quot;&gt;Looking back&lt;/h2&gt;
&lt;p&gt;You might say &amp;quot;well, you googled fewer things this week than you did that week in 2019!&amp;quot;. For one thing, I have more meetings now than I did back then. I&#39;m in a different team, working on different things.&lt;/p&gt;
&lt;p&gt;It also depends from week to week what I&#39;m working on; last week I spent a lot of time building data export in Go, and so my search history was full of frustrated queries like &lt;code&gt;golang readseeker from buffer&lt;/code&gt; and &lt;code&gt;create a file from string golang&lt;/code&gt;. (I still help out on backend tickets when it&#39;s needed.)&lt;/p&gt;
&lt;p&gt;Some of the stuff I googled back then I can remember how to do without looking it up now, but some of it I definitely can&#39;t (e.g. I still can&#39;t get my brain to retain some more complex CSS grid things). For example, I&#39;d 100% still have to google all of these from the last post:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;whitespace regex&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;regex not letter&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;js date&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;grid minmax&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There you have it – I still google loads of stuff. To finish, I&#39;ll leave you with what I said in the post from 2019:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What I&#39;m trying to show with all this is that you can do something 100 times but still not remember how to do it off the top of your head. Never be ashamed of googling, even if it seems like the most basic thing you&#39;re looking up.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
  
  <entry>
    <title>When going back doesn&#39;t mean going backwards</title>
    <link href="https://localghost.dev/blog/when-going-back-doesn-t-mean-going-backwards/"/>
    <updated>2022-08-27T00:00:00Z</updated>
    <id>https://localghost.dev/blog/when-going-back-doesn-t-mean-going-backwards/</id>
    <content type="html">&lt;p&gt;Hey internet! Last time we spoke, I was in a bad place. Burnt out and off work. Well, in May I made the decision to quit my job at the startup after 7 months, and in June I accepted a new job at... my old job. So I&#39;m back at Monzo, &lt;a href=&quot;https://twitter.com/type__error/status/1554859381875003393&quot;&gt;working at the bank&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You don&#39;t often hear about people going back to jobs they&#39;ve left. It turns out it&#39;s really nice, because you already have friends there and people are happy to see you come back. For me, leaving Monzo was always a pull, not a push: this exciting opportunity came up at &lt;a href=&quot;http://incident.io/&quot;&gt;incident.io&lt;/a&gt;, and I thought I&#39;d give it a go.&lt;/p&gt;
&lt;p&gt;Accepting that a job isn&#39;t working out can be a difficult pill to swallow. I really wanted to make it work, and I think a lot of the burnout I experienced was because it wasn&#39;t the right job for me. Being part of an early-stage startup seemed to be the hot thing to do, and this particular one is run by people I really respect. I had to come to terms with the fact that early-stage startups aren&#39;t really my cup of tea: I realised that I work best in bigger organisations, where I can take more of a leadership role and do larger-scale work that improves things for the people around me.&lt;/p&gt;
&lt;p&gt;I also realised that I didn&#39;t really want to market myself as a full-stack developer any more. The week I got back from my time off, I went to &lt;a href=&quot;https://heypresents.com/conferences/2022&quot;&gt;All Day Hey&lt;/a&gt; in Leeds and I left with this incredible sense of clarity. It reminded me of everything I love about the web. And it made me finally accept the fact that, well, I don&#39;t like backend development very much.&lt;/p&gt;
&lt;p&gt;See, I&#39;ve always had a degree of internalised self-doubt about being web developer, as if it means I&#39;m somehow not a &amp;quot;proper&amp;quot; developer for not being a backend dev. (Never mind that if anyone said that to me, I&#39;d give them an earful.)&lt;/p&gt;
&lt;p&gt;I&#39;ve been building websites for over 20 years, but when I learnt Java during my masters I thought I&#39;d become a backend dev, because that was what Real Programmers do. After my career took me onto a React/Node project at John Lewis, then joining Monzo as a full-stack web engineer, I clung on to the &amp;quot;full-stack&amp;quot; title. Doing backend too meant that I could still consider myself a Serious Dev while still doing the fun web stuff as well.&lt;/p&gt;
&lt;p&gt;That &amp;quot;fun web stuff&amp;quot; included teaching people about accessibility, improving testing, architecting and building out brand new web apps, upgrading countless libraries, implementing microfrontends in a large React monolith, architecting and building component libraries. It involved becoming recognised as a conference speaker, and being invited to conferences about web development in the UK and abroad. It involved being promoted to Web Discipline Lead at Monzo, where I could be the &amp;quot;public face&amp;quot; of web internally at Monzo, defining and introducing engineering standards across the organisation. But it&#39;s okay because I was still doing backend engineering to make me a Proper Developer...!&lt;/p&gt;
&lt;p&gt;Oh dear.&lt;/p&gt;
&lt;p&gt;At All Day Hey, when I watched Andy Bell&#39;s brilliant talk &lt;a href=&quot;https://heypresents.com/talks/be-the-browser-s-mentor-not-its-micromanager&quot;&gt;Be The Browser&#39;s Mentor, Not Its Micromanager&lt;/a&gt;, I was &lt;em&gt;so excited&lt;/em&gt; by what I&#39;d just seen. I hadn&#39;t felt that much enthusiasm about what I did for months – sorry, but the introduction of Generics in Go doesn&#39;t hold a candle to modern CSS utility functions and what they mean for responsive website design 💅&lt;/p&gt;
&lt;p&gt;I realised that I hadn&#39;t been doing enough of what I love, and I LOVE THE WEB. Web development is awesome. (And I &lt;em&gt;am&lt;/em&gt; a Proper Developer.) Sadly the company&#39;s engineering needs didn&#39;t really match up with my specialism.&lt;/p&gt;
&lt;p&gt;The week after, I handed in my notice. I was sad, but we all agreed it was the right thing, and everyone was super supportive.&lt;/p&gt;
&lt;p&gt;Ultimately, the 7 months at the startup were well spent: this experience helped me to understand what I really wanted for my career – and I realised it was pretty much what I was doing before. Plus, I met some excellent people, and learnt a lot from them. (I also built a pretty sweet component library, and I hope they&#39;re getting good use out of it.)&lt;/p&gt;
&lt;p&gt;This isn&#39;t a cautionary tale: it&#39;s a reassurance that it&#39;s okay to make the wrong decision. The wrong decision is not necessarily a bad decision, and going back to my old job isn&#39;t a backwards step – I picked up where I left off and I&#39;m heading in the same direction I was when I left. I don&#39;t have any regrets about the past year – I learnt a lot, I have a lot of love for the folks at &lt;a href=&quot;http://incident.io/&quot;&gt;incident.io&lt;/a&gt;, and they&#39;re building something amazing. It just wasn&#39;t the right thing for me, and that&#39;s okay.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Burnout, a cautionary tale (and a plea to take a break)</title>
    <link href="https://localghost.dev/blog/burnout-a-cautionary-tale-and-a-plea-to-take-a-break/"/>
    <updated>2022-04-16T00:00:00Z</updated>
    <id>https://localghost.dev/blog/burnout-a-cautionary-tale-and-a-plea-to-take-a-break/</id>
    <content type="html">&lt;p&gt;It&#39;s Easter and I&#39;m off work til the end of the month. It was originally just going to be for a few days as I&#39;d used up most of my holiday already, but after I burst into tears at my manager on Wednesday during our 1:1 when he asked me how a project was going, he suggested I might need a bit longer (good manager).&lt;/p&gt;
&lt;p&gt;I really love my job, I love what I do and I love my colleagues. Before the pandemic - and even during it - I threw myself at my work and learnt as much as I possibly could. And from my beginnings learning Java at university, I learnt JavaScript, then React, then Kotlin. Then I moved onto Monzo and picked up Go. I was Good At Things.&lt;/p&gt;
&lt;p&gt;But for the last few months I&#39;ve found that nothing goes in any more. I can&#39;t absorb new information. People have to explain things several times, and my head feels like it&#39;s full of cotton wool. It makes me feel like an idiot. I&#39;d tell myself I was better than this and I needed to just &lt;em&gt;focus&lt;/em&gt; and maybe I was just getting too distracted.&lt;/p&gt;
&lt;p&gt;When I sit down to do web development, it&#39;s like autopilot and I can steam through it, but anything backend seems to be beyond my capability at the moment. Which is frustrating because there&#39;s a lot of backend development in my current role. I used to love it, what gives? I&#39;m out of practice, sure, but it&#39;s like there&#39;s this barrier that stops me from learning anything new.&lt;/p&gt;
&lt;p&gt;Weeeelllll, now I can put a name to that barrier: burnout. FFS.&lt;/p&gt;
&lt;p&gt;Was it my job, I thought? Was I unhappy in my new role? Well, the thought of going back to my old job didn&#39;t make me feel any better. Nor would going anywhere else. Switching to a new job certainly came with the stress of starting from scratch, and working at a startup is a whole other vibe. But ultimately I do like it, and I knew that in any other circumstances I&#39;d be thriving there.&lt;/p&gt;
&lt;p&gt;So let&#39;s look at everything else.&lt;/p&gt;
&lt;p&gt;The last two years have been among the worst of my life. I&#39;m sure they have for many of you, too. I spent so long unable to do some of the things I love, in a lockdown that could have been a lot shorter if our government wasn&#39;t equal parts inept and corrupt. The world is permanently on fire. I had to take a hiatus from reading the news because it was all too much. Plus I&#39;ve had my own depression to contend with and other family things that I won&#39;t go into, which have made everything that much more difficult.&lt;/p&gt;
&lt;h2 id=&quot;don&#39;t-be-like-me%2C-please-take-a-break&quot; tabindex=&quot;-1&quot;&gt;Don&#39;t be like me, please take a break&lt;/h2&gt;
&lt;p&gt;I wrote a blog post in 2020 about &lt;a href=&quot;https://localghost.dev/blog/give-yourself-a-break-lessons-from-burnout/&quot;&gt;giving yourself a break&lt;/a&gt;, but apparently I didn&#39;t take enough of my own advice.&lt;/p&gt;
&lt;p&gt;For someone who goes on about work-life balance and mental health, I&#39;m not actually very good at practising what I preach. (Surprise.)&lt;/p&gt;
&lt;p&gt;I&#39;d figured that because I never work late or out-of-hours, I&#39;d avoid burnout. But that&#39;s just one contributing factor.&lt;/p&gt;
&lt;p&gt;And when I take time off I usually feel like I need to fill it with Stuff. Projects, outings, day trips, holidays. Making the most of your time off. I&#39;ve never been good at doing &lt;em&gt;nothing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A couple of weeks ago I was ill with a mystery virus that seemed an awful lot like covid but was negative on all the tests, and a few mornings that week I&#39;d woken up feeling loads better and started working. By the afternoon I had to give up and down tools again because I felt so ill.&lt;/p&gt;
&lt;p&gt;I thought I&#39;d be making myself useful by working when I felt better, but instead I was being more disruptive than anything else. People didn&#39;t know if I was going to finish the thing I was working on, so they didn&#39;t pick it up, and stuff kind of stopped and started. If I&#39;d just taken the rest of the week and shoved my laptop in a cupboard, I&#39;d have actually got the rest I needed.&lt;/p&gt;
&lt;h2 id=&quot;heed-my-words%2C-adventurer!&quot; tabindex=&quot;-1&quot;&gt;Heed my words, adventurer!&lt;/h2&gt;
&lt;p&gt;I am not writing this post to garner sympathy, I&#39;m sharing because I want to be transparent about the fact that this doesn&#39;t &amp;quot;just happen to other people&amp;quot;. I have been running on fumes for months, and it culminated in me crying in a coffee shop in front of my extremely kind and patient manager.&lt;/p&gt;
&lt;p&gt;If you are feeling like things are harder these days, that&#39;s because they are. If you&#39;re not functioning at 100% and find you&#39;re pushing yourself even harder because of it, please stop. I want you to take a minute to check on yourself. Are you okay? Do you need to take some time off?&lt;/p&gt;
&lt;p&gt;(Also, never be ashamed of crying at work. We&#39;ve all been there. Normalise crying at work. It&#39;s a sign that something is wrong, but the crying itself isn&#39;t anything to be ashamed of.)&lt;/p&gt;
&lt;p&gt;I believe in working hard, but I do not believe in working hard at the expense of your physical and mental health.&lt;/p&gt;
&lt;p&gt;So now I&#39;m on a break until May, and I&#39;m going to go for walks, go birdwatching, do jigsaws, plant some vegetables in the allotment, play video games and make a big fuss of my father-in-law&#39;s dog Boris.&lt;/p&gt;
&lt;p&gt;If you&#39;ve got some holiday, please take it.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/boris.JPG&quot; alt=&quot;A brown and white Staffordshire bull terrier lies on the sofa with his limbs extended. He is greying round the muzzle, and has what looks like a smile. He&#39;s lying next to a PS5 controller.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;My plans.&lt;/figcaption&gt;&lt;/figure&gt;
</content>
  </entry>
  
  <entry>
    <title>Start at the beginning: the importance of learning the basics</title>
    <link href="https://localghost.dev/blog/start-at-the-beginning-the-importance-of-learning-the-basics/"/>
    <updated>2022-01-02T00:00:00Z</updated>
    <id>https://localghost.dev/blog/start-at-the-beginning-the-importance-of-learning-the-basics/</id>
    <content type="html">&lt;p&gt;If you&#39;re an early-career developer, Twitter is overflowing with people tweeting great tips -- and some absolute rubbish -- about how to improve your skills and become better at your job. I&#39;ve spoken to more than a few people who&#39;ve asked me, &amp;quot;how should I start?&amp;quot;. And I tell everyone the same thing: &lt;strong&gt;learn the basics.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;However you learn best -- book, video, interactive tutorial -- &lt;strong&gt;you need to learn HTML and CSS  before you can call yourself a web developer&lt;/strong&gt;. I don&#39;t think that&#39;s a particularly controversial statement.&lt;/p&gt;
&lt;p&gt;Once you start getting into interactive website territory, with API calls and fancy stuff, that&#39;s where you need JavaScript (JS) knowledge. More specifically, &lt;strong&gt;vanilla JS&lt;/strong&gt;: plain JS with no additional frameworks or plugins. The JS that your browser understands without having to do any pre-processing. It makes working with frameworks a whole lot easier, and it&#39;ll help you to know when &lt;em&gt;not&lt;/em&gt; to use a framework (and avoid making users download massive JS bundles when all you need is a tiny bit of code). Browsers have come a &lt;em&gt;long&lt;/em&gt; way, and a lot of what we might have needed to use &lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt; to do even just a couple of years ago is now natively supported in the big 4 browsers (Chrome, Firefox, Edge and Safari).&lt;/p&gt;
&lt;h2 id=&quot;where-i-started&quot; tabindex=&quot;-1&quot;&gt;Where I started&lt;/h2&gt;
&lt;p&gt;I started building websites when I was ten years old. I was lucky enough to grow up with computers in the house, and had a book called &amp;quot;Make Your Own Webpage&amp;quot; which taught me the basics of HTML (as it was in 1999). You can even &lt;a href=&quot;https://archive.org/details/makeyourownwebpa00pede&quot;&gt;read it on archive.org&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/make-your-own-webpage.jpg&quot; alt=&quot;The front cover of the book &#39;Make Your Own Webpage, a guide for kids, from the Creators of Internet for Kids!&#39; by Ted Pedersen and Francis Moss. The cover features a CRT monitor and beige desktop computer with a computer mouse that looks like a real mouse, on a mousemat that looks like a slice of cheese.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;A few years later, I built my personal website full of webrings and stolen gifs with the help of &lt;a href=&quot;http://lissaexplains.com/&quot;&gt;Lissa Explains It All&lt;/a&gt;, the ultimate HTML bible for anyone on the internet in 2002. (It&#39;s still online today, but pretty out of date!)&lt;/p&gt;
&lt;p&gt;Fast-forward through LiveJournal, Greymatter, Blogger, Wordpress, pretty much any pre-2010 blogging site/CMS framework you can imagine -- and now I&#39;m building websites (or web apps) as my actual job, using React. A fair bit has changed -- but not as much as you&#39;d think.&lt;/p&gt;
&lt;p&gt;I&#39;m telling you this because I &lt;strong&gt;still use the knowledge I learned when I was ten&lt;/strong&gt; every day at work. HTML tags are still HTML tags, they&#39;re still written much the same way -- HTML5 got rid of some of the ones I used to use (pour one out for &lt;code&gt;marquee&lt;/code&gt;) and introduced some new ones, but the fundamentals are still the same. Most of the websites that I built in 1999 would still render today.&lt;/p&gt;
&lt;p&gt;My first professional web development experience was a React app. I&#39;d just about heard of React at that point, but I&#39;d recently learned JavaScript and Node.JS which gave me a good foundation to build upon. I brushed up on some newer CSS concepts I hadn&#39;t used, but all the HTML and CSS of my past web adventures came right back. The good thing about this stuff is that it&#39;s all over the internet, so when you inevitably forget how to do something really simple, you can just google it.&lt;/p&gt;
&lt;h2 id=&quot;frameworks-serve-a-purpose%2C-but-they-don&#39;t-replace-the-basics&quot; tabindex=&quot;-1&quot;&gt;Frameworks serve a purpose, but they don&#39;t replace the basics&lt;/h2&gt;
&lt;p&gt;People might tell you to learn React, because everyone&#39;s using React. I write React every day, and a lot of that is just JavaScript and HTML. If you don&#39;t know either of those, you&#39;re going to have a bad time -- or you&#39;ll end up with highly specialised framework-specific knowledge that will bite you later on when you need to use a different framework. Lots of people are using React, sure -- but a lot more people aren&#39;t. A far, far larger proportion of the web runs on Wordpress, for example. Lots of sites are built in plain old HTML, CSS and JS, like the &lt;a href=&quot;https://emojinator.fun/&quot;&gt;emojinator&lt;/a&gt; and this very website you&#39;re reading.&lt;/p&gt;
&lt;p&gt;Besides, in a few years we&#39;ll probably using the newest, hottest framework and React will become the butt of jokes in the way that Angular has. Or you&#39;ll land a job at your dream company and find they use Vue, or some state management library from 2011 which has no documentation. I&#39;m not saying don&#39;t learn React -- I&#39;m saying learn the basics first, so you can apply your knowledge to all manner of other frameworks and tools.&lt;/p&gt;
&lt;p&gt;The same goes for CSS. There was a particularly bad take floating around Twitter recently where someone suggested that junior developers should skip CSS and just learn &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt;. I have used Tailwind, and I dislike it for various reasons, but I can see use cases for it such as quick prototyping and a set of nice defaults in the absence of specialist design. However, it doesn&#39;t and shouldn&#39;t &amp;quot;replace&amp;quot; CSS. Tailwind is literally just a library of someone else&#39;s CSS classes, except you have a separate class for nearly every rule instead of writing all your rules together in reusable classes for each component. Instead of learning hundreds of class names, why not learn the CSS rules they translate to and write one CSS class with multiple selectors? When you go to your next job or project and find they don&#39;t use Tailwind, it&#39;ll slow you down as you need to learn the selectors all over again.&lt;/p&gt;
&lt;h2 id=&quot;recommended-resources&quot; tabindex=&quot;-1&quot;&gt;Recommended resources&lt;/h2&gt;
&lt;p&gt;I&#39;d recommend going in the order HTML, CSS, JS. That way, you can build something in HTML, add CSS to it as you learn it, and finally soup it up with your new-found JS knowledge.&lt;/p&gt;
&lt;p&gt;If you&#39;re a backend engineer who only touches the frontend occasionally, you don&#39;t need to go too deep -- but you need a decent grasp of which element does what (&lt;a href=&quot;https://localghost.dev/0221/06/the-right-tag-for-the-job-why-you-should-use-semantic-html/&quot;&gt;semantic HTML&lt;/a&gt;) so you can make sure you&#39;re using the right elements and not creating any accessibiliy problems.&lt;/p&gt;
&lt;h3 id=&quot;learning-html&quot; tabindex=&quot;-1&quot;&gt;Learning HTML&lt;/h3&gt;
&lt;p&gt;I usually recommend these tutorials which provide a really nice overview of different types of elements. Try using some of the tags in &lt;a href=&quot;https://codepen.io/pen/&quot;&gt;Codepen&lt;/a&gt;, and watch things render before your eyes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/HTML_basics&quot;&gt;Getting started with HTML - MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://.freecodecamp.org/learn/responsive-web-design/#basic-html-and-html5&quot;&gt;FreeCodeCamp&#39;s Responsive Web Design course - Basic HTML and HTML5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Learn from how other people do it. Web pages are so bloated with scripts and analytics these days that it&#39;s hard to just right-click and &amp;quot;View Source&amp;quot; in the same way that I did back in the early 00s -- I learnt a lot of HTML by nicking other people&#39;s code! But you can use browser dev tools to look at the structure of the page (the Document Object Model or DOM, as it&#39;s known):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/docs/devtools/open/#elements&quot;&gt;Chrome dev tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector&quot;&gt;Firefox inspector&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;learning-css&quot; tabindex=&quot;-1&quot;&gt;Learning CSS&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://codepen.io/pen/&quot;&gt;Codepen&lt;/a&gt; comes in useful again here to easily write and apply CSS styles to HTML, and have it update instantly.&lt;/p&gt;
&lt;p&gt;Again, MDN has a great beginners&#39; guide. CSS Tricks is my favourite place for useful CSS knowledge (I referred back to their Flexbox cheatsheet for YEARS) and really clearly written guides.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/CSS_basics&quot;&gt;CSS basics -- MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/almanac/&quot;&gt;CSS Almanac -- CSS Tricks&lt;/a&gt; -- a guide to nearly every selector and property in CSS&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/guides/&quot;&gt;CSS Tricks guides&lt;/a&gt; for in-depth info&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Paid&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://egghead.io/courses/css-fundamentals&quot;&gt;CSS fundamentals on egghead.io&lt;/a&gt; by Tyler Clark (video)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;learning-javascript&quot; tabindex=&quot;-1&quot;&gt;Learning JavaScript&lt;/h3&gt;
&lt;p&gt;You want to start with vanilla JS. Having a solid foundation in that will make it easier to use frameworks and libraries in the future.&lt;/p&gt;
&lt;p&gt;How in-depth you go is up to you, and depends on how much interactive stuff you want to build on your website. If you just want a plain static site with a bit of markdown, you probably don&#39;t need JavaScript. This website has a tiny bit of JS on that controls dark mode; without that, it&#39;d just be HTML and CSS (though I did use a static site generator to build it).&lt;/p&gt;
&lt;p&gt;Besides the obligatory MDN article, these resources have been recommended by folks on &lt;a href=&quot;https://twitter.com/type__error/status/1477734460741369860&quot;&gt;Twitter&lt;/a&gt; - there are more suggestions in the replies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics&quot;&gt;Getting started with JavaScript -- MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://freecodecamp.org/&quot;&gt;FreeCodeCamp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javascript.info/&quot;&gt;javascript.info&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wesbos.com/javascript&quot;&gt;Wes Bos&#39;s Beginner JS Notes &amp;amp; Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javascript30.com/&quot;&gt;Wes Bos -- 30 Day Vanilla JS Coding Challenge&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Paid&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vanillajsacademy.com/essentials/&quot;&gt;Vanilla JS Academy&lt;/a&gt; (structured course)&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  <entry>
    <title>The right tag for the job: why you should use semantic HTML</title>
    <link href="https://localghost.dev/blog/the-right-tag-for-the-job-why-you-should-use-semantic-html/"/>
    <updated>2021-06-06T00:00:00Z</updated>
    <id>https://localghost.dev/blog/the-right-tag-for-the-job-why-you-should-use-semantic-html/</id>
    <content type="html">&lt;p&gt;I&#39;ve come across a lot of websites in my career (and in daily browsing) that are straight-up inaccessible. If you&#39;ve ever worked on a project that is riddled with accessibility issues, you&#39;ll know that fixing these problems is a mammoth task - it needs &lt;em&gt;time&lt;/em&gt;, it needs &lt;em&gt;people&lt;/em&gt;, it needs &lt;em&gt;prioritisation&lt;/em&gt;... it costs money, basically. As I mentioned in my blog post &lt;a href=&quot;https://localghost.dev/2020/10/7-myths-designers-and-developers-believe-about-web-accessibility/&quot;&gt;7 myths designers and developers believe about web accessibility&lt;/a&gt;, retrofitting accessibility is &lt;em&gt;hard&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The key is to &lt;em&gt;start out&lt;/em&gt; with the right tools for the job - or rather, the right &lt;em&gt;tags&lt;/em&gt; for the job. In every website, underneath the layers of CSS, the bloated frameworks, the 45945 API calls, there&#39;s good old HTML, and that&#39;s the key to accessible websites. Specifically, &lt;b&gt;semantic HTML&lt;/b&gt;.&lt;/p&gt;
&lt;h2 id=&quot;semantic-html-conveys-meaning&quot; tabindex=&quot;-1&quot;&gt;Semantic HTML conveys meaning&lt;/h2&gt;
&lt;p&gt;Semantics is the study of meaning, and semantic HTML is exactly that - HTML tags that convey meaning. They tell the browser - and assistive technology such as screenreaders - about the structure of the page, and how it should behave when you interact with those elements. A button should let you click on it. An ordered list should have numbers.&lt;/p&gt;
&lt;p&gt;Sighted people rely on visual information to tell them about the structure of a page. Based on our prior knowledge of UI conventions, we can identify where a header is, which parts of the page are buttons or form elements, and what the title of the page is, for example. But if you don&#39;t get that visual information, how can you tell what&#39;s on the page?&lt;/p&gt;
&lt;p&gt;Assistive technology such as screenreaders will take the HTML markup of the page and present it to the user either by reading it out audibly, or sending the output to something like a &lt;a href=&quot;https://en.wikipedia.org/wiki/Refreshable_braille_display&quot;&gt;braille display&lt;/a&gt;. They&#39;ll use the different types of HTML tags in the document to present structured information to the user, allowing them to navigate by headings, or cycle through the links in the page.  So it matters what HTML tags we use, to make sure the screenreaders get the complete picture.&lt;/p&gt;
&lt;h2 id=&quot;example%3A-a-non-semantic-news-site&quot; tabindex=&quot;-1&quot;&gt;Example: a non-semantic news site&lt;/h2&gt;
&lt;p&gt;Take this mocked-up news site (as you can see, graphic design is my passion). I&#39;ve built it using mostly &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements, with a couple of &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;s as I wanted some nice big headings. My menu at the top is a series of &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s containing links, and the footer at the bottom is the same.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;265&quot; data-theme-id=&quot;dark&quot; data-default-tab=&quot;result&quot; data-user=&quot;sophiekoonin&quot; data-slug-hash=&quot;jOBxyVB&quot; data-preview=&quot;true&quot; data-pen-title=&quot;Semantic HTML blog post example: no semantics&quot;&gt;
  &lt;span&gt;See the Pen 
    &lt;a href=&quot;https://codepen.io/sophiekoonin/pen/jOBxyVB&quot;&gt;
      Semantic HTML blog post example: no semantics&lt;/a&gt; by &lt;a href=&quot;https://codepen.io/sophiekoonin&quot;&gt;@sophiekoonin&lt;/a&gt;
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;If you&#39;re a sighted user like me, it looks perfectly fine. I can see a menu, a header, some titles and a footer. The byline and image caption is nicely italicised, and there are some nice buttons and fancy SVG checkboxes on the cookie banner.&lt;/p&gt;
&lt;p&gt;But let&#39;s take a look at this page from the perspective of assistive tech, which relies on the underlying HTML markup to establish the structure of the document. I&#39;m using the screenreader software &lt;a href=&quot;https://support.apple.com/en-gb/guide/voiceover/welcome/mac&quot;&gt;VoiceOver&lt;/a&gt;, which is built into MacOS, but if you&#39;re on Windows you can use &lt;a href=&quot;https://www.nvaccess.org/download/&quot;&gt;NVDA&lt;/a&gt; which is free to download.&lt;/p&gt;
&lt;h3 id=&quot;landmarks&quot; tabindex=&quot;-1&quot;&gt;Landmarks&lt;/h3&gt;
&lt;p&gt;Screenreader software such as VoiceOver, JAWS and NVDA provides a way for users to navigate to different sections on the page based on &lt;b&gt;landmarks&lt;/b&gt;. So, you could skip directly to the footer, or directly to the main part of the site. This relies on these landmarks being signposted through semantic tags such as &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;,&lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;. We haven&#39;t used any of these tags in the example, so screen readers wouldn&#39;t be able to identify any landmarks.&lt;/p&gt;
&lt;p&gt;When I run VoiceOver and press Ctrl+Option+Shift+I to tell me about the page, it says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Page contains 14 links 2 headings&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When I properly mark up the header, footer and main sections of the page, with an &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; around the content of the news article itself, VoiceOver allows me to navigate between them with Ctrl+Option+right/left arrow.  It tells me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Page contains 14 links 2 headings 3 landmarks 1 article&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;menus&quot; tabindex=&quot;-1&quot;&gt;Menus&lt;/h3&gt;
&lt;p&gt;If a screenreader user is trying to find the menu in this news page, they&#39;re going to have to go through all the links on the page to try and find one that seems like it could be a menu link. The &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; wrapping the menu is completely ignored by the screenreader, so all they hear is each individual link.  There&#39;s nothing to tell them which part is the menu. People shouldn&#39;t have to tab through the page incessantly to find out how to navigate to a different part of the website.&lt;/p&gt;
&lt;p&gt;Prior to HTML5, the best way to mark up menus with lists of links was an unordered list - &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;. Now we have the &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; tag, short for navigation.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;menu&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;News&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Politics&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;World&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Sport&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Tech&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Technically, you don&#39;t have to have a list inside the &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; - you can just put links in. I personally like to keep the list inside - the nice thing about lists is that some screen readers will read out how many items there are, so the user knows how long to keep tabbing through. It&#39;s also good for backwards compatibility in case any older screen readers don&#39;t understand &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Lists can be styled easily (including removing bullet points), and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; (list item) elements can contain links and buttons.&lt;/p&gt;
&lt;p&gt;You can add &lt;code&gt;aria-label&lt;/code&gt; attributes to your &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; elements to give even more information about the purpose of the menu.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;nav&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-label&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;main navigation&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&#39;s how VoiceOver interprets all of this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;main navigation, navigation&lt;/p&gt;
&lt;p&gt;list, 5 items&lt;/p&gt;
&lt;p&gt;link, Sport, 4 of 5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Whether you use &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; or not isn&#39;t a hard-and-fast rule. I noted that &lt;a href=&quot;https://gov.uk/&quot;&gt;gov.uk&lt;/a&gt; (an example of amazing accessible design) doesn&#39;t actually use them at all, sticking with unordered lists. As long as you use one and/or the other, you&#39;ll be fine.&lt;/p&gt;
&lt;p&gt;As an aside, I recommend using the Dev Tools inspector to look through the source for &lt;a href=&quot;http://gov.uk/&quot;&gt;gov.uk&lt;/a&gt; to see how they use ARIA attributes, as they use them very well.&lt;/p&gt;
&lt;h3 id=&quot;checkboxes&quot; tabindex=&quot;-1&quot;&gt;Checkboxes&lt;/h3&gt;
&lt;p&gt;These checkboxes aren&#39;t real checkboxes - they&#39;re &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements with CSS &lt;code&gt;:before&lt;/code&gt; pseudoselectors containing an SVG checkbox icon. VoiceOver reads them out as plain text, leaving you with no idea you can even click them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Chocolate chip&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&#39;s super annoying that you can&#39;t style the default checkbox in browsers, but there are ways around it that still let you use &lt;code&gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt;. The same goes for radio buttons.&lt;/p&gt;
&lt;p&gt;If we put the input back in and &lt;em&gt;visually&lt;/em&gt; hide it (leaving the input element in the DOM), we get a much more helpful readout:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;choc-chip&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;choc-chip&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;visually-hidden&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pretty-checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-hidden&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; Chocolate chip&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(NB. you could even just have the actual SVG inline here)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Chocolate chip, unticked, checkbox&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We hide the &amp;quot;pretty&amp;quot; checkbox from screen readers, because they will pick up the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The input itself has a CSS class of &lt;code&gt;&amp;quot;visually-hidden&amp;quot;&lt;/code&gt;, which looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.visually-hidden&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1px 1px 1px 1px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;clip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1px&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 1px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;clip-path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;inset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;1px&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;white-space&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nowrap&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can&#39;t simply use &lt;code&gt;visibility: hidden&lt;/code&gt; or &lt;code&gt;display: none&lt;/code&gt; as these attributes actually apply to screenreaders as well. Anything hidden that way will also be hidden to screenreaders. This &lt;code&gt;visually-hidden&lt;/code&gt; class makes sure that elements with this styling are invisible to sighted users, but still visible to assistive tech.&lt;/p&gt;
&lt;p&gt;For more information on this approach, check out &lt;a href=&quot;https://www.sarasoueidan.com/blog/inclusively-hiding-and-styling-checkboxes-and-radio-buttons/&quot;&gt;Sara Soueidan&#39;s guide to inclusively hiding &amp;amp; styling checkboxes and radio buttons&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For even more semantic goodness, we can now wrap our checkboxes in a &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt;, which groups together related form-fields. We can then attach the &amp;quot;Which of these cookies can we use?&amp;quot; text to the fieldset by making it a &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;fieldset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;legend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Which of these cookies can we use?&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;legend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;choc-chip&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;choc-chip&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pretty-checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-hidden&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; Chocolate chip&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;oatmeal-raisin&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;oatmeal-raisin&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pretty-checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; Oatmeal &lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;amp;&quot;&gt;&amp;amp;amp;&lt;/span&gt; raisin&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;fieldset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;VoiceOver:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Which of these cookies can we use?, group&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;buttons&quot; tabindex=&quot;-1&quot;&gt;Buttons&lt;/h3&gt;
&lt;p&gt;The &amp;quot;buttons&amp;quot; - actually &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements with added &lt;code&gt;onclick&lt;/code&gt; attributes - are recognised as &amp;quot;Clickable&amp;quot; by Voiceover. Not all screenreader software is able to identify clickable elements in this way.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Accept all, clickable&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, if I&#39;m navigating through the page using only the keyboard, I can&#39;t select one because the browser doesn&#39;t know it&#39;s a button.&lt;/p&gt;
&lt;p&gt;Sure, we &lt;em&gt;could&lt;/em&gt; go adding a &lt;code&gt;tabindex&lt;/code&gt; attribute to these buttons to make them tabbable, but then you run the risk of messing up the natural tabbing order of the document. The best solution is to &lt;strong&gt;use a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element&lt;/strong&gt;. That&#39;s what it&#39;s for, and you can style it pretty much any way you like using CSS. You can even &lt;a href=&quot;https://codepen.io/sophiekoonin/pen/oNZdebX&quot;&gt;make a button look like a link, and vice versa&lt;/a&gt;, which is something I do a lot when building a website to a design spec.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;  &lt;span class=&quot;token selector&quot;&gt;.button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pointer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 6px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; auto 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;justify-content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;align-items&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; center&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.8rem 1rem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #420a55&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token selector&quot;&gt;.button:hover&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #8d6c99&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Accept all, button&lt;/p&gt;
&lt;p&gt;You are currently on a button... to click this button, press Ctrl+Option+Space.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;headings&quot; tabindex=&quot;-1&quot;&gt;Headings&lt;/h3&gt;
&lt;p&gt;We&#39;ve got three H1 elements on the page: the site name, the article headline, and the cookie banner. A site should only ever have one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element - it&#39;s the main heading that tells you what the page is about. Any other headings should be nested underneath, or possibly not even headings at all (in the case of &amp;quot;The Woofer Times&amp;quot;, this doesn&#39;t need to be an actual heading).&lt;/p&gt;
&lt;p&gt;There&#39;s a subheading within the article which is simply bold text. That should be a lower-level nested heading, in this case an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Screenreaders allow users to navigate by headings, so it&#39;s important they&#39;re in a logical order.&lt;/p&gt;
&lt;p&gt;If you want big text, style it with CSS rather than relying on the browser default size of heading elements.&lt;/p&gt;
&lt;h3 id=&quot;bold-and-italic-text&quot; tabindex=&quot;-1&quot;&gt;Bold and italic text&lt;/h3&gt;
&lt;p&gt;The byline and the image caption are displayed in italics using the &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; tag. However, screen readers may actually read this out differently because they expect the &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; tag to signal &lt;b&gt;emphasis&lt;/b&gt; - that&#39;s what &lt;code&gt;em&lt;/code&gt; means. So the tone of voice might change as it&#39;s being read out, with additional stress. The italics in the byline and caption are a stylistic choice, so we should italicise it with CSS rather than &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; tag still exists alongside the &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; tag, but represents text that stands out from the rest of the body, such as scientific names, thoughts, technical terms and idiomatic terms from other languages:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;The red fox, &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Vulpes vulpes&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;, is commonly found... &lt;br /&gt;It was a case of &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;i&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;fr&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;déjà vu&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Sure&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;, she thought, &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;that must be it&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;em&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;really&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;em&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; don&#39;t like this book.&lt;br /&gt;Do it &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;em&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;now&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;em&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;!&lt;br /&gt;No, &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;em&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;I&#39;m&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;em&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; Spartacus.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same goes for any bold text - &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; indicates significance or keywords and may also result in the screenreader voice changing when read out, so use CSS if the effect is purely presentational.&lt;/p&gt;
&lt;p&gt;Somewhat confusingly, both &lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; are used in slightly different situations despite both rendering as bold text in browsers - &lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt; &amp;quot;indicates that its contents have strong importance, seriousness, or urgency&amp;quot; (&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong&quot;&gt;MDN&lt;/a&gt;), where as &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; is used to draw attention without the urgency (e.g. for relevant terms in a blog post like this one).&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;I won&#39;t tell you again, &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;strong&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;do not disconnect the fire alarm&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;strong&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;This is known as &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;semantic HTML&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NB. Frustratingly, Markdown doesn&#39;t seem to distinguish between these elements, so everything is &lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt;.  If you want to use &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; you&#39;ll have to add them in as HTML within your Markdown.&lt;/p&gt;
&lt;h3 id=&quot;image-caption&quot; tabindex=&quot;-1&quot;&gt;Image caption&lt;/h3&gt;
&lt;p&gt;It&#39;s clear to sighted users that the text under the image is a caption, but not to screen readers - there&#39;s nothing associating the two at all.&lt;/p&gt;
&lt;p&gt;We can fix that by wrapping the image in a &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; element, then adding a &lt;code&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt; underneath the image.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;figure&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;a lovely fluffy samoyed&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://codepen-assets.s3.eu-west-2.amazonaws.com/alex-russell-saw-Dj8cxyi9ink-unsplash-1.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;figcaption&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;caption&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&quot;The most angery pupper I have ever seen&quot; Photo: &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://unsplash.com/@alexrussellsaw&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Alex Russell-Saw&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;figcaption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;figure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;VoiceOver says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;The most angery pupper I have ever seen&amp;quot; Photo: Alex Russell-Saw, figure&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;before then reading out the image information:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a lovely fluffy samoyed, image&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;you-can-still-use-divs!&quot; tabindex=&quot;-1&quot;&gt;You can still use &lt;code&gt;div&lt;/code&gt;s!&lt;/h2&gt;
&lt;p&gt;As I demonstrated above, &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements can be extremely misused. That&#39;s not to say you shouldn&#39;t use them &lt;em&gt;at all&lt;/em&gt;: on the contrary. But you should only use them for their intended purpose: entirely meaningless containers. I use them to group elements together which I then style with CSS. Or I&#39;ll wrap the entire page in a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; and make it into a flex container for my &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;. &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s are great, as long as you don&#39;t use them in place of more meaningful elements.&lt;/p&gt;
&lt;p&gt;You can use the Dev Tools inspector on this very website and see the way I&#39;ve used &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s presentationally: for example, all the stars in the header are divs which are totally hidden from screenreaders, because they&#39;re entirely decorative.&lt;/p&gt;
&lt;h2 id=&quot;the-same-news-site%2C-with-semantic-tags&quot; tabindex=&quot;-1&quot;&gt;The same news site, with semantic tags&lt;/h2&gt;
&lt;p&gt;I&#39;ve recreated the same site using semantic HTML tags, and it looks pretty much exactly the same (save some different margins here and there that are easy enough to fix).&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;265&quot; data-theme-id=&quot;dark&quot; data-default-tab=&quot;result&quot; data-user=&quot;sophiekoonin&quot; data-slug-hash=&quot;yLMjMgQ&quot; data-preview=&quot;true&quot; data-pen-title=&quot;Semantic HTML blog post example: semantic HTML&quot;&gt;
  &lt;span&gt;See the Pen 
    &lt;a href=&quot;https://codepen.io/sophiekoonin/pen/yLMjMgQ&quot;&gt;
      Semantic HTML blog post example: semantic HTML&lt;/a&gt; by &lt;a href=&quot;https://codepen.io/sophiekoonin&quot;&gt;@sophiekoonin&lt;/a&gt;
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;There is still a lot of room for improvement&lt;/strong&gt;. ARIA attributes come into play here, to add extra information about the roles of each part of the page. I&#39;m just illustrating the semantic elements in this example.&lt;/p&gt;
&lt;p&gt;Here are the main differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the page is broken up into &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;, with an &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; round the main page content&lt;/li&gt;
&lt;li&gt;there is only one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; on the page, because it signifies the main heading that tells you what the page is about&lt;/li&gt;
&lt;li&gt;the &amp;quot;Accept all&amp;quot; and &amp;quot;Close&amp;quot; buttons are actual &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; elements&lt;/li&gt;
&lt;li&gt;the checkboxes are &lt;code&gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt;, with &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt;s on each one
&lt;ul&gt;
&lt;li&gt;they&#39;re also inside a &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; with a &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt; explaining what the checkboxes are for&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;the menu links are in an unordered list, &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;, wrapped in a &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the subheadings in the article are now &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; (the first level of nesting under the main heading)&lt;/li&gt;
&lt;li&gt;the byline and caption are styled italic through CSS, rather than &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt; tags&lt;/li&gt;
&lt;li&gt;I&#39;ve used a &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; for the image, with a &lt;code&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt; for the caption to indicate it&#39;s a caption for that image&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;semantics-from-the-start-%3D-accessibility-from-the-start&quot; tabindex=&quot;-1&quot;&gt;Semantics from the start = accessibility from the start&lt;/h2&gt;
&lt;p&gt;Using semantic HTML as building blocks for a website will give you a lovely accessible foundation upon which to add your fancy CSS and whizzy JavaScript. You can use semantic elements in JS frameworks, too - I write React every day at work, and always use semantic elements. Your users (and/or your customers) will thank you for it.&lt;/p&gt;
&lt;h2 id=&quot;find-out-more-about-semantic-html&quot; tabindex=&quot;-1&quot;&gt;Find out more about semantic HTML&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element&quot;&gt;MDN: HTML Elements reference&lt;/a&gt; - with explanations of each element&#39;s purpose&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn-the-web.algonquindesign.ca/topics/html-semantics-cheat-sheet&quot;&gt;Semantic HTML cheat sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  <entry>
    <title>A typical day: pandemic edition</title>
    <link href="https://localghost.dev/blog/a-typical-day-pandemic-edition/"/>
    <updated>2021-01-18T00:00:00Z</updated>
    <id>https://localghost.dev/blog/a-typical-day-pandemic-edition/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;This is a series started by &lt;a href=&quot;http://cdevroe.com/2021/01/07/my-typical-day/&quot;&gt;Colin Devroe&lt;/a&gt;. Some other lovely folks have written their own, including &lt;a href=&quot;https://www.sarasoueidan.com/desk/typical-day/&quot;&gt;Sara Soueidan&lt;/a&gt; and &lt;a href=&quot;https://www.cassie.codes/posts/my-typical-day/&quot;&gt;Cassie Evans&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This post would have looked very different prior to March 2020. Before then, I&#39;d be out at events, meetups or social meetings several nights a week, in the office every day seeing people, and commuting to and from work. Needless to say, as someone who gets energy from being around others, the change to working from home full-time and not going out has had a massive impact on my mental health and my depression has got much worse. I don&#39;t think I would have been nearly as &lt;a href=&quot;https://localghost.dev/2020/12/give-yourself-a-break-lessons-from-burnout/&quot;&gt;burnt out&lt;/a&gt; as I was in December if all of this hadn&#39;t been going on. So this is my &amp;quot;current normal&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;my-typical-day&quot; tabindex=&quot;-1&quot;&gt;My typical day&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;08:00 - 09:00:&lt;/strong&gt; wake up, about an hour later than I used to. I&#39;ll usually sit in bed for a bit drinking coffee, talking to my husband, and checking the news/Twitter/notifications (it&#39;s a habit I&#39;m trying to break, but not doing very well).&lt;/p&gt;
&lt;p&gt;At some point during this hour I&#39;ll scrape myself out of bed and shower, get dressed (I can&#39;t work in PJs!) and find some breakfast. If I&#39;m honest, this is usually about 15 mins before I start work, because my bed is extremely comfortable and it&#39;s cold in the house.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;09:00&lt;/strong&gt;: catch up on Slack messages, see if there&#39;s anything that needs my attention, say hi to the team.&lt;/p&gt;
&lt;p&gt;We usually have a quick standup at 10ish, then I get stuck into whatever I&#39;m working on. My days are often peppered with 1:1s, planning meetings and various other things - PR reviews, answering questions on Slack, triaging bugs. At the moment I find it hard to focus for long periods of time so whatever I&#39;m doing I&#39;ll inevitably be distracted by notifications (I need to get into the habit of turning off Slack while I work).&lt;/p&gt;
&lt;p&gt;Depending on what I&#39;m working on, I might be doing web work in React or backend work in Go, or I might be writing a proposal for a feature or technical change.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;12:00 - 13:00&lt;/strong&gt;: lunchtime. Quite an early lunch, a relic from when I used to be up at 7, eating breakfast at 7:30 and hungry by 12. I&#39;ll often go for a walk in the park and listen to a podcast (&lt;a href=&quot;https://darknetdiaries.com/&quot;&gt;Darknet Diaries&lt;/a&gt;, &lt;a href=&quot;https://switchedonpop.com/&quot;&gt;Switched On Pop&lt;/a&gt; and &lt;a href=&quot;https://strongsongspodcast.com/&quot;&gt;Strong Songs&lt;/a&gt; are my favourites) or chat to my husband. On especially good days, we might go down to our garage where we have a little gym set up - I&#39;ve been doing some free weights.&lt;/p&gt;
&lt;p&gt;I miss buying lunch, which is undisputably the most annoying meal to have to make.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;13:00 - 18:00:&lt;/strong&gt; the rest of my working day - more coding and 1:1s. I block out parts of the day in my calendar so that I have uninterrupted time with no meetings.&lt;/p&gt;
&lt;p&gt;At points I&#39;ll go downstairs to refill my drink and pester my husband.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;18:00:&lt;/strong&gt; I log off from work. I&#39;m very strict about what time I finish work - never after 6pm.&lt;/p&gt;
&lt;p&gt;Once every couple of weeks I have a therapy session via video call, which has been massively helpful this year.&lt;/p&gt;
&lt;p&gt;I&#39;m a creative person and I originally imagined I&#39;d spend a lot of the free time I gained from not commuting doing things like making music or building cool things, but in reality I just browse the internet or play a video game.&lt;/p&gt;
&lt;p&gt;I&#39;ve been thinking a lot about &lt;a href=&quot;https://butyoudontlooksick.com/articles/written-by-christine/the-spoon-theory/&quot;&gt;spoon theory&lt;/a&gt; recently. Originally conceived as an analogy to living with chronic illness, I think it fits perfectly with the way my depression has been manifesting itself this year: I just haven&#39;t got enough spoons right now to do all the things I want to do. So often when I feel I should be being productive or doing something creative, all I&#39;ll have the energy to do is just sit down and play video games. Over Xmas it was Assassin&#39;s Creed: Valhalla, then a lot of &lt;a href=&quot;https://www.stardewvalley.net/&quot;&gt;Stardew Valley&lt;/a&gt;, and I&#39;ve racked up an embarrassing number of hours on &lt;a href=&quot;https://www.twopointhospital.com/&quot;&gt;Two Point Hospital&lt;/a&gt; over the last few weeks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;19:00:&lt;/strong&gt; time to make dinner, or continue to veg out while my husband makes dinner. Or we give up and order a takeaway.&lt;/p&gt;
&lt;p&gt;We&#39;ve been making an extra effort to eat at the table over the last few months, which is nice because we actually talk to each other and pay attention to what we&#39;re eating instead of just zoning out in front of the TV 🙈&lt;/p&gt;
&lt;p&gt;Generally after dinner we&#39;ll watch TV, or continue playing video games next to each other because we&#39;re adults and make sensible choices. Sometimes I&#39;ll pick up whatever embroidery I have in progress and do it while we watch TV - I&#39;m currently embroidering my wedding flowers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://localghost.dev/img/blog/typical-day/embroidery.jpg&quot; alt=&quot;&quot; title=&quot;An embroidery in progress featuring statice, a peony, roses and a gerbera&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;https://localghost.dev/img/blog/typical-day/wedding-flowers.jpg&quot; alt=&quot;&quot; title=&quot;A photo of my wedding bouquet&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I&#39;ve started keeping a little journal of good things that happen every day. They can be as minor as &amp;quot;made a &lt;a href=&quot;https://www.bbcgoodfood.com/recipes/aubergine-tomato-halloumi-pie&quot;&gt;really nice pie&lt;/a&gt;&amp;quot; or something like &amp;quot;got really positive feedback on the proposal I wrote&amp;quot;. I tend to fixate on negative things, so having written evidence that good stuff is still happening should hopefully anchor me a bit and remind me of the positive side. I recommend it! Plus it&#39;s an excuse to buy a notebook and some nice pens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;23:00:&lt;/strong&gt; time for bed. Over the last six years I&#39;ve been going to bed at 11pm so religiously that I actually get sleepy at 11pm automatically. I try and read a bit before bed (currently making my way through Elena Ferrante&#39;s Neapolitan Novels) but usually I only manage a few pages before I conk out.&lt;/p&gt;
&lt;p&gt;I feel like this wasn&#39;t a particularly exciting or enlightening typical day, but really, how can it be? Like &lt;a href=&quot;https://www.cassie.codes/posts/my-typical-day/&quot;&gt;Cassie&lt;/a&gt; says: &amp;quot;If you&#39;re reading these posts - whatever your day looks like - whether you smashed through a huge to-do list or not. You&#39;re doing good, remember to be kind to yourself.&amp;quot;.&lt;/p&gt;
&lt;p&gt;All we can really do is make it through the day, focus on the tiny things that make us happy, and know that there is a light at the end of the tunnel. At the time of writing, 5.8% of the UK population have received their first dose of the vaccine (including my dad, hey dad!). Good news is out there, it&#39;s just not as clickbaity as the bad news, so we see less of it.&lt;/p&gt;
&lt;p&gt;Now, if you&#39;ll excuse me, I have a fake hospital to run.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Give yourself a break: lessons from burnout</title>
    <link href="https://localghost.dev/blog/give-yourself-a-break-lessons-from-burnout/"/>
    <updated>2020-12-16T00:00:00Z</updated>
    <id>https://localghost.dev/blog/give-yourself-a-break-lessons-from-burnout/</id>
    <content type="html">&lt;p&gt;I started writing this post a few days ago, and was so exhausted I couldn&#39;t actually be bothered to finish it, which tells you a lot really. And if you&#39;re too exhausted to read another blog post, here&#39;s a summary: have a rest. Go and do something nice. Tech can wait.&lt;/p&gt;
&lt;p&gt;A couple of weeks ago (possibly - I have no concept of time any more) I tweeted this, which seemed to resonate with folks:&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/type__error&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1474717155983773700/sXRdF5e3_normal.jpg&quot; alt=&quot;Avatar for type__error&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/type__error&quot;&gt;Sophie Koonin &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/type__error/status/1335329159200055303&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;the only coding I&#39;ve done outside of work in quite a long time is a small bit of JS to apply hats to emoji. I don&#39;t know how anyone does tech stuff out of hours, it&#39;s exhausting enough doing it IN hours&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=1335329159200055303&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;160 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Dec 5, 2020 09:04:15 (UTC)&quot; href=&quot;https://twitter.com/type__error/status/1335329159200055303&quot;&gt;10:04 PM · Dec 5, 2020&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;(A plug for &lt;a href=&quot;https://emojinator.fun/&quot;&gt;emojinator&lt;/a&gt;, the site in question where you can add hats to emoji)&lt;/p&gt;
&lt;p&gt;Twitter is awash with fantastically talented people building incredible stuff and sharing it, as well as those insufferable grifters who tweet things like &amp;quot;15 things you must learn to be a good developer #100daysofcode&amp;quot; and then hawk you their ebook. &amp;quot;Thought leaders&amp;quot; (don&#39;t you just hate that term) are churning out article after article of brilliant leadership advice, technical deep-dives, creative things to do in CSS, you name it. I don&#39;t know about you, but the article count on my RSS reader has been increasing for months and I just have &lt;em&gt;not&lt;/em&gt; been reading anything. I can barely focus at the moment.&lt;/p&gt;
&lt;p&gt;I became a tech lead in September, which is something I&#39;ve been wanting to do for quite a while. One day I&#39;ll write about what I&#39;ve learned as a new tech lead, but now is not the time, because I don&#39;t think I&#39;ve been able to really succeed in my role due to the constant being-on-fire-ness of this entire year. Instead, have some lessons from the trash fire of 2020 that we can take over into the slightly-smaller-but-still-burning trash fire of 2021.&lt;/p&gt;
&lt;h2 id=&quot;lesson-number-1%3A-give-yourself-a-break&quot; tabindex=&quot;-1&quot;&gt;Lesson number 1: give yourself a break&lt;/h2&gt;
&lt;p&gt;As a new tech lead, I&#39;ve felt like I&#39;m letting my team down because I don&#39;t have the mental capacity to sit and read about the things I need to improve on, like observability and monitoring. I&#39;ve had a copy of the SRE Workbook on my laptop waiting to be read, which I&#39;ve barely touched.&lt;/p&gt;
&lt;p&gt;Where did all these expectations come from? Myself, mostly. Nobody is peering over my shoulder going &amp;quot;why aren&#39;t you reading about Prometheus?&amp;quot;. (Actually, my team have been nothing but supportive this entire year, and I love them all.)&lt;/p&gt;
&lt;p&gt;The coronavirus pandemic has meant that my &lt;a href=&quot;https://shechoir.com/london&quot;&gt;choir&lt;/a&gt; hasn&#39;t been able to meet since March. The choir I&#39;ve been a part of for seven years, have been co-running for five of those years, and which forms a huge part of my own identity. I&#39;m an extrovert who gets energy from being around people (but not in a Colin Robinson kind of way). Most of us have barely seen our friends and family. This year has been intensely difficult. I&#39;m sure you&#39;ve all experienced something similar.&lt;/p&gt;
&lt;p&gt;On top of that, the political situation is dire. As well as the absolute corrupt shambles of a government who have done such a terrible job of handling the COVID pandemic that we have the highest death rate in Europe, there&#39;s a big red countdown timer on the UK government website that counts down to Brexit when I&#39;m looking up just what the hell being in Tier 3 actually means. Many, many people have lost loved ones, there&#39;s a whole wave of anti-vaccine &amp;quot;Keep Britain Free&amp;quot; zealots popping up all over the place, and the UK has been nicknamed &amp;quot;TERF island&amp;quot; because of the rampant transphobia being spouted by formerly respectable public figures. And that&#39;s just on our doorsteps in the UK.&lt;/p&gt;
&lt;p&gt;The SRE Workbook can wait, basically. We have enough on our collective plates.&lt;/p&gt;
&lt;h2 id=&quot;lesson-number-2%3A-if-it-benefits-your-work%2C-it-can-be-done-in-working-hours&quot; tabindex=&quot;-1&quot;&gt;Lesson number 2: if it benefits your work, it can be done in working hours&lt;/h2&gt;
&lt;p&gt;Perhaps you used to watch conference talks on the daily commute, or read technical books in bed. I definitely had a copy of The Manager&#39;s Path next to the bed that I was chipping away at at one point. But now that commute is gone for many of us, and I don&#39;t know about you but the only thing I have the energy for in the evenings is playing video games or idly browsing the internet.&lt;/p&gt;
&lt;p&gt;I believe quite strongly that if you are learning something in order to become better at your job, you should be doing that within working hours. In my team, we all know that &lt;em&gt;technically&lt;/em&gt; it&#39;s encouraged to take time out to learn something - we get a budget to do just that - but we rarely ever do it. To that end, I actually scheduled 2 hours a week in the whole team&#39;s calendar on a Friday for &amp;quot;Reading time&amp;quot;. They can use that time however they want: they can watch videos, try something out, read a book. They can take more time, or less time. They can do it on a different day, or skip it entirely. All it is is the explicit permission to take some time out of your week to learn something, &lt;em&gt;if you want&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;(I don&#39;t know if they actually take the time: I haven&#39;t asked. I just want them to know they can, in writing.)&lt;/p&gt;
&lt;h2 id=&quot;lesson-number-3%3A-some-things-are-boring-and-that&#39;s-okay&quot; tabindex=&quot;-1&quot;&gt;Lesson number 3: some things are boring and that&#39;s okay&lt;/h2&gt;
&lt;p&gt;Kubernetes does not interest me. I have the utmost respect for the infra folks on Twitter who seem super intelligent and knowledgeable about it, but I cannot bring myself to be interested in it. For a while I felt like not being into this stuff made me a lesser developer somehow. But my specialism lies elsewhere and there are things I&#39;m good at that people who do Kubernetes for a living aren&#39;t (and I have it on good authority that &amp;quot;do Kubernetes&amp;quot; is a technical term). That&#39;s how well-functioning teams work.&lt;/p&gt;
&lt;p&gt;I know enough &lt;code&gt;kubectl&lt;/code&gt; to get a list of pods and SSH into one of them (but mainly because I have the zsh autocomplete plugin and it fills it in for me based on my past commands). That&#39;s all I need: most of the actual Kubernetes wizardry is automated or managed by people who specialise in it (in my case, our excellent Infrastructure Platform team). A good developer or tech lead will know when it&#39;s the right time to delegate to someone who knows more about it than they do.&lt;/p&gt;
&lt;h2 id=&quot;lesson-number-4%3A-mental-health-is-more-important-than-kpis&quot; tabindex=&quot;-1&quot;&gt;Lesson number 4: mental health is more important than KPIs&lt;/h2&gt;
&lt;p&gt;I&#39;ll caveat this section with the fact that I know many people work at companies where mental health is not something to be discussed, or something that people really seem to take into account. And I also know it&#39;s not as simple as &amp;quot;find another job&amp;quot; and that should never be the only solution.&lt;/p&gt;
&lt;p&gt;Instead, this is an appeal to senior leadership and management. Your employees are not inanimate batteries you plug in to power your company. They are humans, with complicated lives, families they haven&#39;t been able to see for months, and children having to stay home from school because someone in their class tested positive for COVID. Their partner might have lost their job this year. They may be struggling with working from home, missing being around people in the office, or they might be finding video calls even more exhausting than real-life meetings. If you&#39;ve sadly had to make redundancies this year, are you expecting the reduced number of people to do the same amount of work as before?&lt;/p&gt;
&lt;p&gt;If you&#39;re a team lead, check in on your team. Are they working long hours? Encourage them to sign off earlier. I highly recommend this &lt;a href=&quot;https://twitter.com/kkukshtel/status/1338240765605109762&quot;&gt;Twitter thread&lt;/a&gt; about why working late a couple of hours a week can lead to completely unrealistic expectations of how long projects take to complete.&lt;/p&gt;
&lt;p&gt;Schedule 1:1s with them and ask them how they&#39;re feeling about things. Encourage them to share their workload if they have too much: having more on your plate than you can cope with right now is not a sign of failure.&lt;/p&gt;
&lt;p&gt;Mental health should be taken as seriously as physical health. We have trained &lt;a href=&quot;https://mhfaengland.org/&quot;&gt;mental health first aiders&lt;/a&gt; who can provide a swift response over Slack, an Employee Assistance Program for access to counselling and legal information, and people can take mental health days if they are struggling. I&#39;ve taken three afternoons off at the last minute in the past three weeks because I was so exhausted with &lt;em&gt;[gestures wildly]&lt;/em&gt; everything, and my team were very understanding about it. I know I am privileged in that regard, and I am grateful.&lt;/p&gt;
&lt;p&gt;Ultimately, the productivity and success of the company will suffer more if your team burn out. People will start taking extended leave, or they&#39;ll quit. It&#39;s a choice between delaying a product release by a day and the mental health of a human being.&lt;/p&gt;
&lt;p&gt;--&lt;/p&gt;
&lt;p&gt;Sorry folks, I wrote a long article when I promised you you didn&#39;t have to read articles. Go and have a cup of tea and look out of the window for a bit.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/type__error&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1474717155983773700/sXRdF5e3_normal.jpg&quot; alt=&quot;Avatar for type__error&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/type__error&quot;&gt;Sophie Koonin &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/type__error/status/1335331963243257857&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;I guess what I&#39;m saying is I&#39;m really tired, it&#39;s okay if you&#39;re really tired, let&#39;s all be really tired and accept that the Google SRE Workbook will stay untouched on the shelf for a few more weeks&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=1335331963243257857&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;20 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Dec 5, 2020 09:15:23 (UTC)&quot; href=&quot;https://twitter.com/type__error/status/1335331963243257857&quot;&gt;10:15 PM · Dec 5, 2020&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;</content>
  </entry>
  
  <entry>
    <title>7 myths designers and developers believe about web accessibility</title>
    <link href="https://localghost.dev/blog/7-myths-designers-and-developers-believe-about-web-accessibility/"/>
    <updated>2020-10-11T00:00:00Z</updated>
    <id>https://localghost.dev/blog/7-myths-designers-and-developers-believe-about-web-accessibility/</id>
    <content type="html">&lt;p&gt;In an ideal world, being &amp;quot;good at accessibility&amp;quot; wouldn&#39;t make you stand out from the crowd. Companies wouldn&#39;t be hiring accessibility experts to help them unpick and untangle the inaccessible products they&#39;ve been building for years. Speaking about web accessibility at a conference would be as unnecessary as getting up on stage and giving a talk on how to write HTML.&lt;/p&gt;
&lt;p&gt;But we don&#39;t live in that world, and the web is full of inaccessible websites. Try navigating the &lt;a href=&quot;https://libertylondon.com/&quot;&gt;Liberty London&lt;/a&gt; website with just your keyboard - can you add something to your basket?&lt;/p&gt;
&lt;p&gt;I want to bust a few myths that I&#39;ve come across over the years, in the hope that accessibility will stop being something to &amp;quot;deal with later&amp;quot; and start being something that people think about from the start.&lt;/p&gt;
&lt;h2 id=&quot;myth-1%3A-the-majority-of-your-users-don&#39;t-have-access-needs&quot; tabindex=&quot;-1&quot;&gt;Myth 1: The majority of your users don&#39;t have access needs&lt;/h2&gt;
&lt;p&gt;Repeat after me: there&#39;s no such thing as a &amp;quot;typical&amp;quot; or &amp;quot;normal&amp;quot; user.&lt;/p&gt;
&lt;p&gt;When we&#39;re designing and building websites or apps, it&#39;s all too easy to forget that we are coming from a narrow perspective. My own abilities, experiences and knowledge shape how I interact with a website, and my experience may be totally different from yours. So even if you know instinctively that a particular icon means &amp;quot;download&amp;quot;, others might not make that connection.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/accessibility-myths/spiderman-point.jpg&quot; alt=&quot;Spiderman pointing at himself&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Is this how you see your users?&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Microsoft&#39;s brilliant &lt;a href=&quot;https://www.microsoft.com/design/inclusive/&quot;&gt;Inclusive Design Toolkit&lt;/a&gt; warns of the consequences of this selective thinking:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“If we use our own abilities and biases as a starting point, we end up with products designed for people of a specific gender, age, language ability, tech literacy, and physical ability. Those with specific access to money, time, and a social network.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a non-disabled, computer-literate developer with a Macbook and fibre internet, I need to make sure I&#39;m not only building apps for people like me. All my users will have different requirements, different technology and different backgrounds. As the Inclusive Design Toolkit puts it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“When it comes to people, there’s no such thing as “normal.” The interactions we design with technology depend heavily on what we can see, hear, say, and touch. Assuming all those senses and abilities are fully enabled all the time creates the potential to ignore much of the range of humanity.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;myth-2%3A-accessibility-is-optional&quot; tabindex=&quot;-1&quot;&gt;Myth 2: Accessibility is optional&lt;/h2&gt;
&lt;p&gt;It&#39;s actually the law, in both the UK and the USA (I can&#39;t speak for other countries, but I&#39;d be keen to hear from anyone who knows about any legislation in other places).&lt;/p&gt;
&lt;p&gt;In the UK, The Equality Act 2010 makes it illegal to discriminate against people with disabilities - and that includes by accident! It doesn’t explicitly refer to websites, but the Equality and Human Rights Commission’s (EHRC) Code of Practice does list websites as one of the services to the public that should be considered covered by the Equality Act.&lt;/p&gt;
&lt;p&gt;According to the EHRC, an organisation &amp;quot;is responsible for ensuring that reasonable adjustments have been made where needed, for example by changing the size of the font, to ensure that disabled users are able to get the information, without being placed at a substantial disadvantage (even if the [organization] employs an external organisation to build and maintain its website).&amp;quot;&lt;/p&gt;
&lt;p&gt;The EHRC may:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conduct formal investigations&lt;/li&gt;
&lt;li&gt;Serve non-discrimination notices&lt;/li&gt;
&lt;li&gt;Act over persistent discrimination&lt;/li&gt;
&lt;li&gt;Issue &lt;a href=&quot;https://www.equalityhumanrights.com/sites/default/files/employercode.pdf&quot;&gt;Codes of Practice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Help someone prosecute a company - this requires someone to actually sue the company, which there&#39;s no case law for at the moment - but that could change any time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the US, there&#39;s the Americans with Disabilities Act (ADA). Famously, &lt;a href=&quot;https://www.bbc.co.uk/news/technology-46894463&quot;&gt;Domino&#39;s Pizza was sued&lt;/a&gt; by a blind person who couldn&#39;t use the website with a screenreader. According to US law firm &lt;a href=&quot;https://www.adatitleiii.com/2020/04/the-curve-has-flattened-for-federal-website-accessibility-lawsuits/&quot;&gt;Seyfarth&lt;/a&gt;, in 2019 there were 2,256 web accessibility lawsuits filed.&lt;/p&gt;
&lt;h2 id=&quot;myth-3%3A-access-needs-come-from-permanent-disabilities&quot; tabindex=&quot;-1&quot;&gt;Myth 3: Access needs come from permanent disabilities&lt;/h2&gt;
&lt;p&gt;The truth is, anyone at any time can have access needs, and they can be permanent, temporary or situational. Temporary impairments might be due to a medical condition, and situational impairments may result from the environment around us - a situation we&#39;re in.&lt;/p&gt;
&lt;p&gt;Some examples of permanent conditions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;partial or full blindness&lt;/li&gt;
&lt;li&gt;having a limb amputated&lt;/li&gt;
&lt;li&gt;learning difficulties, such as dyslexia&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A temporary impairment could be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;visual aura from a migraine&lt;/li&gt;
&lt;li&gt;repetitive strain injury making it difficult to use a mouse&lt;/li&gt;
&lt;li&gt;cognitive processing difficulties (also known as brain fog) following an illness&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Situational impairments might include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a bright light causing glare on the screen&lt;/li&gt;
&lt;li&gt;loud noise, making it difficult to concentrate&lt;/li&gt;
&lt;li&gt;slow internet&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if you consider yourself not to have any form of disability, you could find yourself with a temporary or situational impairment at any point.&lt;/p&gt;
&lt;p&gt;Often when developers &lt;em&gt;do&lt;/em&gt; think about accessibilty, they think of screen readers and people with visual impairments. That&#39;s a start, but there’s a spectrum of what constitutes disability. The important thing to note is that it doesn’t necessarily translate to some kind of personal health condition.&lt;/p&gt;
&lt;p&gt;According to the World Health Organisation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Disability is not just a health problem. It is a complex phenomenon, reflecting the interaction between features of a person’s body and features of the society in which [they live].&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So much of the world around us can influence whether or not we have, or consider ourselves to have, a disability. Summed up perfectly in this Tweet by &lt;a href=&quot;https://twitter.com/amandaleduc/status/1300083052710899712&quot;&gt;Amanda Leduc&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/AmandaLeduc&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1412041452675383297/qD9K8Hh4_normal.jpg&quot; alt=&quot;Avatar for AmandaLeduc&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/AmandaLeduc&quot;&gt;Amanda Leduc ♿️ &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/AmandaLeduc&quot;&gt;@AmandaLeduc&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/AmandaLeduc/status/1300083052710899712&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;If you wear corrective lenses of any kind, you have a disability. And guess what: your disability has already been accommodated, which is part of why you might not see yourself as disabled.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=1300083052710899712&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;152136 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Aug 30, 2020 02:48:48 (UTC)&quot; href=&quot;https://twitter.com/AmandaLeduc/status/1300083052710899712&quot;&gt;04:48 PM · Aug 30, 2020&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;h2 id=&quot;myth-4%3A-accessibility-is-a-barrier-to-good-design&quot; tabindex=&quot;-1&quot;&gt;Myth 4: Accessibility is a barrier to good design&lt;/h2&gt;
&lt;p&gt;I&#39;ve heard this one a lot. And as a web developer I feel like I’m often turning around to designers and saying “Sorry, I can’t do that, because it’s not accessible”. (The best designers will then turn around and say, &amp;quot;okay, let&#39;s find something that works better.&amp;quot;)&lt;/p&gt;
&lt;p&gt;It’s easy to imagine that in order for design to be truly accessible you have to build sites that look like the &lt;a href=&quot;http://info.cern.ch/hypertext/WWW/TheProject.html&quot;&gt;first-ever web page&lt;/a&gt;, but that’s not the case.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/accessibility-myths/accessible-web-page.png&quot; alt=&quot;A screenshot of the first ever web page on cern.ch: white background, black text, blue hyperlinks, no styling whatsoever.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Is this... accessible design?&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The reality is that accessible design &lt;em&gt;is&lt;/em&gt; good design - and vice versa.&lt;/p&gt;
&lt;p&gt;When it comes down to it, can we really call a design good if it doesn’t work for everyone? You can build the sleekest, prettiest user interface, but if someone who uses the keyboard to get around the internet can’t see what they’re doing, are we really going to call that good design?&lt;/p&gt;
&lt;p&gt;As Jessie Hausler, the Director of Product Accessibility at Salesforce, wrote in his article &lt;em&gt;&lt;a href=&quot;https://medium.com/salesforce-ux/7-things-every-designer-needs-to-know-about-accessibility-64f105f0881b&quot;&gt;7 Things Every Designer Needs to Know about Accessibility&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Accessibility will not force you to make a product that is ugly, boring, or cluttered. It will introduce a set of constraints to incorporate as you consider your design.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If we can work within the constraints of the technology we&#39;re building for, or the constraints of what&#39;s in style, we can work within the constraints of accessible design.&lt;/p&gt;
&lt;h2 id=&quot;myth-5%3A-accessibility-is-hard-to-implement&quot; tabindex=&quot;-1&quot;&gt;Myth 5: Accessibility is hard to implement&lt;/h2&gt;
&lt;p&gt;This one has a grain of truth in: accessibility can be difficult to implement &lt;em&gt;retrospectively&lt;/em&gt;. If you&#39;ve built an entire web app without considering accessibility, it can take a lot of time (and cost money) to go back and fix it up so that it&#39;s accessible.&lt;/p&gt;
&lt;p&gt;But if you consider accessibility from the &lt;em&gt;start&lt;/em&gt;, factoring it into your designs and the way you write your code, it doesn&#39;t have to be difficult. Accessibility by default is a lot easier than accessibility after the fact.&lt;/p&gt;
&lt;p&gt;As web developers, by sticking to some best practices in HTML we&#39;re already halfway there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;using semantic HTML elements such as &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; to mark up the different parts of the document (I&#39;ll write more about this soon!)&lt;/li&gt;
&lt;li&gt;using &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; for buttons with &lt;code&gt;onclick&lt;/code&gt; attributes, and &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; for links to different pages (and not adding &lt;code&gt;onclick&lt;/code&gt; attributes to anything except buttons!)&lt;/li&gt;
&lt;li&gt;nesting headings correctly, from &lt;code&gt;h1&lt;/code&gt; through to &lt;code&gt;h6&lt;/code&gt; , with only one &lt;code&gt;h1&lt;/code&gt; on the page&lt;/li&gt;
&lt;li&gt;keeping HTML tags for markup, and using CSS for style (rather than, say, using a &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; tag because you want big text)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many of the things that will help some groups of users with access needs will also benefit others: for example, good semantic HTML is great for screenreader users, but also helpful for keyboard or &lt;a href=&quot;https://gettecla.com/blogs/news/introduction-to-assistive-switches&quot;&gt;adaptive switch&lt;/a&gt; users, as with the right tags the browser knows what should be focusable and what shouldn&#39;t. Labels on forms make them easier to read and understand for people of all cognitive abilities, and they are good for screenreader users too.&lt;/p&gt;
&lt;p&gt;Add an accessibility checklist to your JIRA tickets or pull request templates: make it part of your definition of done. Look out for best practices in your code reviews.&lt;/p&gt;
&lt;h2 id=&quot;myth-6%3A-react-apps-are-inherently-inaccessible&quot; tabindex=&quot;-1&quot;&gt;Myth 6: React apps are inherently inaccessible&lt;/h2&gt;
&lt;p&gt;I seem to follow two camps of people on Twitter: people in the React community, and people who hate the React community. I am by no means a hardcore React stan (and I think the community can be as toxic as any popular programming language/framework community can be) but I use it every day at work and I think it&#39;s just as good as some of the alternatives out there.&lt;/p&gt;
&lt;p&gt;One of the arguments against React that I hear most frequently is that React produces inaccessible websites which are &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s all the way down. &lt;strong&gt;It doesn&#39;t.&lt;/strong&gt; If React apps are a mess of un-semantic &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s, it&#39;s because the developer put them there. The issue is not with the framework, but the lack of semantic HTML knowledge of the developers who use it: you can write any HTML you like in JSX.&lt;/p&gt;
&lt;p&gt;Ultimately, screen readers tend to ignore &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; components, as they&#39;re generic containers. If we use semantic HTML elements for the actual content of the page, there shouldn&#39;t be a problem at all from a markup perspective.&lt;/p&gt;
&lt;p&gt;React components can&#39;t return more than one element, so with older versions of React you had to wrap multiple elements in a container &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;. This would have added a few extra containers to the page. But the introduction of &lt;a href=&quot;https://reactjs.org/docs/fragments.html&quot;&gt;React Fragments&lt;/a&gt; solved that, and usually doesn&#39;t result in any additional elements being added to the DOM.&lt;/p&gt;
&lt;p&gt;Another thing to watch out for is screen readers not alerting users when content on the page changes. This isn&#39;t a React problem specifically but a &lt;a href=&quot;https://codeburst.io/building-accessible-single-page-apps-2ea3e4fbbc01&quot;&gt;single-page application (SPA) problem&lt;/a&gt;, and it can be solved with ARIA live regions. You&#39;d still have this problem if you built your app in vanilla JavaScript.&lt;/p&gt;
&lt;p&gt;Ideally, your SPA should also work with JavaScript turned off - with React we have tools like &lt;a href=&quot;https://localghost.dev/blog/7-myths-designers-and-developers-believe-about-web-accessibility/nextjs.org/&quot;&gt;Next.js&lt;/a&gt; which produce isomorphic (server- and client-side) applications.&lt;/p&gt;
&lt;h2 id=&quot;myth-7%3A-automated-testing-will-catch-all-accessibility-problems&quot; tabindex=&quot;-1&quot;&gt;Myth 7: Automated testing will catch all accessibility problems&lt;/h2&gt;
&lt;p&gt;People love to show off their Lighthouse scores, don&#39;t they?&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/accessibility-myths/lighthouse-badges.png&quot; alt=&quot;A screenshot of a github repo that offers Lighthouse badges for your repository or website so you can brag about your site&#39;s awesome Lighthouse performance&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Is it though?&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://developers.google.com/web/tools/lighthouse/&quot;&gt;Lighthouse&lt;/a&gt; is an open-source automated testing tool that you can run as a Node module, from the CLI, from Chrome or as part of your CI checks. It checks for performance, accessibility, progressive web app performance, best practices and SEO. It&#39;s a great tool, but unfortunately it&#39;s often treated as a silver bullet. A high Lighthouse score is a good thing, but it doesn&#39;t mean that you&#39;ve &amp;quot;done&amp;quot; accessibility - there are always things that Lighthouse won&#39;t be able to detect.&lt;/p&gt;
&lt;p&gt;The best way to test accessibility is to approach it from all sides. Automated tooling such as Lighthouse or &lt;a href=&quot;https://www.deque.com/axe/&quot;&gt;axe&lt;/a&gt;) can and should be part of your development process, as it&#39;ll provide a quick feedback loop for common accessibility problems in your markup and CSS. But what these tools don&#39;t account for are things like the quirks of different screenreader software (and boy, do they have quirks), or the other kinds of assistive technology people will use to access your website. Lighthouse can&#39;t tell you whether your site is still legible when it&#39;s zoomed in 600%, or whether you can interact with the various parts of the app with a keyboard as you would with a mouse. The Accessibility in Government blog has a great article about &lt;a href=&quot;https://accessibility.blog.gov.uk/2017/02/24/what-we-found-when-we-tested-tools-on-the-worlds-least-accessible-webpage/&quot;&gt;what they found when they tested automated tooling on the world&#39;s least accessible webpage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before you merge your PR, check how your new feature behaves with screenreaders: Macs and iPhones come with &lt;a href=&quot;https://www.apple.com/uk/accessibility/iphone/vision/&quot;&gt;VoiceOver&lt;/a&gt;, Android has &lt;a href=&quot;https://support.google.com/accessibility/android/answer/6283677?hl=en&quot;&gt;TalkBack&lt;/a&gt;, Linux has &lt;a href=&quot;https://help.gnome.org/users/orca/stable/introduction.html.en&quot;&gt;Orca&lt;/a&gt;, and you can download the open-source &lt;a href=&quot;https://www.nvaccess.org/download/&quot;&gt;NVDA&lt;/a&gt; screenreader for Windows. Does it read out everything it&#39;s supposed to? Is it reading out anything it&#39;s &lt;em&gt;not&lt;/em&gt; supposed to? Are the headings in the right order?&lt;/p&gt;
&lt;p&gt;Ultimately, there’s no substitute for getting people with actual access needs to use the website or app. You can do some user testing, commission a formal audit, and/or make sure you have ways for users to give you feedback. Include disabled users in your UX research upfront, as well, so that you&#39;re building something accessible right from the start.&lt;/p&gt;
&lt;h2 id=&quot;it&#39;s-your-turn&quot; tabindex=&quot;-1&quot;&gt;It&#39;s your turn&lt;/h2&gt;
&lt;p&gt;If you encounter any of these myths, &lt;strong&gt;you can (and should) challenge them&lt;/strong&gt;. A lot of the time, these myths stick around because accessibility just isn&#39;t being talked about. Be the one to bring it up, and get others on board too. Bake accessibility into your design systems and your ways of working.&lt;/p&gt;
&lt;h2 id=&quot;resources-%26-further-reading&quot; tabindex=&quot;-1&quot;&gt;Resources &amp;amp; further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.microsoft.com/design/inclusive/&quot;&gt;Microsoft Inclusive Design Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/salesforce-ux/7-things-every-designer-needs-to-know-about-accessibility-64f105f0881b&quot;&gt;7 Things Every Designer Needs to Know about Accessibility - Jessie Hausler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.deque.com/accessible-design/&quot;&gt;Deque - Accessible Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.deque.com/accessible-development/&quot;&gt;Deque - Accessible Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://marcysutton.com/&quot;&gt;Marcy Sutton&lt;/a&gt; - blog posts and talks from an accessibility expert&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://accessibility.blog.gov.uk/2017/02/24/what-we-found-when-we-tested-tools-on-the-worlds-least-accessible-webpage/&quot;&gt;What we found when we tested tools on the world&#39;s least accessible webpage&lt;/a&gt; - Accessibility in Government Blog&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  <entry>
    <title>Defending yourself against cross-site scripting attacks with Content-Security-Policy</title>
    <link href="https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/"/>
    <updated>2020-05-03T00:00:00Z</updated>
    <id>https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/</id>
    <content type="html">&lt;p&gt;I spent an entire day last week wrestling with a PDF-rendering library in React which was refusing to work in production. Locally it ran just fine, but as soon as we built our app in production mode, it wasn&#39;t doing anything. Looking at the console, the errors it was spitting out made my heart sink. I&#39;d seen these before.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&quot;https://localghost.dev/img/blog/csp/eval-error.png&quot;&gt;&lt;img src=&quot;https://localghost.dev/img/blog/csp/eval-error.png&quot; alt=&quot;Console error: Refused to evaluate a string as JavaScript because &#39;unsafe-eval&#39; is not an allowed source of script in the following Content Security Policy directive: script-src &#39;self&#39;.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/a&gt;&lt;figcaption&gt;The dreaded console error&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;This was an error caused by our &lt;code&gt;Content-Security-Policy&lt;/code&gt; (CSP) header, telling our browser that something in the library should be blocked - specifically, an &lt;code&gt;eval()&lt;/code&gt; function within one of the dependencies of our PDF-rendering library. I did what any self-respecting developer would do and complained at anyone who would listen - okay, I posted on Twitter - and then discovered that a lot of other developers weren&#39;t aware of what CSP was or what it was for. So I thought I&#39;d write a post about it.&lt;/p&gt;
&lt;p&gt;The error messages I was getting were protecting me against a common web security vulnerability - &lt;strong&gt;cross-site scripting attacks&lt;/strong&gt; (XSS). As a web developer, it&#39;s really important to be aware of what XSS is and how to prevent it.&lt;/p&gt;
&lt;h2 id=&quot;contents&quot; tabindex=&quot;-1&quot;&gt;Contents &lt;!-- omit in toc --&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#cross-site-scripting-xss&quot;&gt;Cross-site scripting (XSS)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#stored-xss&quot;&gt;Stored XSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#reflected-xss&quot;&gt;Reflected XSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#dom-based-xss&quot;&gt;DOM-based XSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#preventing-xss&quot;&gt;Preventing XSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#content-security-policy-is-a-set-of-rules-about-permitted-content-on-a-website&quot;&gt;Content-Security-Policy is a set of rules about permitted content on a website&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#fetch-directives&quot;&gt;Fetch directives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#document-directives&quot;&gt;Document directives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#navigation-directives&quot;&gt;Navigation directives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#unsafe-inline-and-the-risks-of-inline-styles&quot;&gt;&lt;code&gt;unsafe-inline&lt;/code&gt; and the risks of inline styles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#scripts-unsafe-inline-and-unsafe-eval-why-eval-is-evil&quot;&gt;Scripts, &lt;code&gt;unsafe-inline&lt;/code&gt; and &lt;code&gt;unsafe-eval&lt;/code&gt;: why &lt;code&gt;eval()&lt;/code&gt; is evil&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#how-to-create-a-csp-header&quot;&gt;How to create a CSP header&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#adding-to-a-csp-header&quot;&gt;Adding to a CSP header&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#styled-components-and-unsafe-inline&quot;&gt;styled-components and &lt;code&gt;unsafe-inline&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#environment-based-csp&quot;&gt;Environment-based CSP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#the-moral-of-the-story&quot;&gt;The moral of the story&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#references--further-reading&quot;&gt;References &amp;amp; further reading&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;cross-site-scripting-(xss)&quot; tabindex=&quot;-1&quot;&gt;Cross-site scripting (XSS)&lt;/h2&gt;
&lt;p&gt;XSS involves someone injecting malicious code into an unsuspecting website, which then executes on the victim&#39;s computer.&lt;/p&gt;
&lt;p&gt;This injected code can do things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;copy your cookies and send them to the attacker&lt;/li&gt;
&lt;li&gt;get information about your location or data from your webcam etc&lt;/li&gt;
&lt;li&gt;grab session tokens from local storage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On websites that store sensitive information, such as banking or shopping websites, XSS vulnerabilities could allow someone to impersonate you by stealing your access token and using it to log in as you - which means gold-plated toilet seats for them, and a nice credit card bill for you.&lt;/p&gt;
&lt;p&gt;The Open Web Application Security Project (OWASP) recognises three different methods of XSS: &lt;strong&gt;stored&lt;/strong&gt;, &lt;strong&gt;reflected&lt;/strong&gt; and &lt;strong&gt;DOM-based&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;stored-xss&quot; tabindex=&quot;-1&quot;&gt;Stored XSS&lt;/h3&gt;
&lt;p&gt;Stored XSS refers to malicious code sent in the server response from something like a database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: on a website allowing people to submit comments to discuss news articles, a user submits the following comment:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Great stuff guys!&amp;lt;script&amp;gt;/* sneaky code */&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the website isn&#39;t sanitizing any user input (stripping it of any HTML tags) and is rendering the comment directly into the DOM, that script will execute as soon as you load the page it&#39;s on. Before you know it, your browser has posted comments all over the site declaring your support for some deeply unpleasant organisation.&lt;/p&gt;
&lt;p&gt;There&#39;s a really interesting &lt;a href=&quot;https://darknetdiaries.com/episode/61/&quot;&gt;episode of the podcast Darknet Diaries&lt;/a&gt; featuring Samy, the (accidental) creator of a MySpace worm that used XSS to get people&#39;s profiles to automatically add him as a friend. This is a great example of stored XSS, because it all started with something he posted on his own profile (which was then stored in MySpace&#39;s database).&lt;/p&gt;
&lt;h3 id=&quot;reflected-xss&quot; tabindex=&quot;-1&quot;&gt;Reflected XSS&lt;/h3&gt;
&lt;p&gt;This is where malicious user input in a request is sent back in the immediate server response, executing on the receiving client&#39;s browser.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: someone posts a link online to a shopping website, with a search term in the URL so it takes you directly to the catalog page. But they&#39;ve also included some &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags in the query string.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://niche-tshirts.com/shirts?q=extreme+ironing&amp;lt;script&amp;gt;/* sneaky code */&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;When the server receives the request, it takes the entire query string and uses that as the search parameter. In the HTML that it returns, it renders:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;You searched for: amateur paleontology&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* sneaky code */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, your poor unsuspecting browser will execute what&#39;s between those script tags, and the attacker will be able to gain access to your access token and anything else they&#39;ve managed to scrape.&lt;/p&gt;
&lt;h3 id=&quot;dom-based-xss&quot; tabindex=&quot;-1&quot;&gt;DOM-based XSS&lt;/h3&gt;
&lt;p&gt;Finally, DOM-based XSS is when JavaScript running on the page uses data from somewhere the attacker can control, such as &lt;code&gt;window.location&lt;/code&gt; (the URL of the page). Say we have some JS on our page which takes &lt;code&gt;window.location&lt;/code&gt; and then executes some function with it:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://niche-tshirts.com/shirts?q=spelunking&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; params &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URLSearchParams&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;search&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; searchTerm &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;q&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;p&gt;You searched for: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;searchTerm&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/p&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If our attacker from before sends another link with the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags in the query string, these will be rendered into the DOM when the browser sets the inner HTML content of the &lt;code&gt;#content&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;Unlike the previous two examples, this all happens client-side - the server isn&#39;t involved at all.&lt;/p&gt;
&lt;h3 id=&quot;preventing-xss&quot; tabindex=&quot;-1&quot;&gt;Preventing XSS&lt;/h3&gt;
&lt;p&gt;Some of the methods we can use to prevent XSS attacks on our websites include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sanitizing user input, making sure there are no HTML tags in it&lt;/li&gt;
&lt;li&gt;escape certain characters (like &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;amp;&lt;/code&gt;, and &lt;code&gt;&amp;quot;&lt;/code&gt;) with HTML entity encoding (e.g. &lt;code&gt;&amp;amp;amp;&lt;/code&gt; for &amp;amp;) to prevent them being executed&lt;/li&gt;
&lt;li&gt;not rendering arbitrary content from the server as HTML - render it as plain text&lt;/li&gt;
&lt;li&gt;check the Content-Type is correct - only &lt;code&gt;text/html&lt;/code&gt; if you are &lt;em&gt;definitely&lt;/em&gt; returning HTML&lt;/li&gt;
&lt;li&gt;use &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies&quot;&gt;HttpOnly cookies&lt;/a&gt; for sensitive data so that the JavaScript &lt;code&gt;Document.cookie&lt;/code&gt; API can&#39;t access them&lt;/li&gt;
&lt;li&gt;and... set up a &lt;code&gt;Content-Security-Policy&lt;/code&gt; header!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;content-security-policy-is-a-set-of-rules-about-permitted-content-on-a-website&quot; tabindex=&quot;-1&quot;&gt;Content-Security-Policy is a set of rules about permitted content on a website&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Content-Security-Policy&lt;/code&gt; is an additional layer of security on a site, preventing things like malicious scripts from being run by defining strict rules about what content you can and can&#39;t have on a website. It can be one of the HTTP headers that we can send from the web server to the client (browser), or a meta tag in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of an HTML page. A browser will read the CSP and check whether the scripts, stylesheets and various other resources it&#39;s executing or displaying conform to the rules in the policy. If not, it won&#39;t load them.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/csp/gandalf.png&quot; alt=&quot;Gandalf from Lord of the Rings saying &#39;you shall not pass&#39;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;CSP is basically Browser Gandalf.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;A CSP meta tag may look a bit like this, for a site with Google Analytics and some Twitter/Facebook embeds, and images from a CDN:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Content-Security-Policy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;default-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; manifest-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; prefetch-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; worker-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; object-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; font-src *; connect-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://www.google-analytics.com; img-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://some-cdn.com; script-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://platform.twitter.com https://www.google-analytics.com https://connect.facebook.net https://staticxx.facebook.com; style-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://platform.twitter.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/csp/csp-error.png&quot; alt=&quot;Console error: Refused to load the script &#39;http://evil.example.com/evil.js&#39; because it violates the following Content Security Policy directive: script-src &#39;self&#39; https://apis.google.com&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;An example Content-Security-Policy error from Google&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The CSP header or meta tag content is always a string containing a semicolon-separated list of rules.&lt;/p&gt;
&lt;p&gt;A policy has a list of &lt;strong&gt;directives&lt;/strong&gt; which are usually suffixed with &lt;code&gt;-src&lt;/code&gt;, and refer to different kinds of rules for resources and content on the page.&lt;br /&gt;
Some common categories of directive are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#fetch-directives&quot;&gt;fetch directives&lt;/a&gt;: which resource types may be loaded, and where from&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#document-directives&quot;&gt;document directives&lt;/a&gt;: what properties the document or worker may have&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/defending-yourself-against-cross-site-scripting-attacks-with-content-security-policy/#navigation-directives&quot;&gt;navigation directives&lt;/a&gt;: where a user on the page can navigate to/submit a form to&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next to each directive we specify one or more permitted &lt;strong&gt;sources&lt;/strong&gt; for each of these directives.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;script-src: &#39;self&#39; https://othersite.com;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- directive: source source; --&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I won&#39;t go through every single directive - there are a lot - but I&#39;ll outline some of the most common ones, and what rules they might enforce. Plus, the good old caveat that Internet Explorer only supports &lt;em&gt;one&lt;/em&gt; directive (&lt;code&gt;sandbox&lt;/code&gt;), and that&#39;s with the legacy &lt;code&gt;X-Content-Security-Policy&lt;/code&gt; header.&lt;/p&gt;
&lt;p&gt;While the HTTP header and meta tags are mostly the same, the main differences are that HTTP headers have wider browser support, support all of the directives (meta tags support &lt;em&gt;most&lt;/em&gt; of the directives) and may be cached by proxies (meta tags won&#39;t be).&lt;/p&gt;
&lt;p&gt;As long as you&#39;re employing multiple methods of defence against XSS, including CSP, you can protect yourself (yes, &lt;em&gt;even&lt;/em&gt; in IE). It&#39;s important to emphasise here that CSP is &lt;em&gt;one way&lt;/em&gt; of protecting your website against XSS - it&#39;s not enough on its own.&lt;/p&gt;
&lt;h3 id=&quot;fetch-directives&quot; tabindex=&quot;-1&quot;&gt;Fetch directives&lt;/h3&gt;
&lt;p&gt;These directives govern which resource types may be loaded, and where from. Things like images, scripts, styles and frames will be defined here.&lt;/p&gt;
&lt;p&gt;Any of these directives may also have a wildcard value (&lt;code&gt;*&lt;/code&gt;), which basically means &amp;quot;anything goes&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;image-src&lt;/code&gt;: Permitted sources for any images/favicons on the page.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;script-src&lt;/code&gt;: Permitted sources for any JavaScript on the page.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;style-src&lt;/code&gt;: What kind of CSS it&#39;s allowed to load, and where from.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;font-src&lt;/code&gt;: where fonts specified by the CSS &lt;code&gt;@font-face&lt;/code&gt; rule may be fetched from (e.g. Google Fonts)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;frame-src&lt;/code&gt;: where iframes may load content from (e.g. Stripe elements)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;connect-src&lt;/code&gt;: hosts that your JavaScript may make requests to (e.g. an API, with &lt;code&gt;fetch&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;default-src&lt;/code&gt;: the fallback if any of the rules don&#39;t match the resource&lt;/p&gt;
&lt;h3 id=&quot;document-directives&quot; tabindex=&quot;-1&quot;&gt;Document directives&lt;/h3&gt;
&lt;p&gt;Document directives restrict the use of plugins (such as with &lt;code&gt;&amp;lt;embed&amp;gt;&lt;/code&gt;) and let us enable sandbox mode.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;plugin-types&lt;/code&gt;: allows you to define permitted &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types&quot;&gt;MIME types&lt;/a&gt; for embedded media and elements using &lt;code&gt;&amp;lt;embed&amp;gt;&lt;/code&gt; tags. These days, you rarely need to use &lt;code&gt;embed&lt;/code&gt;, so I don&#39;t expect you&#39;ll come across this one very much.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sandbox&lt;/code&gt;: literally the only directive that IE supports! This allows you to restrict the browser environment on the page, effectively blocking &lt;em&gt;everything&lt;/em&gt; - popups, scripts, forms, you name it. It has different sources from the rest of the directives - you can specify exactly what should be enabled in sandbox mode. Take a look at the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox&quot;&gt;MDN documentation on sandbox&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h3 id=&quot;navigation-directives&quot; tabindex=&quot;-1&quot;&gt;Navigation directives&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;form-action&lt;/code&gt;: if you&#39;re using traditional HTML forms with &lt;code&gt;action&lt;/code&gt; attributes, this directive specifies the URIs you&#39;re allowed to submit to.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;frame-ancestors&lt;/code&gt;: specifies which pages or URIs are allowed to embed iframes and other frame/embeddable content.&lt;/p&gt;
&lt;h3 id=&quot;sources&quot; tabindex=&quot;-1&quot;&gt;Sources&lt;/h3&gt;
&lt;p&gt;Most directives have the same possible list of sources. With the exception of &lt;strong&gt;host source&lt;/strong&gt; and &lt;strong&gt;scheme source&lt;/strong&gt;, they are all specified in single quotes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#39;self&#39;&lt;/code&gt; - anything from the same host is fine. So a CSP for localghost.dev with &lt;code&gt;image-src: &#39;self&#39;&lt;/code&gt; and &lt;code&gt;script-src: &#39;self&#39;&lt;/code&gt; would be allowed to display images and run scripts from localghost.dev.&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;host source&lt;/strong&gt; : external hosts that the resource can come from.
&lt;ul&gt;
&lt;li&gt;For example, &lt;code&gt;style-src: &amp;quot;https://myhost.com&amp;quot;&lt;/code&gt; allows you to include a stylesheet from &lt;a href=&quot;http://myhost.com/&quot;&gt;myhost.com&lt;/a&gt;, e.g. &lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://myhost.com/style.css&amp;quot;/&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you often use content delivery networks (CDNs), you&#39;ll need to specify them here. You can also use &lt;strong&gt;wildcards&lt;/strong&gt; for the subdomain of the URL, and restrict things to specific &lt;strong&gt;ports&lt;/strong&gt; as well. The &lt;strong&gt;protocol&lt;/strong&gt; matters, so a host source with &lt;code&gt;https://&lt;/code&gt; will not allow anything from &lt;code&gt;http://&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;e.g. &lt;code&gt;connect-src: &#39;self&#39; https://*.localghost.dev&lt;/code&gt; will allow anything over HTTPS from a subdomain of this site.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;scheme source&lt;/strong&gt;: what scheme (protocol) it&#39;s okay to fetch resources from. Chiefly &lt;code&gt;https:&lt;/code&gt; or &lt;code&gt;http:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&#39;unsafe-inline&#39;&lt;/code&gt;: whether inline &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;/&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags are allowed. I&#39;ve only really used this for &lt;code&gt;script-src&lt;/code&gt; and &lt;code&gt;style-src&lt;/code&gt; before. I&#39;ll talk more about why inline style and script tags are a security risk later in the article.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&#39;unsafe-eval&#39;&lt;/code&gt;: whether or not JS is allowed to use the &lt;code&gt;eval()&lt;/code&gt; function, which executes arbitrary code from whatever string is passed in. I&#39;ll go into more detail about why this is a bad thing in a later section.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nonce&lt;/code&gt; - you may specify an &lt;strong&gt;unguessable&lt;/strong&gt; cryptographic nonce (a base-64 encoded string) which you can then pass into inline styles or scripts as an attribute to allow them to load on the page. This means you can use inline &lt;code&gt;&amp;lt;style nonce=&amp;quot;mysecretstring&amp;quot;&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags without indiscriminately allowing &lt;em&gt;all&lt;/em&gt; inline styles - effectively marking only a specific set of inline styles as &amp;quot;safe&amp;quot;. This &lt;strong&gt;must&lt;/strong&gt; be randomly generated and unguessable, otherwise it&#39;s basically pointless as anyone can guess the hash and pop it in their injected scripts.&lt;/li&gt;
&lt;li&gt;hashes - e.g. &lt;code&gt;sha256-&amp;lt;your hash value&amp;gt;&lt;/code&gt;. This is a base64-encoded representation of your inline styles or scripts, so the browser can check the hash against its own hash of the &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;/&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; to make sure it&#39;s the real deal. Anything that doesn&#39;t match the hash will be ignored. Hashes are static, while nonces are generated server-side on every page load.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;none&lt;/code&gt; - no URLs match, no nothing may be loaded at all. For example, I don&#39;t use iframes on this site at all, so I&#39;d have &lt;code&gt;frame-src: none&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;unsafe-inline-and-the-risks-of-inline-styles&quot; tabindex=&quot;-1&quot;&gt;&lt;code&gt;unsafe-inline&lt;/code&gt; and the risks of inline styles&lt;/h3&gt;
&lt;p&gt;But why would we have to explicitly enable &lt;code&gt;unsafe-inline&lt;/code&gt; for &lt;code&gt;style-src&lt;/code&gt;, and why are inline &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tags considered &amp;quot;unsafe&amp;quot;?&lt;/p&gt;
&lt;p&gt;There are actually a few vulnerabilities that can be triggered using CSS. They&#39;re rare and, yes, less harmful than JS-based XSS attacks, but it&#39;s still worth protecting yourself against them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;messing up your site&#39;s styles - on a big-name website or app, this can cause reputational damage&lt;/li&gt;
&lt;li&gt;injecting styles into the page to add unsolicited content or offensive text&lt;/li&gt;
&lt;li&gt;disguising user-generated content to look like official content, e.g. a fake login link&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these can be prevented with &lt;code&gt;unsafe-inline&lt;/code&gt;, meaning the browser will only pay attention to the styles from your defined stylesheets.&lt;/p&gt;
&lt;p&gt;Ultimately, allowing &lt;code&gt;unsafe-inline&lt;/code&gt; is a calculated risk: if you really can&#39;t get around it with a nonce or a hash, then you can enable this knowing that you are introducing a slight vulnerability, but it&#39;s highly unlikely to be anything super severe.&lt;/p&gt;
&lt;p&gt;There&#39;s a helpful &lt;a href=&quot;https://stackoverflow.com/a/31759553&quot;&gt;StackOverflow answer&lt;/a&gt; which explains this in more detail.&lt;/p&gt;
&lt;h3 id=&quot;scripts%2C-unsafe-inline-and-unsafe-eval%3A-why-eval()-is-evil&quot; tabindex=&quot;-1&quot;&gt;Scripts, &lt;code&gt;unsafe-inline&lt;/code&gt; and &lt;code&gt;unsafe-eval&lt;/code&gt;: why &lt;code&gt;eval()&lt;/code&gt; is evil&lt;/h3&gt;
&lt;p&gt;While enabling &lt;code&gt;unsafe-inline&lt;/code&gt; for styles is not the end of the world, it&#39;s a bad idea to allow it for scripts. A lot of harm can be done with an inline script that&#39;s been injected into your code - with a &lt;code&gt;connect-src&lt;/code&gt; directive defined as well it would mean that that script couldn&#39;t connect to any other sources, but it could still cause havoc, such as pretending to be you and updating user-generated content.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;eval()&lt;/code&gt;, on the other hand, should be avoided at all costs. It takes a string as a parameter, and blindly executes it as Javascript. There&#39;s literally a section in the MDN article about &lt;code&gt;eval()&lt;/code&gt; called &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Never_use_eval!&quot;&gt;&amp;quot;Never use eval()!&amp;quot;&lt;/a&gt;. This opens up a whole host of security vulnerabilities - if &lt;code&gt;unsafe-eval&lt;/code&gt; is enabled, anyone can execute arbitrary code in your application. Yikes.&lt;/p&gt;
&lt;h2 id=&quot;how-to-create-a-csp-header&quot; tabindex=&quot;-1&quot;&gt;How to create a CSP header&lt;/h2&gt;
&lt;p&gt;In a static site, you can add a meta tag to your site&#39;s &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Content-Security-Policy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;default-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; manifest-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; prefetch-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; worker-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; object-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; font-src *; connect-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://www.google-analytics.com; img-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://some-cdn.com; script-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;sha256-flsjfljlkfjaspdjfsdkgs&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://platform.twitter.com https://www.google-analytics.com https://connect.facebook.net https://staticxx.facebook.com; style-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;nonce-adsfasdfasfsadf&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; https://platform.twitter.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&#39;re running an app with an Express server, you can easily set it as one of the response headers with &lt;code&gt;helmet-csp&lt;/code&gt; - check out the &lt;a href=&quot;https://helmetjs.github.io/docs/csp/&quot;&gt;Helmet docs&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;The safest method is to have the most restrictive CSP possible, and only add new sources if you&#39;re completely sure. Include a &lt;code&gt;default-src: &#39;none&#39;&lt;/code&gt; so that if no rule matches a resource, it will be blocked.&lt;/p&gt;
&lt;h2 id=&quot;adding-to-a-csp-header&quot; tabindex=&quot;-1&quot;&gt;Adding to a CSP header&lt;/h2&gt;
&lt;p&gt;When is it safe to add new sources to a CSP header? Perhaps you&#39;ve included an image or stylesheet in your code, and your browser is refusing to render it because it violates the CSP. Before adding the URL as a source, consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;do you trust this site?&lt;/li&gt;
&lt;li&gt;how specific can you make the URI? (avoid wildcards unless it&#39;s a host you control)&lt;/li&gt;
&lt;li&gt;could you host the file on an already approved source?&lt;/li&gt;
&lt;li&gt;could you add the CSS file to your repo instead?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;styled-components-and-unsafe-inline&quot; tabindex=&quot;-1&quot;&gt;styled-components and &lt;code&gt;unsafe-inline&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If you&#39;re using &lt;code&gt;styled-components&lt;/code&gt;, which renders &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tags into the page, rather than enabling &lt;code&gt;unsafe-inline&lt;/code&gt; for styles you can define a nonce by setting it as a Webpack global (&lt;code&gt;__webpack_nonce__&lt;/code&gt;). The caveats: this is apparently undocumented, and only works with server-side rendered code. So you might have to enable &lt;code&gt;unsafe-inline&lt;/code&gt; for that one.&lt;/p&gt;
&lt;h3 id=&quot;environment-based-csp&quot; tabindex=&quot;-1&quot;&gt;Environment-based CSP&lt;/h3&gt;
&lt;p&gt;If you run different environments for development and production, you may want to consider serving different CSP headers for different environments. For example, your &lt;code&gt;image-src&lt;/code&gt; directive might point to a non-prod CDN if &lt;code&gt;process.env.NODE_ENV !== &#39;production&lt;/code&gt;, but the production CDN otherwise. Similarly, if you use a local server at &lt;code&gt;localhost:6060&lt;/code&gt; as an API for development but your production app points to a hosted API somewhere else, you might want to add &lt;code&gt;localhost:6060&lt;/code&gt; to your CSP &lt;em&gt;only for the development environment&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There are some frameworks, such as Hugo and Next.JS, which rely on inline scripts for hot reloading. In this case, it&#39;s fine to add &lt;code&gt;unsafe-inline&lt;/code&gt; to your &lt;code&gt;script-src&lt;/code&gt; &lt;strong&gt;in development&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example, if you use Hugo and want to enable live reloading with your CSP, as well as scripts imported from the site itself, you can use &lt;code&gt;.Site.IsServer&lt;/code&gt; (though this only works if you use server mode for development and not production):&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Content-Security-Policy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;default-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;; [...] script-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt; {{ if eq .Site.IsServer true }}&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;unsafe-inline&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;{{ end}} {{ .Site.BaseURL }};&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;the-moral-of-the-story&quot; tabindex=&quot;-1&quot;&gt;The moral of the story&lt;/h2&gt;
&lt;p&gt;So, how did I get around the &lt;code&gt;unsafe-eval&lt;/code&gt; warnings I was seeing in the console?&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/csp/ron-swanson.webp&quot; alt=&quot;A gif of Ron Swanson throwing his computer into a dumpster&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;Unfortunately... the only solution was to chuck out that library and find something else. There are no workarounds for a library that uses &lt;code&gt;eval&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When adding a CSP header to a site, start out with the principle of least privilege: only permit &lt;em&gt;exactly&lt;/em&gt; what you need, nothing more. When in doubt, be overly restrictive, and see what console errors you&#39;re getting.&lt;/p&gt;
&lt;p&gt;If you&#39;re working on a site or app that has a CSP header set, don&#39;t be tempted to add sources just to make console errors go away. Make sure you know exactly what you&#39;re allowing.&lt;/p&gt;
&lt;p&gt;And promise me you will never, ever enable &lt;code&gt;unsafe-eval&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;references-%26-further-reading&quot; tabindex=&quot;-1&quot;&gt;References &amp;amp; further reading&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cloudflare.com/learning/security/threats/cross-site-scripting/&quot;&gt;Cloudflare - What is Cross-Site Scripting?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy&quot;&gt;MDN - Content-Security-Policy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting&quot;&gt;MDN - Cross-Site Scripting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/xss/&quot;&gt;OWASP - Cross-Site Scripting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/DOM_Based_XSS&quot;&gt;OWASP - DOM-based XSS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Google&#39;s &lt;a href=&quot;https://csp-evaluator.withgoogle.com/&quot;&gt;CSP Evaluator&lt;/a&gt; can check how watertight your CSP is (but is not exhaustive).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developers.google.com/web/fundamentals/security/csp&quot;&gt;Google Web Fundamentals - CSP&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>ffconf 2019: future friends beside the seaside</title>
    <link href="https://localghost.dev/blog/ffconf-2019-future-friends-beside-the-seaside/"/>
    <updated>2019-11-16T00:00:00Z</updated>
    <id>https://localghost.dev/blog/ffconf-2019-future-friends-beside-the-seaside/</id>
    <content type="html">&lt;p&gt;Now in its 11th year, &lt;a href=&quot;https://ffconf.org/&quot;&gt;ffconf&lt;/a&gt; is one of the biggest events in the conference calendar for web developers across the UK (and further afield). Yet somehow I&#39;ve managed to miss every one since I got into tech, because of some reason or another - last year I was at the week-long blockchain sales pitch that is Web Summit - so I was understandably very excited to finally be going. It takes place at the lovely &lt;a href=&quot;https://www.picturehouses.com/cinema/duke-of-york-s-picturehouse&quot;&gt;Duke of York&#39;s Picturehouse&lt;/a&gt; in Brighton - the first conference I&#39;ve attended that had cupholders in the seats! (Fun fact, I applied for a job there once.)&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054723761_90697f5ae7_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Photo: Trys Mudford&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;One of the best things about attending conferences is seeing friendly faces from the community, and this particular subset of the JS community is so lovely. It does give you hope (and a refreshing break from some of the other conferences and meetups I&#39;ve attended in the past few years which have had 97% more posturing). I spend a lot of time in the London bubble so it&#39;s great to meet folks from other tech communities, and going to the &lt;a href=&quot;https://asyncjs.com/&quot;&gt;Async&lt;/a&gt; meetup the night before was a great way to do that.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054939337_0d28f8a8c9_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;JS (and real-life) friends! (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;(I also got to meet &lt;a href=&quot;https://noopkat.com/&quot;&gt;Suz Hinton&lt;/a&gt; at the afterparty and didn&#39;t make a fool of myself, so that is always a plus. She&#39;s extremely lovely.)&lt;/p&gt;
&lt;p&gt;What made these talks &lt;em&gt;especially&lt;/em&gt; good was that they focused more on people and stories. My favourite kind of conference talk is one where people show something amazing they built, and share their experiences of building it (a good example from JSConf EU 2019 is &lt;a href=&quot;https://www.youtube.com/watch?v=ZsBAkSxwU5c&quot;&gt;Bringing back dialup: the internet over SMS&lt;/a&gt; by Alexandra Sunderland). I don&#39;t need to come away with an exact step-by-step guide on how to do the thing (I&#39;ll never remember it all anyway), and it might not even be a practical thing for me to ever attempt, but I want to know all about it because it&#39;s amazing.&lt;/p&gt;
&lt;p&gt;I&#39;ve been thinking a lot recently about the &lt;em&gt;reasons&lt;/em&gt; that people learn to code - and in fact, I submitted to the ffconf CFP with a talk about this, which I&#39;m going to try and polish up and submit elsewhere. When I started doing web development, I didn&#39;t really know what I was doing or why I was doing it - I thought it&#39;d be cool to make a website, and how else was I going to get my Neopets shop to play music and have a flashy background?&lt;/p&gt;
&lt;p&gt;It seems like a lot of the coding for creativity&#39;s sake has been lost in favour of learning the latest, greatest technology in order to advance your career and to be able to say that you&#39;re using it. I could go on, and I probably will in another blog post, but seeing people up on stage doing ridiculous and beautiful things with code gives me hope for creative coding (and, most importantly, it inspires me to do some too).&lt;/p&gt;
&lt;p&gt;I came home from ffconf and restyled my entire website with ludicrous link effects and a gradient border. It&#39;s not quite making jewellery from SVGs but it&#39;s a start.&lt;/p&gt;
&lt;p&gt;Here&#39;s a bit of what I took away from each of the ffconf talks. I haven&#39;t included many photos because my phone&#39;s camera is atrocious in low light, but I&#39;ve borrowed some nice pictures from the official photos by Trys Mudford on &lt;a href=&quot;https://flickr.com/photos/remysharp/albums/72157711751196107&quot;&gt;Remy Sharp&#39;s Flickr&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;sharon-steed---engaging-empathy&quot; tabindex=&quot;-1&quot;&gt;Sharon Steed - Engaging Empathy&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Empathy: the thing you have to do to not be an asshole in the office.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Opening the conference was author and communications consultant Sharon Steed. She spoke about her experiences of growing up with and living with a stutter - and the difficulties she&#39;s had with others not taking her seriously. She&#39;s a fantastic storyteller, and as she shared with us her challenges and achievements it felt like she was taking us with her on her journey.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054724506_16d5135ec3_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Sharon Steed (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;She compared empathy to love; &amp;quot;the thing everyone understands, but nobody can explain&amp;quot;. It&#39;s intangible, but it&#39;s also a choice: we can &lt;em&gt;choose&lt;/em&gt; to have empathy for others (and we should). (Her tales of new love were accompanied by &lt;em&gt;that&lt;/em&gt; picture of Britney and Justin in denim, which was an all around win for me.)&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ffconf/sharonsteed-1.jpg&quot; alt=&quot;Photo of Sharon Steed giving a conference talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;So, what to take away from Sharon&#39;s talk? We should &lt;strong&gt;foster environments of collaboration and inclusion&lt;/strong&gt;. People need to feel safe in order to speak honestly - having open lines of communication and being transparent from the start will help this. She also pointed out that teams don&#39;t always need to work in the same way: people should be able to do things on their own terms.&lt;/p&gt;
&lt;p&gt;Sharon also described what she called the &amp;quot;Key Empathy Behaviours&amp;quot;: patience, perspective and connection. As long as we are being present and remembering the &lt;strong&gt;why&lt;/strong&gt; of what we&#39;re doing, understanding where others are coming from, and speak for &lt;strong&gt;intention&lt;/strong&gt; and not impact, we&#39;ll be able to engage empathy and make everyone feel like they belong.&lt;/p&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/empathy/&quot;&gt;Engaging Empathy&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;amina-adewusi---what-does-it-take-to-become-a-developer-in-2020%3F&quot; tabindex=&quot;-1&quot;&gt;Amina Adewusi - What does it take to become a developer in 2020?&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;We need a recruitment revolution.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Amina&#39;s talk focused on the barriers to entry for under-represented people in the industry: a topic that has come up time and time again but doesn&#39;t really seem to be getting any better (especially for people of colour).&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054726391_72d4de9b7c_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Amina Adewusi (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Her words were powerful, and the measured way she spoke really conveyed the gravity of what she was saying. In the last 11 years, the proportion of women and non-white students in computer science has not improved: last year, only 20% of computer science students were female, and only 15% were non-white. And a computer science degree is already a privileged platform to launch your career from. What about those who don&#39;t go down that path?&lt;/p&gt;
&lt;p&gt;She spoke of the generosity of strangers: the bootcamp alumni who all answered her questions when she contacted them out of the blue, happy to give advice. And while bootcamps are a great way to fast-track your career into tech, they&#39;re also very exclusionary for anyone with caring responsibilities, and they can be very expensive. She spoke of her experiences raising a baby while also learning to code, which frankly blew my mind - learning to code is really hard (don&#39;t let anyone tell you otherwise!) so to do that while also looking after a very young child is just phenomenal.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ffconf/aminaadewusi-1.jpg&quot; alt=&quot;Photo of Amina Adewusi giving a conference talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;For those who self-teach, it&#39;s hard to get a job once you&#39;ve learned the skills. More often than not, recruitment is unforgiving, with high expectations, long interview processes and unreasonable deadlines (Amina recalled being sent a tech test on a Friday, with the expectation she&#39;d send it back on the Monday!). It&#39;s not just the time it takes, either - the interview process can be very intimidating and sometimes discriminatory.&lt;/p&gt;
&lt;p&gt;As Amina put it: &lt;strong&gt;this is a call to action&lt;/strong&gt;. How can we, as experienced engineers, help the next generation of developers get a foothold? Some of her excellent suggestions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mentor at organisations like &lt;a href=&quot;https://www.codebar.io/&quot;&gt;Codebar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;pair with new engineers&lt;/li&gt;
&lt;li&gt;give engineers time to work on open source&lt;/li&gt;
&lt;li&gt;be mindful when recruiting - don&#39;t assume everyone has all the time in the world&lt;/li&gt;
&lt;li&gt;observe the &lt;a href=&quot;https://www.ericholscher.com/blog/2017/aug/2/pacman-rule-conferences/&quot;&gt;&amp;quot;pacman&amp;quot; rule&lt;/a&gt; when talking to people at events&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/what-does-it-take/&quot;&gt;What does it take to become a developer in 2020?&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;alice-bartlett---getting-more-from-git&quot; tabindex=&quot;-1&quot;&gt;Alice Bartlett - Getting more from Git&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;My process is &#39;try stuff until it works and don&#39;t ask any questions&#39;.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Somehow, Alice turned a pretty dry subject - git - into one of the most relatable and entertaining talks I&#39;ve ever seen.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054211838_fb160b70ec_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Alice Bartlett (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;With entertaining anecdotes about the meaningless commit messages she&#39;d write early in her career (we&#39;ve all been guilty of that, and you should see the nonsense commits I&#39;ve made to this very website) she highlighted the importance of considering who else is going to be reading all of it - including Future You. A commit message should be a single unit of work that makes sense in isolation, and that will tell you &lt;em&gt;why&lt;/em&gt; the change is made. So no more &amp;quot;fix bug&amp;quot; commits.&lt;/p&gt;
&lt;p&gt;Of course, it&#39;s not always possible to commit code with this in mind, and many of us approach coding by trying stuff out and going all over the place, so git offers us some handy ways of rewriting history so that we can make the commits sensible &lt;em&gt;after&lt;/em&gt; the fact.&lt;/p&gt;
&lt;p&gt;Here, Alice took us through a brief history of git (including a very entertaining swipe at Linus Torvalds and his &lt;a href=&quot;https://gizmodo.com/linux-founder-takes-some-time-off-to-learn-how-to-stop-1829105667&quot;&gt;controversy&lt;/a&gt;: &amp;quot;the creator of Linux and git, two projects he named after himself&amp;quot;). Many attendees in the room hadn&#39;t had the... pleasure of working with non-distributed source control systems like SVN, so she took us through how git differs and why it&#39;s so helpful for things like testing out changes and controlling the quality of code that&#39;s merged in.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Why are we so bad at git?&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ffconf/alicebartlett-git.jpg&quot; alt=&quot;Picture of LEGO heads that says &#39;you are in a detached HEAD state&#39;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Everything is confusing&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;A lot of the problem is the jargon and the impenetrable docs, Alice argued - and I agree with her there, having never read a man page that I understood.&lt;/p&gt;
&lt;p&gt;And then, using simple and clear language, Alice took us through the process of rewriting git history using interactive rebase (&lt;code&gt;git rebase --i&lt;/code&gt;). It&#39;s a super useful tool, allowing you to squash multiple commits into one, reword commit messages and change the order they are applied in. She also showed us &lt;code&gt;git add --patch&lt;/code&gt; which lets you choose which &amp;quot;hunks&amp;quot; of your code to commit and which to leave unstaged. I&#39;m not going to go into too much detail here, but the video is definitely worth a watch when it comes out.&lt;/p&gt;
&lt;p&gt;Some top git tips here to take away:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don&#39;t just link to Slack posts or tickets in the PR - give a bit of background info&lt;/li&gt;
&lt;li&gt;...but don&#39;t write an essay about the change, keep it concise&lt;/li&gt;
&lt;li&gt;commit messages should be meaningful and say &lt;em&gt;why&lt;/em&gt; the change happened&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/getting-more-from-git/&quot;&gt;Getting more from Git&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;laura-kalbag---8-unbelievable-things-you-never-knew-about-tracking&quot; tabindex=&quot;-1&quot;&gt;Laura Kalbag - 8 Unbelievable Things You Never Knew About Tracking&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;We&#39;re asked to give up everything, or get nothing.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Laura highlighted the ridiculous amount of information that various sites have about all of us just through embedded scripts and images. And even though this data is anonymised, a study showed it was possible to actually re-identify people from this data based on their browsing habits. Scary, right?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054212948_48bb29c813_w.jpg&quot; alt=&quot;&quot; title=&quot;Laura Kalbag (photo: Trys Mudford&quot; /&gt;)&lt;/p&gt;
&lt;p&gt;She touched on the Cambridge Analytica scandal - &amp;quot;tracking affects democracy&amp;quot; - and how companies can manipulate people through precise targeting based on their interests, knowing exactly what will make them tick. Facebook&#39;s latest ad campaign got a shout out for being totally hypocritical - when you choose to share something with &amp;quot;Only Me&amp;quot; or &amp;quot;Friends&amp;quot; you&#39;re also sharing it with Facebook!&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ffconf/laurakalbag-1.jpg&quot; alt=&quot;Photo of Laura Kalbag giving a conference talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;Companies make it worse by having incomprehensible terms and conditions, filled with legal jargon. When you consider that 1 in 6 people in England have very poor literacy skills (source: &lt;a href=&quot;https://literacytrust.org.uk/parents-and-families/adult-literacy/&quot;&gt;National Literacy Trust&lt;/a&gt;) it&#39;s especially problematic. Sites like Facebook are a lifeline for many people, but if they can&#39;t understand what they&#39;re signing up for is it really consent?&lt;/p&gt;
&lt;p&gt;While we can&#39;t escape technology - Laura argued there is no longer a distinction between &amp;quot;online life&amp;quot; and &amp;quot;real life&amp;quot; - we must all consider the &lt;strong&gt;impact our products will have&lt;/strong&gt; outisde of the immediate interface. She described how we can build more ethical tech, by making things that function without users&#39; personal info, furthering the human experience rather than for corporate profit. I find this a really interesting and difficult dilemma, as in our society it&#39;s really difficult (if not impossible) to build a sustainable product that isn&#39;t for-profit in some way. It would require pretty significant government support, which isn&#39;t going to happen any time soon.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Friends don&#39;t let friends get tracked by corporations.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I knew from the title that this talk would be worrying, but I didn&#39;t anticipate just how unsettled I&#39;d feel afterwards! As someone whose life has been basically entirely managed by Google products for years, I realised I needed to make a change. Laura suggested &lt;a href=&quot;https://switching.software/&quot;&gt;switching.software&lt;/a&gt; as a resource for alternatives to common &amp;quot;big tech&amp;quot; products, which is a great place to start.&lt;/p&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/privacy/&quot;&gt;8 Unbelievable Things You Never Knew About Tracking&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;harry-roberts---from-milliseconds-to-millions%3A-a-look-at-the-numbers-powering-web-performance&quot; tabindex=&quot;-1&quot;&gt;Harry Roberts - From Milliseconds to Millions: A Look at the Numbers Powering Web Performance&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;How do you &lt;em&gt;know&lt;/em&gt; the site is slow?&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A talk with a rather different tone from the last one - a focus on Harry&#39;s experience as a web performance consultant. Performance is definitely one of those things I know I should know more about, so I was geared up for the next couple of talks to help me boost that knowledge a little bit.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054730331_c8ba40ded7_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Harry Roberts (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Harry had the great suggestion of keeping a list of questions that you can ask all potential clients, so that you can better understand the problem. In his case, things like: &amp;quot;How do you know the site is slow?&amp;quot;. You could do this for any kind of consulting work - knowing exactly what to ask is hugely important. You can shape these questions over time, knowing exactly where to look next time and what doesn&#39;t work.&lt;/p&gt;
&lt;p&gt;I must admit I was a little put off when he suggested we &amp;quot;leave our ethics at the door&amp;quot; given the talk he&#39;d just followed, and some of the talk seemed a little too focused on the clients and not on the stories behind it. But this was, after all, a talk on numbers.&lt;/p&gt;
&lt;p&gt;I found it particularly interesting how he identified a performance issue localised to Venezuela, and got all the engineers on the team to use a simulated Venezuelan internet connection to get them to think about things like network conditions and how it might be for other countries. We often take our internet speed for granted, and even when Virgin Media is at its worst, we still have vastly better internet than much of the world. Much of the world&#39;s population is dependent on mobile internet, so are our apps really suitable for everyone?&lt;/p&gt;
&lt;p&gt;Harry advocated for normalising performance - making it part of our everyday work. It can be a hard thing to argue for, when your managers are pushing for more new features, but if you can show them the numbers, it&#39;s hard to argue.&lt;/p&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/from-milliseconds-to-millions/&quot;&gt;From Milliseconds to Millions: A Look at the Numbers Powering Web Performance&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;anna-migas---effortless-performance-debugging&quot; tabindex=&quot;-1&quot;&gt;Anna Migas - Effortless Performance Debugging&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;If [the browser] fails to load the frames fast enough, we&#39;ll experience jank.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Continuing my crash course in performance, Anna showed us with a live demo how we can use the power of Chrome Dev Tools to debug some common performance issues. Using the Profiler tab she showed how we can identify how loading is progressing and the performance of animations during interactions. You can see at-a-glance what&#39;s taking the longest time to load, plus it also has some helpful metrics such as the time to &lt;a href=&quot;https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint&quot;&gt;First Meaningful Paint&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054944937_d87fd371d8_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Anna Migas (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;In the spirit of the Live Demo, Anna was going to show us how the Lighthouse integration in Chrome can audit performance issues on web apps, but sadly technology was not on our side and Lighthouse wouldn&#39;t work (it seemed it wasn&#39;t just Anna though). Despite this hiccup, there were still a lot of really useful tips I took away from her talk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Look through Network tab to see what&#39;s been downloaded, and in what order&lt;/li&gt;
&lt;li&gt;Block elements using the request blocking tab to see the impact of not loading them&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;font-display: swap&lt;/code&gt; to show a fallback font before the font is loaded&lt;/li&gt;
&lt;li&gt;Using a lazy-loading library to only load pictures as you need them&lt;/li&gt;
&lt;li&gt;Using an image&#39;s intrinsic ratio to show placeholders and prevent text from jumping around as images load&lt;/li&gt;
&lt;li&gt;Splitting CSS into a critical path stylesheet and others that can be loaded separately&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ffconf/annamigas-1.jpg&quot; alt=&quot;Photo of Anna Migas giving a conference talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/effortless-performance-debugging/&quot;&gt;Effortless Performance Debugging&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;charlotte-dann---taking-the-web-off-the-screen&quot; tabindex=&quot;-1&quot;&gt;Charlotte Dann - Taking The Web Off The Screen&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;You&#39;d think that art is an expressive process, and adding this binary middle step seems incongruous, but... computers are better adapted to the design process than any traditional artistic medium.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I actually didn&#39;t make many notes for this talk because I was so engrossed in the incredible visuals Charlotte was showing us. As I mentioned before, I&#39;m a big fan of coding for artistic reasons, even if I don&#39;t really do it myself much. I&#39;m not particularly &amp;quot;good&amp;quot; at SVG or any kind of web animation, so it blows me away when I see what people can do with canvas, SVG and JS.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054950652_645f381878_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Charlotte Dann (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;In Charlotte&#39;s case, she bridges the gap between digital and physical art, using what she designs using generative CSS to produce prints and even intricate jewellery. She&#39;s made jigsaw puzzles which she&#39;s laser cut out, got a pen plotter to draw abstract designs onto pieces of paper for that precise yet hand-drawn look.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;nth-child&lt;/code&gt; pseudoselectors, she showed us how you can create an abstract pattern from a series of squares and circles. She&#39;s done a few of these, and used them as wall art for her studio!&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ffconf/charlottedann-1.jpg&quot; alt=&quot;Photo of Charlotte Dann giving a conference talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;She&#39;s also the founder of &lt;a href=&quot;https://hexatope.io/&quot;&gt;Hexatope&lt;/a&gt;, a web app that lets you draw beautiful patterns on a hexagonal grid and get them cast into silver and gold jewellery. The designs are incredible, and it&#39;s really fun to play with.&lt;/p&gt;
&lt;p&gt;I absolutely love hearing about things like this, and it&#39;s inspired me to get more involved in creative coding. If only people spent as much time doing things like this as they did arguing about which framework is best.&lt;/p&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/taking-the-web-off-the-screen/&quot;&gt;Taking The Web Off The Screen&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;suz-hinton---adventures-in-reinventing-interfaces&quot; tabindex=&quot;-1&quot;&gt;Suz Hinton - Adventures in reinventing interfaces&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;I want less mass-produced surveillance bullshit and more Harry Potter magic.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was super excited for Suz&#39;s talk, as I&#39;ve followed her online for some time and I think her hardware projects are amazing, so it was great to see some of them demoed. She demonstrated how we can use web APIs to interact with non-standard interfaces like printers and other hardware.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://live.staticflickr.com/65535/49054951142_95abc9eb9e_w.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Suz Hinton (photo: Trys Mudford)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Using a thermal receipt printer, the Web Media API and the Web USB API, Suz recreated her very own Gameboy Printer! She also showed off her web app that lets you upload Arduino programs directly to the Arduino via the browser, which made me think I should dig out the Arduino I&#39;ve had in a drawer for several years and never used. (We&#39;ve all got a drawer like that.)&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ffconf/suzhinton-1.jpg&quot; alt=&quot;Photo of Suz Hinton giving a conference talk&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;The tone of the talk shifted considerably when Suz started talking about ownership over computers and data. She cited a 1985 ruling by the Federal Communications Commission which allocated the 900MHz frequency band to industrial, scientific and medical uses. Amateur radio users were allowed to use the band if they liked, as long as it didn&#39;t interfere with the protected uses.&lt;/p&gt;
&lt;p&gt;However, now the FCC have proposed that private companies should be able to use these bands. And guess who&#39;s jumped straight in there? Everyone&#39;s favourite Big Bad Retailer, Amazon.&lt;/p&gt;
&lt;p&gt;Amazon&#39;s new &lt;a href=&quot;https://techcrunch.com/2019/09/25/amazon-sidewalk-is-a-new-long-range-wireless-network-for-your-stuff/&quot;&gt;Sidewalk&lt;/a&gt; network functions on this 900MHz band. Even the 700-odd Amazon employees testing the products managed to form a localised network on the 900MHz frequency stretching across much of the Los Angeles Basin. Meaning they&#39;ve basically made a frequency jammer. (Bear in mind frequency jammers are illegal in many countries.) If hundreds of thousands of Amazon customers start buying these products which operate on this frequency, what&#39;s going to happen to all those medical devices that rely on this band?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;This is the scariest thing I&#39;ve ever heard.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At this point Suz started crying, which really drove home just how doomed we&#39;ll be if this stuff keeps happening. &amp;quot;We are pretending that these devices are supposed to be helping people, and these people have no idea that they are actually contributing to a privately owned network that companies like this can do whatever they want with.&amp;quot;&lt;/p&gt;
&lt;p&gt;It&#39;s our job to make sure that we are fighting against things like this - &amp;quot;we&#39;ve done a bad job at educating people&amp;quot;. We should be building more &amp;quot;Harry Potter magic&amp;quot; instead of buying corporate home technology, Suz argued - she namechecked &lt;a href=&quot;http://samanthagoldste.in/&quot;&gt;Samantha Goldstein&lt;/a&gt;, who built a stained glass panel that goes cloudy if it&#39;s raining.&lt;/p&gt;
&lt;p&gt;ffconf talk page: &lt;a href=&quot;https://ffconf.org/talks/nerdverse/&quot;&gt;Adventures in reinventing interfaces&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;reflections&quot; tabindex=&quot;-1&quot;&gt;Reflections&lt;/h2&gt;
&lt;p&gt;I came away from ffconf inspired and filled with a desire to build weird stuff: I want to learn to do things with hardware, make pretty patterns with CSS, and teach my niece how to do the same just for the hell of it.&lt;/p&gt;
&lt;p&gt;I also came away feeling terrified by corporate surveillance and the absolute disregard for ethics in technology under the guise of convenience.&lt;/p&gt;
&lt;p&gt;Being a developer isn&#39;t just about building flashy stuff and sending it off into the world and moving onto the next thing: we&#39;ve got a responsibility to make sure that the tech we&#39;re building is doing good, not harm, and that people are educated about the implications if we do start building creepy stuff like Sidewalk. As Laura Kalbag put it: &lt;strong&gt;be the advocate, and question the default&lt;/strong&gt;. We know what these products and these companies are doing, so it&#39;s our job to tell everyone about it.&lt;/p&gt;
&lt;p&gt;ffconf is a small, family-run conference, with passionate speakers who have a story to tell. I&#39;d love to see more community-focused conferences like this - it&#39;s all too common nowadays to go to a big conference and end up listening to sales pitch after sales pitch when all you want to do is learn something.&lt;/p&gt;
&lt;p&gt;I feel like I should probably get rid of the Google Home that&#39;s sitting in my living room right now.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Everything I googled in a week as a professional software engineer</title>
    <link href="https://localghost.dev/blog/everything-i-googled-in-a-week-as-a-professional-software-engineer/"/>
    <updated>2019-09-02T00:00:00Z</updated>
    <id>https://localghost.dev/blog/everything-i-googled-in-a-week-as-a-professional-software-engineer/</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;Update 15/10/2022:&lt;/strong&gt; I&#39;ve written a new version of this! &lt;a href=&quot;https://localghost.dev/blog/everything-i-googled-in-a-week-as-a-senior-software-engineer/&quot;&gt;Everything I googled in a week as a senior software engineer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In an attempt to dispel the idea that if you have to google stuff you&#39;re not a proper engineer, this is a list of nearly everything I googled in a week at work, where I&#39;m a software engineer with several years&#39; experience.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/ground.png&quot; alt=&quot;A google search for &amp;quot;threw it on the ground&amp;quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Happy birthday to the ground.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Obviously these weren&#39;t all googled in a row (although you can probably spot that a few were), but throughout the day. I can&#39;t remember the context of everything I was googling, but hopefully it&#39;ll make you feel a little better next time you have to google something.&lt;/p&gt;
&lt;h2 id=&quot;monday&quot; tabindex=&quot;-1&quot;&gt;Monday&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;npm react-testing-library&lt;/code&gt; - during a React upgrade, looking at dependencies to see latest versions and checking for breaking changes.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a &amp;quot;gql&amp;quot; tag?&lt;/code&gt; - said React upgrade then started causing some super fun errors.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react-apollo release notes&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react-apollo/test-utils&lt;/code&gt; - tests were throwing some odd errors with our graphQL components.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;undo a rebase&lt;/code&gt; - oops.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react testing library apollo &amp;quot;invariant violation&amp;quot;&lt;/code&gt; - package upgrades are so much fun!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jest silence warnings&lt;/code&gt; - don&#39;t judge me, ok?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;semantic HTML contact details&lt;/code&gt; - wanted to check if the &lt;code&gt;&amp;lt;address&amp;gt;&lt;/code&gt; tag was relevant here&lt;/p&gt;
&lt;p&gt;&lt;code&gt;aa contrast checker&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;temporary visual impairment&lt;/code&gt; - fact checking for an accessibility talk I was giving that week&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dominos accessibility&lt;/code&gt; - popcorn.gif&lt;/p&gt;
&lt;p&gt;&lt;code&gt;shame gif&lt;/code&gt; - an important part of any presentation&lt;/p&gt;
&lt;h2 id=&quot;tuesday&quot; tabindex=&quot;-1&quot;&gt;Tuesday&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;javascript get array of unique dates&lt;/code&gt; - if I have an array of &lt;code&gt;Date&lt;/code&gt;s, how can I filter them so they are unique? (&lt;code&gt;reduce&lt;/code&gt;, naturally, but I can rarely use that without googling it first)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;date to locale string&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;js date to locale string&lt;/code&gt; - after I got a load of Java results&lt;/p&gt;
&lt;p&gt;&lt;code&gt;alternatives to Moment.js&lt;/code&gt; - it&#39;s large&lt;/p&gt;
&lt;p&gt;&lt;code&gt;group array items by date&lt;/code&gt; - more &lt;code&gt;reduce&lt;/code&gt; fun&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sort object keys javascript&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react fragment keys&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next link&lt;/code&gt; - needed a reminder of how to use the Link component in Next.JS&lt;/p&gt;
&lt;p&gt;&lt;code&gt;React.Children.only expected to receive a single React element child.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;visual studio code disable autocomplete html&lt;/code&gt; - it keeps autoclosing HTML elements on the same line, and I still can&#39;t switch it off&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dt dd dl&lt;/code&gt; - couldn&#39;t remember what the example use for these was.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;html nested sections&lt;/code&gt; - is it ok to have &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; inside &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;display dl in pairs&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;veggie ipsum&lt;/code&gt; - the best lorem ipsum generator&lt;/p&gt;
&lt;p&gt;&lt;code&gt;css keyframes&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;css animate underline text&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dl vs ul&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react generating keys&lt;/code&gt; - should I use some kind of hash, or should I use data in the props? (I ended up constructing a string with unique timestamp data)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;css checkbox&lt;/code&gt; - can we style checkboxes yet? (no)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flexbox center span&lt;/code&gt; - it was 17:24 and I was tired by this point&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grid minmax&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flexible grid row&lt;/code&gt; - I don&#39;t have a whole lot of CSS Grid experience, so I always end up googling a ton with this.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grid row height auto&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cauliflower shortage&lt;/code&gt; - someone told me about this and I panicked&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next.js hooks&lt;/code&gt; - we can use them, right? (we can, and I did)&lt;/p&gt;
&lt;h2 id=&quot;wednesday&quot; tabindex=&quot;-1&quot;&gt;Wednesday&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cors&lt;/code&gt; - today is going to be bleak&lt;/p&gt;
&lt;p&gt;&lt;code&gt;the corrs&lt;/code&gt; - once I hit some CORS errors I decided I needed to make a meme, and I needed to find the perfect image. It took a surprisingly long time.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/thecorrs-search.png&quot; alt=&quot;Many many Google search results for The Corrs&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/thecors.jpg&quot; alt=&quot;A photoshopped version of the Corrs&#39; album with the title &amp;quot;No Access-Control-Allow-Origin header is present on the requested resource&amp;quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;Worth it.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;git patch trailing whitespace&lt;/code&gt; - I was sent a git patch with some whitespace that prevented it from actually patching&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jsx annotation&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;web api fetch preflight&lt;/code&gt; - in my CORS adventures I wanted to read up a bit more about preflight requests.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;web api fetch origin header&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;discriminated union flow&lt;/code&gt; - trying to diagnose problems with my Flow types.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;whitespace regex&lt;/code&gt; - is it &lt;code&gt;\w&lt;/code&gt;? (no, that&#39;s a word - it&#39;s &lt;code&gt;\s&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;regex not letter&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pat butcher emoji&lt;/code&gt; - what can I say, I google important things&lt;/p&gt;
&lt;p&gt;&lt;code&gt;woman shouting at cat&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;google oauth&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next.js authentication&lt;/code&gt; - sometimes it&#39;s helpful to google stuff to see if anyone has written examples of how to do common flows in the framework or tool that you&#39;re using&lt;/p&gt;
&lt;p&gt;&lt;code&gt;component displayname&lt;/code&gt; - do I need to do this with my higher-order components?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nextCookie&lt;/code&gt; - starting to mess around with oauth cookies&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reading cookies in react&lt;/code&gt; - there must be a better way than &lt;code&gt;document.cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;js-cookie npm&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cookies-js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;npm cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;universal-cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;google oauth cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;🍪&lt;/p&gt;
&lt;h2 id=&quot;thursday&quot; tabindex=&quot;-1&quot;&gt;Thursday&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;log in with google&amp;quot; localhost&lt;/code&gt; - was having all sorts of problems getting this to work&lt;/p&gt;
&lt;p&gt;&lt;code&gt;httpserverrequest javascript&lt;/code&gt; - I have a feeling this was something to do with Flow types&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nextjs flowtypes&lt;/code&gt; - yep, there you go&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;python-social-auth&amp;quot; react&lt;/code&gt; - trying to figure out if the django backend I was working with would play nicely with my React frontend&lt;/p&gt;
&lt;p&gt;&lt;code&gt;google social login&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vary header&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;get cookie from 302&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;google social login cookies&lt;/code&gt; - I was having a really fun time with this as you can tell&lt;/p&gt;
&lt;p&gt;&lt;code&gt;google oauth cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;python-social-auth set-cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;python-social-auth site:stackoverflow.com&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;python-social-auth react site:stackoverflow.com&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;django&lt;/code&gt; - I think I gave up at this point and just googled Django because I have literally never used it&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fetch send cookies&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;testing same origin credentials locally&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cross origin cookies&lt;/code&gt; - spoiler alert: not a thing&lt;/p&gt;
&lt;p&gt;&lt;code&gt;useState default value&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;The value of the &#39;Access-Control-Allow-Origin&#39; header in the response must not be the wildcard &#39;*&#39; when when the request&#39;s credentials mode is &#39;include&#39;.&lt;/code&gt; - googling error messages is only second to console.log() as a debugging method&lt;/p&gt;
&lt;p&gt;&lt;code&gt;useState with empty array&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react hooks initial state empty array&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;Provisional headers are shown&amp;quot;&lt;/code&gt; - this is where the requests weren&#39;t going through and I couldn&#39;t see what the actual headers being sent were&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fetch send cookies&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;how to see request headers in chrome&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fetch not sending cookies&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Thursday was a whole lot of fun D:&lt;/p&gt;
&lt;h2 id=&quot;friday&quot; tabindex=&quot;-1&quot;&gt;Friday&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;provisional headers are shown&lt;/code&gt; - still at it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sending cookies from localhost&lt;/code&gt; - have I mentioned that I hate cookies?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;editing host file&lt;/code&gt; - desperate times (and it didn&#39;t even work)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sending cookies with different domain&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;getinitialprops functional component&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;getting cookies from document&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;js find&lt;/code&gt; - to check the usage and return types&lt;/p&gt;
&lt;p&gt;&lt;code&gt;string contains&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;string methods js&lt;/code&gt; - I can&#39;t keep any of these in my head&lt;/p&gt;
&lt;p&gt;&lt;code&gt;js string methods&lt;/code&gt; - 20 mins later&lt;/p&gt;
&lt;p&gt;&lt;code&gt;js fetch manual cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;django react cookies localhost&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;django react cookies localhost site:stackoverflow.com&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;httponly cookie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;django httponly&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;async await promise.all&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nextjs port&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;google appengine node ports&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next rename static&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;install gcloud cli&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;method patch&lt;/code&gt; - couldn&#39;t remember what the HTTP method &lt;code&gt;PATCH&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nextjs env&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next.js environment variables&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next js docs&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;editing data with hooks&lt;/code&gt; - literally no idea what I was trying to google here but this was past 5pm so I was evidently quite tired&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react form submit&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dayjs&lt;/code&gt; - I needed the documentation again.&lt;/p&gt;
&lt;p&gt;What I&#39;m trying to show with all this is that you can do something 100 times but still not remember how to do it off the top of your head. Never be ashamed of googling, even if it seems like the most basic thing you&#39;re looking up. I can never remember how &lt;code&gt;Date&lt;/code&gt; works.&lt;br /&gt;
I&#39;ve built plenty of forms in React but couldn&#39;t remember how &lt;code&gt;onSubmit&lt;/code&gt; worked on the Friday evening at 5:30pm. I constantly have to google JS string methods. Cookies are terrible. (Incidentally, we fixed the cookie issue by running everything in a docker container and tunneling with &lt;code&gt;ngrok&lt;/code&gt;, so everything&#39;s on the same domain.)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Questions to ask at an engineering interview</title>
    <link href="https://localghost.dev/blog/questions-to-ask-at-an-engineering-interview/"/>
    <updated>2019-08-22T16:55:34Z</updated>
    <id>https://localghost.dev/blog/questions-to-ask-at-an-engineering-interview/</id>
    <content type="html">&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/silicon-valley-crushed-it.png&quot; alt=&quot;A still from the HBO series Silicon Valley in which two interviewers are asking a candidate &#39;it says here on your resume that from 2010 to 2011, you crushed it?&#39;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;/figure&gt;
&lt;p&gt;Tech job interviews are often different flavours of the same thing, regardless of where you apply. Interviewers are likely to ask you questions about your experiences, perhaps a hypothetical question about what you might do in a certain situation, or delve into some of the how-it-works stuff under the hood of whatever programming language you&#39;ll be using. However, there&#39;s one question that you can &lt;em&gt;guarantee&lt;/em&gt; will come up:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Do you have any questions for us?&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(At this point you&#39;ll probably sigh with relief - internally, at least - as you&#39;ve reached the end of the interview.)&lt;/p&gt;
&lt;p&gt;It might be tempting to just skip over this with a &amp;quot;no, thank you&amp;quot; - maybe the job description gave you enough information for now - but you should always ask &lt;strong&gt;at least one question&lt;/strong&gt;. It&#39;s a surprisingly important part of the interview. Firstly, it&#39;s an opportunity for you to squash any worries you might have, or find out the answers to anything that wasn&#39;t quite clear before. Secondly, it&#39;s a chance for you to peek into how things &lt;em&gt;really&lt;/em&gt; are at Company X before you get too far in and realise you&#39;ve Made A Huge Mistake. An interview should be as much you interviewing &lt;em&gt;them&lt;/em&gt; as it is them interviewing you, as you need to find out whether the company is a good fit for &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Of course, you don&#39;t have to wait until the very end of the interview to ask questions - it&#39;s great to ask relevant questions throughout (though be careful that you don&#39;t end up answering every question with another question)!&lt;/p&gt;
&lt;h2 id=&quot;what-your-questions-say-about-you&quot; tabindex=&quot;-1&quot;&gt;What your questions say about you&lt;/h2&gt;
&lt;p&gt;This part of the interview is not just for your benefit: the questions you ask tell the interviewer more about you than you might think. For starters, it shows how engaged you are, what your priorities are and the kind of things you value in your role. It&#39;s an opportunity to show off your knowledge and experience by asking questions tailored to the work that you&#39;re looking for.&lt;/p&gt;
&lt;p&gt;How many questions is too many? It depends how much time you&#39;ve got left, but don&#39;t be afraid to turn up with a list. I brought a notebook into mine, and I took notes while they answered.&lt;/p&gt;
&lt;p&gt;So, what kind of questions might you ask? Obviously it&#39;s a chance for you to get answers to things that weren&#39;t clear about the application process or the job itself. You can ask about the kind of learning and development opportunities, or ask the old favourite of &amp;quot;what do you like most about working here&amp;quot;? Don&#39;t be afraid to spin questions that the interviewer asked you back around on them, as long as it&#39;s relevant and reasonable.&lt;/p&gt;
&lt;p&gt;My favourite interview question tactic is to think about things from my previous roles that frustrate you or that you know you don&#39;t want to experience again. Asking questions about these things can give you an idea of whether they do things differently at this place, or whether you&#39;re walking into the same job all over again. (Alternatively, if there&#39;s something you particuarly enjoy about your current role, it&#39;s a good way of finding out whether it&#39;ll be the same at this new place too.)&lt;/p&gt;
&lt;p&gt;I&#39;ll give you some questions that I might ask as a starter (and in some cases, what these questions are &lt;em&gt;really&lt;/em&gt; asking). I&#39;m not saying you should ask all of these questions - that would probably take all afternoon - but feel free to pick and choose depending on where you&#39;re applying and what&#39;s important to you. They&#39;re here as a starting point.&lt;/p&gt;
&lt;h2 id=&quot;the-%22how-does-this-work-here%3F%22-questions&quot; tabindex=&quot;-1&quot;&gt;The &amp;quot;how does this work here?&amp;quot; questions&lt;/h2&gt;
&lt;p&gt;These are the questions based on your past experience. It&#39;s a great way to understand more about processes at the company, as well as making sure you won&#39;t end up working at somewhere that&#39;s exactly the same as your last place (unless that&#39;s something you want).&lt;/p&gt;
&lt;h3 id=&quot;working-in-product-teams&quot; tabindex=&quot;-1&quot;&gt;Working in product teams&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;How closely do the dev team work with business stakeholders/customers?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Is this a case of &amp;quot;IT vs The Business&amp;quot; or are engineers embedded throughout the company? I&#39;ve worked in both situations, and it&#39;s much nicer being considered a core part of the business rather than a &amp;quot;supporting function&amp;quot; building a product for someone else&#39;s business needs. Is there a product manager on the team who represents the needs of the customer? Are there regular demos with relevant stakeholders? Do they do any user testing?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How does work come in to the team?&lt;/p&gt;
&lt;p&gt;How involved are engineers with deciding what to build?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Am I going to be involved in the decision making and the shaping of what we&#39;re building or am I going to be blindly picking up JIRA tickets? Is it an iterative development process, or is it a case of &amp;quot;requirements come in, code comes out 6 months later&amp;quot;?&lt;/p&gt;
&lt;p&gt;It took a bit of getting used to, but now I love being involved right at the beginning, helping to decide what it is we&#39;re going to build and how we&#39;re going to build it. It&#39;s related to the first question in that it shows that engineering is a core part of the company and not just something that you do to achieve the thing for the business.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Who makes technical decisions? How much independence do product teams have to make technical decisions?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This question is about autonomy in what you&#39;re building. Is it going to be a case of &amp;quot;here is the work, go and do it&amp;quot; or &amp;quot;how shall we build this? What do you think?&amp;quot;&lt;/p&gt;
&lt;p&gt;Some degree of uniformity is vital, especially if you&#39;re working with lots of microservices. But having strategies for the way you work and the technologies you use is one thing; being told exactly what to do and having no independence or flexibility is another thing entirely.&lt;/p&gt;
&lt;h3 id=&quot;code%2C-deployment-and-infrastructure&quot; tabindex=&quot;-1&quot;&gt;Code, deployment and infrastructure&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Who looks after the live applications?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Is it &amp;quot;you build it, you run it&amp;quot; or is it &amp;quot;you build it, and throw it over the wall&amp;quot;? Do engineers have ownership of the apps they build, and are they trusted to look after them?&lt;/p&gt;
&lt;p&gt;It&#39;s also worth finding out how on-call works, because if that&#39;s something that you can accommodate, it&#39;s a great opportunity to learn about the tech and how things work.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What&#39;s your deployment process like?&lt;/p&gt;
&lt;p&gt;What does an average path to production look like for a service or application?&lt;/p&gt;
&lt;p&gt;Do you practice continuous integration?&lt;/p&gt;
&lt;p&gt;How often do you release to production?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Can I deploy stuff myself on an ad-hoc basis, or is it once a week/every three months? Is it going to be six months before you let me put it into the wild?&lt;/p&gt;
&lt;p&gt;This is about finding out how much friction there is in the path to production. The more obstacles and Process With A Capital P, the more obstacles to innovation and experimentation. &lt;em&gt;That said&lt;/em&gt;, there is a happy medium, and I don&#39;t believe you should be firing off software into prod without due diligence, some process and quality control, especially when you&#39;re working with people&#39;s data. It&#39;s worth finding out how the company handles that delicate balance.&lt;/p&gt;
&lt;p&gt;Bonus points for continuous deployment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Say I wanted to spin up a new service. How would I do that?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Would I need to get permission from the Change Advisory Board in a distant ivory tower? Would I need to write numerous documents and have handover meetings for deployment and maintenance?&lt;/p&gt;
&lt;p&gt;The answer I got in my Monzo interview was &amp;quot;there&#39;s a command line script to generate a new service&amp;quot; and I nearly wept with joy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How do you do version control?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If they say &amp;quot;Subversion&amp;quot;, it&#39;s time to question why. Is there a big beast of a monolith that was written in Java 6 and nobody has quite had the guts to move it off SVN because they aren&#39;t &lt;em&gt;quite&lt;/em&gt; sure where all the code lives, and do you really want to work with that every day?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How are architectural decisions made?&lt;/p&gt;
&lt;p&gt;Do you have an architecture team? What do they do?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do you have people whose job title is literally &amp;quot;Architect&amp;quot;? If so, are they hands-on and technical, or do they come in and tell you how to build stuff and then leave again? Am I going to be allowed to make my own decisions about the structure of the software I&#39;m building?&lt;/p&gt;
&lt;p&gt;I&#39;ve definitely met some good architects, but really things like solution architecture should be done by the team building the actual thing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What&#39;s your testing strategy?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do your developers do any testing? (Conversely, are you obsessed with as high test coverage as possible?) And if there&#39;s pretty poor test coverage, are they open to improving it or do they see it as a waste of time?&lt;/p&gt;
&lt;h2 id=&quot;the-%22how-is-it-really%3F%22-questions&quot; tabindex=&quot;-1&quot;&gt;The &amp;quot;how is it really?&amp;quot; questions&lt;/h2&gt;
&lt;p&gt;The questions that help you delve into day-to-day life at the company.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What does a typical day look like for you?&lt;/p&gt;
&lt;p&gt;What are the working hours like here?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Will I be working until 8pm, or can I go to my clay pigeon shooting evening class without getting Meaningful Glances from my colleagues behind their screens?&lt;/p&gt;
&lt;p&gt;Perhaps I&#39;m naïve, but I firmly believe in a work-life balance. I was very lucky to have that in my previous job, and I have it in my current job. I don&#39;t believe working later makes you a better contributor, as I think the more tired and burned out you get the worse your work is going to be in the long run. I want to know what kind of hours people keep so I can factor it into my decision.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Are there many parents here?&lt;/p&gt;
&lt;p&gt;How does parental leave work here?&lt;/p&gt;
&lt;p&gt;What facilities do you have for new parents?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This one is not a question I&#39;ve asked, as I don&#39;t have children and don&#39;t plan to have them any time soon, but if you&#39;re a parent or at that stage in your life where it&#39;s something you&#39;re thinking about, you want to know whether it&#39;s a parent-friendly workplace, whether there&#39;s anywhere to go and breastfeed, and what kind of caregiver leave they offer.&lt;/p&gt;
&lt;p&gt;I know that some places can be a bit funny if women of childbearing age ask about this kind of thing in interviews; if that&#39;s the case, I would question whether it&#39;s really somewhere you want to work.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What kind of diversity and inclusion initiatives do you have here?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Does the company take diversity and inclusion seriously? Many (if not most) tech companies have traditionally very poor diversity in terms of gender and ethnicity - and often age, too. Trying to hire from a more diverse pool of candidates is one thing, but how are they trying to make things better in order to get people to stay? Are they hiring a diversity and inclusion lead? Do they have groups or networks?&lt;/p&gt;
&lt;h2 id=&quot;the-%22where-can-i-go-from-here%3F%22-questions&quot; tabindex=&quot;-1&quot;&gt;The &amp;quot;where can I go from here?&amp;quot; questions&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;What kind of learning and development opportunities are there for employees?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A good way to find out whether they have a learning budget, or whether you can ask for books/courses/conference tickets.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you ever host meetups or community events?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Perhas not important to everyone, but as someone who owes a lot of my professional development to the community as a whole, it&#39;s really important that wherever I work has a good community spirit.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do people here ever speak at conferences?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This one is a bit less helpful as (especially if it&#39;s a small team) it could be that the employees don&#39;t &lt;em&gt;want&lt;/em&gt; to speak at a conference, and that&#39;s totally fine. But if it&#39;s a huge company and nobody really speaks at conferences, it kind of raises the question of whether anyone does anything worth talking about (or, if they are, whether the company isn&#39;t keen on letting them talk about it.)&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I hope this has given you an idea of the kind of questions you might want to ask at an interview, but more importantly, the value you can get from asking them. If you&#39;ve got any more thoughts or ideas for interview questions, share this on Twitter with the link below and join the conversation!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Why software engineers should know their audience</title>
    <link href="https://localghost.dev/blog/why-software-engineers-should-know-their-audience/"/>
    <updated>2019-04-06T00:00:00Z</updated>
    <id>https://localghost.dev/blog/why-software-engineers-should-know-their-audience/</id>
    <content type="html">&lt;p&gt;When you&#39;re talking about what you&#39;re working on, do you ever stop to think about what you&#39;re saying and whether the person you&#39;re talking to can actually understand it?&lt;/p&gt;
&lt;p&gt;There&#39;s more to being a software engineer than coding. What people often underestimate are the so-called &amp;quot;soft skills&amp;quot; (the worst term for something that&#39;s really vital) - the way that you interact with others around you. In particular, how you communicate what you&#39;re doing to people with different skillsets.&lt;/p&gt;
&lt;p&gt;Imagine you&#39;re in a standup and someone gives this update:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#39;ll synthesize the haptic DDR3 network, that should shut down the SDD capacitor!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This came straight from the brilliant &lt;a href=&quot;http://shinytoylabs.com/jargon/&quot;&gt;Hollywood Jargon Generator&lt;/a&gt;, but to anyone who doesn&#39;t have as much technical experience as you, that might as well have been what you just said.&lt;/p&gt;
&lt;h2 id=&quot;u-wot-m8&quot; tabindex=&quot;-1&quot;&gt;u wot m8&lt;/h2&gt;
&lt;p&gt;One of the best pieces of advice I ever got was from a tech lead who took all of the engineers aside after a standup where we&#39;d been discussing how we were getting on with the new authentication flow we were writing. She told us to make sure we didn&#39;t go into too much technical detail in the standup, so that everyone could understand it. Sounds so simple, right?&lt;/p&gt;
&lt;p&gt;We&#39;d just spent ten minutes with the rest of the team - including our product manager and the marketing lead - and we&#39;d been talking about refresh tokens and token expiry. It had meant absolutely nothing to several of the people there. The more we mentioned these arcane technical concepts, the less the rest of the team wanted to come along to standups because they felt it was irrelevant or above them in some way.&lt;/p&gt;
&lt;p&gt;&amp;quot;But it&#39;s a standup!&amp;quot; I hear you cry. &amp;quot;You&#39;re only meant to give a quick high-level update anyway!&amp;quot;&lt;/p&gt;
&lt;p&gt;You&#39;d be surprised how easy it is to start talking in jargon without even realising for even the smallest of updates. Next time you give a standup update, ask yourself: if I weren&#39;t technical, would I know what I was talking about?&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://localghost.dev/img/blog/xkcd-eli5.png&quot; alt=&quot;&amp;quot;Two characters are talking. Left: What&#39;ve you been up to? Right: Doing tons of math for my thesis. Left: Can you explain it like I&#39;m five? Right: Oh my God, where are your parents?&amp;quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; /&gt;&lt;figcaption&gt;source: xkcd&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;How much technical detail do you really need to go into? If your standup tends to be &amp;quot;here&#39;s what I did yesterday and here&#39;s what I&#39;m doing today&amp;quot;, do you need to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&#39;re still trying to get the auth service to store the user&#39;s refresh token in the database and check it against the incoming requests.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or can you just say&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&#39;re still trying to get authentication working in the backend.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To you the first example might look pretty easy to understand, but that&#39;s probably because you&#39;re an engineer. You know what a refresh token is. You know what a request is in this context. Non-technical folk probably knows what a database is, and what authentication is, but that&#39;s about it, and they&#39;ve switched off by the end of the sentence. By keeping the technical detail to a minimum you&#39;ll be providing an update that the rest of the team understand, so they know what everyone&#39;s working on.&lt;/p&gt;
&lt;p&gt;What about if there&#39;s a particular technical thing that&#39;s blocking you that you wanted to mention in standup? Either mention that you&#39;re generally blocked in the update and approach one of your fellow engineers afterwards, or maybe have a 5-minute dev-only standup after the main team standup where you can go into more technical detail.&lt;/p&gt;
&lt;p&gt;Here&#39;s another example:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some of our ElasticSearch nodes went down last night, it turns out we are still using the old cluster so we&#39;re going to migrate to the new cluster today.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;vs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Our search system went down last night, it turns out we&#39;re using an old server* so we&#39;re going to move it to the newer one today.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;* I know this isn&#39;t technically the same thing, but to someone who doesn&#39;t know what a cluster is, it literally doesn&#39;t matter. You can go into more detail in the relevant dev standup/slack channel/coffee break.&lt;/p&gt;
&lt;h2 id=&quot;use-real-world-analogies&quot; tabindex=&quot;-1&quot;&gt;Use real-world analogies&lt;/h2&gt;
&lt;p&gt;Keeping your language simple works for technical people too. If you&#39;re mentoring another engineer or helping someone work through a problem, being able to explain technical concepts in an easy-to-understand way and relating them to tangible concepts in the real world can really help others to learn from you. You&#39;ll find it a useful skill for giving talks - there&#39;s a real difference between &amp;quot;show me how&amp;quot; and &amp;quot;make me understand&amp;quot;. For example, in a talk about &lt;a href=&quot;https://redux-saga.js.org/&quot;&gt;redux-saga&lt;/a&gt; I used pictures of dogs to illustrate the library of effects it provides. In pretty much every object-oriented programming language tutorial there is some kind of &lt;code&gt;Person&lt;/code&gt; or &lt;code&gt;Car&lt;/code&gt; class to help you understand the concept of an object, and the tutorials about composition and inheritance usually talk about different species of animals.&lt;/p&gt;
&lt;p&gt;With the auth token example, I told my team a story about a secret members&#39; club involving an ever-changing secret handshake and a badge that let you learn the new secret handshake, which went down well and helped the others to get what we were trying to do, even though my product manager thought I was talking about a sex club.&lt;/p&gt;
&lt;h2 id=&quot;yeah%2C-so-we-really-need-to-reticulate-the-splines-in-our-codebase&quot; tabindex=&quot;-1&quot;&gt;Yeah, so we really need to reticulate the splines in our codebase&lt;/h2&gt;
&lt;p&gt;It&#39;s not just standups where this skill comes in handy: in your day-to-day role, explaining technical things clearly and simply might be the thing that convinces them why you should take a break from delivering new features to go back and tackle the mountain of tech debt that&#39;s been piling up:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We need to upgrade a lot of the packages, check for security vulnerabilities and replace a lot of deprecated code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What does &amp;quot;deprecated&amp;quot; mean? What are packages in this context?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&#39;ve got some old code that needs updating because soon it won&#39;t work any more, and it might pose a security risk.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It sounds so basic, but to a non-engineer, that&#39;s all they need to know. They might ask some questions about what kind of risk it poses, or what &amp;quot;won&#39;t work any more&amp;quot; means, but it&#39;s a lot easier to follow.&lt;/p&gt;
&lt;h2 id=&quot;challenge-yourself-to-keep-it-simple&quot; tabindex=&quot;-1&quot;&gt;Challenge yourself to keep it simple&lt;/h2&gt;
&lt;p&gt;It&#39;s not always easy to translate the hard stuff in easy terms, especially when you&#39;re working on things that involve kubernetes (true story). I still haven&#39;t found a good layman&#39;s explanation for what Docker does. But next time you&#39;re in a standup, listen carefully to what your fellow engineers say and then catch up with your other team members afterwards to ask if they followed everything. If they say yes, then you&#39;re fine, and you can just carry on as you were. But if they say no, consider getting your team to challenge themselves to deliver very simple standup for a a week. Make up ridiculous stories to illustrate migrating ElasticSearch clusters. At the end, ask those same people whether they feel like they know more about what you&#39;ve been up to.&lt;/p&gt;
&lt;p&gt;And if all else fails, there&#39;s my old favourite fallback:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everything&#39;s slightly broken, but I&#39;m working on making it not broken.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
  
  <entry>
    <title>Things experienced speakers wish they&#39;d known:</title>
    <link href="https://localghost.dev/blog/things-experienced-speakers-wish-they-d-known/"/>
    <updated>2018-01-24T15:00:00Z</updated>
    <id>https://localghost.dev/blog/things-experienced-speakers-wish-they-d-known/</id>
    <content type="html">&lt;p&gt;Congratulations, you&#39;ve been accepted to speak at a conference!&lt;/p&gt;
&lt;p&gt;But once the initial euphoria wears off, you might find the impostor syndrome starting to set in. What if I&#39;m not good enough? Do I know enough about this topic? What if the audience hates me?&lt;/p&gt;
&lt;p&gt;That&#39;s me right now. I&#39;m currently preparing my first ever conference talk for &lt;a href=&quot;https://www.reactfest.uk/&quot;&gt;ReactFest 2018&lt;/a&gt;, which I was encouraged to apply to by the excellent folk at &lt;a href=&quot;https://www.meetup.com/en-AU/ReactJS-Girls-London/&quot;&gt;ReactJS Girls London&lt;/a&gt;. Having gained quite a few new followers on Twitter after my talk was announced, I thought I&#39;d canvas a bit for helpful hints for a first time speaker. I figured a few people might respond.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/type__error&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1474717155983773700/sXRdF5e3_normal.jpg&quot; alt=&quot;Avatar for type__error&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/type__error&quot;&gt;Sophie Koonin &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/type__error/status/955554649666355200&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;People who have spoken at tech conferences: what&#39;s one thing you wish you&#39;d known before your first talk?&lt;br /&gt;&lt;br /&gt;(RT for reach please?)&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955554649666355200&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;751 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 09:35:56 (UTC)&quot; href=&quot;https://twitter.com/type__error/status/955554649666355200&quot;&gt;10:35 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;I got so many fantastic tips and suggestions—including some from experienced speakers like &lt;a href=&quot;https://www.twitter.com/sarah_edo&quot;&gt;Sarah Drasner&lt;/a&gt;, &lt;a href=&quot;https://www.twitter.com/dan_abramov&quot;&gt;Dan Abramov&lt;/a&gt; and &lt;a href=&quot;https://www.twitter.com/anjuan&quot;&gt;Anjuan Simmons&lt;/a&gt; — that one user suggested I turn it into a blog post. So here it is. (Thanks to &lt;a href=&quot;https://www.twitter.com/sayzlim&quot;&gt;@sayzlim&lt;/a&gt; for the suggestion!)&lt;/p&gt;
&lt;p&gt;These tips have come from the tech community, but I think the majority of them can apply to any public speaking event.&lt;/p&gt;
&lt;h2 id=&quot;preparing-your-talk%3A-slides-and-content&quot; tabindex=&quot;-1&quot;&gt;Preparing your talk: Slides and content&lt;/h2&gt;
&lt;p&gt;You&#39;ve got the outline of your talk that you submitted to the Call for Papers, but how do you turn it into a full talk? Whether your talk is full-length or a shorter lightning talk, it can be quite stressful when you&#39;re deciding what should go in and what you should leave out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Find someone with speaking experience to help you put together your talk.&lt;/strong&gt; The organisers of ReactFest put me in touch with a lovely volunteer who offered to give me some pointers. Find a friend, mentor or colleague with experience of giving conference talks, and ask if they will help you out.&lt;/p&gt;
&lt;p&gt;One thing that came up repeatedly on Twitter was the concept of storytelling. Rather than just listing ideas or treating the talk like a tutorial, you want to &lt;strong&gt;tell a story&lt;/strong&gt;. This makes the talk so much more engaging, and more likely to be remembered.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/markdalgleish&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/754886061872979968/BzaOWhs1_normal.jpg&quot; alt=&quot;Avatar for markdalgleish&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/markdalgleish&quot;&gt;🧁 Mark Dalgleish &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/markdalgleish&quot;&gt;@markdalgleish&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/markdalgleish/status/955688673911103493&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/threepointone&quot;&gt;@threepointone&lt;/a&gt; Share a story, not a series of facts. Took me far too long to figure that one out.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955688673911103493&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;20 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 06:28:30 (UTC)&quot; href=&quot;https://twitter.com/markdalgleish/status/955688673911103493&quot;&gt;07:28 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1336281436685541376/fRSl8uJP_normal.jpg&quot; alt=&quot;Avatar for dan_abramov&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;дэн &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;@dan_abramov&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/dan_abramov/status/955591200769232896&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; It helps if you have one idea to center your talk around. Like in Inception movie, what’s the one thing you want to put in their heads? This helps you decide what to cut (and you might have to cut things when you realize you’re running over the day before the talk).&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955591200769232896&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;55 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:01:10 (UTC)&quot; href=&quot;https://twitter.com/dan_abramov/status/955591200769232896&quot;&gt;01:01 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;When it comes to putting a deck together, most people tend to use Google Slides, Keynote or PowerPoint, but tech folks might also like to try out &lt;a href=&quot;https://revealjs.com/#/&quot;&gt;Reveal.JS&lt;/a&gt;, which lets you write fully responsive slides in HTML or Markdown (perfect for code snippets!). I used it for a talk I gave at a meetup, and had the entire talk hosted on GitHub Pages just in case I had to use someone else&#39;s computer (which, in the end, I did!).&lt;/p&gt;
&lt;p&gt;Once you&#39;ve got the content nailed, you can focus on the design. Don&#39;t worry about being too fancy — you want your audience to focus on what you are saying rather than what&#39;s on the slides. &lt;strong&gt;Too many words on the slides will distract the audience, as will too many animated gifs!&lt;/strong&gt; You can always create another version of your deck with more details on for sharing afterwards, as suggested by &lt;a href=&quot;https://www.twitter.com/henrihelvetica&quot;&gt;@henrihelvetica&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/johnwards&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1504834746907607046/byLeFAmk_normal.jpg&quot; alt=&quot;Avatar for johnwards&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/johnwards&quot;&gt;John Wards &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/johnwards&quot;&gt;@johnwards&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/johnwards/status/955786243605843970&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Take all those points off the slide and move to speaker notes, replace with cat* picture that represents that section.&lt;br /&gt;&lt;br /&gt;People will focus on you rather than reading ahead and becoming bored.&lt;br /&gt;&lt;br /&gt;*other options are available&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955786243605843970&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;27 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:56:12 (UTC)&quot; href=&quot;https://twitter.com/johnwards/status/955786243605843970&quot;&gt;01:56 PM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Keep your slide theme nice and simple, and consider whether the theme you have chosen will be easily readable from the back of the room with a crappy projector. Put your name and Twitter handle (if you have one) at the bottom of every slide because people will forget it if you only put it at the beginning (thanks &lt;a href=&quot;https://www.twitter.com/claireinez&quot;&gt;@claireinez&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you&#39;re putting code in your slides, &lt;strong&gt;don&#39;t go overboard.&lt;/strong&gt; Sometimes it&#39;s inevitable — for example if you&#39;re talking about how a particular tool or library works —but as &lt;a href=&quot;https://www.twitter.com/alexmcpherson&quot;&gt;@alexmcpherson&lt;/a&gt; suggests, it&#39;s best to keep them short, 8–10 lines of code maximum. You can always share a repo or a CodePen link with your audience afterwards.&lt;/p&gt;
&lt;h2 id=&quot;practice-makes-perfect&quot; tabindex=&quot;-1&quot;&gt;Practice makes perfect&lt;/h2&gt;
&lt;p&gt;Something that came up over and over again: &lt;strong&gt;rehearse your talk!&lt;/strong&gt; Do it on your own, give it to your cat, make your colleagues listen to it and get their feedback. I got my fiancé to listen to my talk about &lt;a href=&quot;https://redux-saga.js.org/&quot;&gt;redux-saga&lt;/a&gt;, and even though he didn&#39;t know the content, he gave me some really helpful feedback about &lt;em&gt;how&lt;/em&gt; I was delivering the talk. &lt;strong&gt;Your manner of delivery is just as important as what you&#39;re saying.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Local developer meetups can be a fantastic place to &lt;strong&gt;try out your talk&lt;/strong&gt; before the conference and gather some feedback/see how it lands — a bit like how comedians try out new material in smaller venues before festivals and tours.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/jevakallio&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1530342542075695104/u546yO_I_normal.jpg&quot; alt=&quot;Avatar for jevakallio&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/jevakallio&quot;&gt;Jani Eväkallio &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/jevakallio&quot;&gt;@jevakallio&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/jevakallio/status/955557640821706752&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Rehearse three times:&lt;br /&gt;- First alone&lt;br /&gt;- Second with supportive audience (partner, friends, colleagues)&lt;br /&gt;- Finally, a smaller local meetup&lt;br /&gt;&lt;br /&gt;By the conference you&#39;ll know your timings &amp;amp; punchlines by heart and have ironed out any kinks, so you can focus on having fun&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955557640821706752&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;153 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 09:47:49 (UTC)&quot; href=&quot;https://twitter.com/jevakallio/status/955557640821706752&quot;&gt;10:47 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Rehearsing your talk will also help you to get a feel for &lt;strong&gt;how long it takes to run&lt;/strong&gt;. Your talk will be strictly timeboxed, so make sure you get your key points across in the time that you have.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1336281436685541376/fRSl8uJP_normal.jpg&quot; alt=&quot;Avatar for dan_abramov&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;дэн &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;@dan_abramov&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/dan_abramov/status/955589928011927553&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; If you haven’t practiced you will run over. My first talk at a local meetup was supposed to be 30 minutes, I only got through half of the slides. This is solved by practice: actually rehearse the whole talk (to an empty room, then to an audience).&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955589928011927553&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;56 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 11:56:07 (UTC)&quot; href=&quot;https://twitter.com/dan_abramov/status/955589928011927553&quot;&gt;12:56 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Don&#39;t be tempted to script out your entire talk, as it&#39;ll come across as a bit robotic (plus put a whole lot more pressure on you to learn it). Instead, become familiar with the key points of your talk and &lt;strong&gt;deliver those in a more improvised, natural way&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;technology-isn&#39;t-always-your-friend&quot; tabindex=&quot;-1&quot;&gt;Technology isn&#39;t always your friend&lt;/h2&gt;
&lt;p&gt;Make sure your talk works offline — you never know what&#39;s going to happen. I&#39;ve been to a tech conference before with no wifi or sockets for power. As &lt;a href=&quot;https://twitter.com/Naomi_Freeman/status/955565518488031234&quot;&gt;@naomi_freeman&lt;/a&gt; suggests: &amp;quot;Don&#39;t trust the wifi. Download any online content BEFORE travelling.&amp;quot;&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/shanselman&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1133122333290291200/xV9gO-D6_normal.jpg&quot; alt=&quot;Avatar for shanselman&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/shanselman&quot;&gt;Scott Hanselman 🇺🇦 &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/shanselman&quot;&gt;@shanselman&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/shanselman/status/955967486846951424&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; test your talk in Airplane mode&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955967486846951424&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;13 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 24, 2018 12:56:24 (UTC)&quot; href=&quot;https://twitter.com/shanselman/status/955967486846951424&quot;&gt;01:56 AM · Jan 24, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Dan Abramov suggests having a &lt;strong&gt;backup of the slides online&lt;/strong&gt; that will run on someone else&#39;s laptop. Google Slides can be run from anywhere if you share the link, or you can host your Reveal.JS talk somewhere like GitHub Pages. Make sure you are comfortable giving your talk &lt;strong&gt;without prompts&lt;/strong&gt;, as you might not be able to access your speaker notes.&lt;/p&gt;
&lt;p&gt;If you can, find out beforehand what the setup will be like at the conference. The projector they are using, the size of the room and the equipment available will all affect things like font size, colour scheme and audio.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/Paul_Bone&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1227157516125007872/wGv0kVwc_normal.jpg&quot; alt=&quot;Avatar for Paul_Bone&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/Paul_Bone&quot;&gt;Paul Bone &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/Paul_Bone&quot;&gt;@Paul_Bone&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/Paul_Bone/status/955662979504029696&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/MsAmandaDean&quot;&gt;@MsAmandaDean&lt;/a&gt; Whether the projector is DVI/VGA/HDMI etc. Whether it&#39;s 4:3 or 16:9. Whether the room is light or dark (should I use light slides or dark ones).&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955662979504029696&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;2 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 04:46:24 (UTC)&quot; href=&quot;https://twitter.com/Paul_Bone/status/955662979504029696&quot;&gt;05:46 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/CynthiaSavard&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/920814970522259457/RjXTRlt3_normal.jpg&quot; alt=&quot;Avatar for CynthiaSavard&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/CynthiaSavard&quot;&gt;Cynthia Savard &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/CynthiaSavard&quot;&gt;@CynthiaSavard&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/CynthiaSavard/status/955895439232028673&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/CallbackWomen&quot;&gt;@CallbackWomen&lt;/a&gt; Bring all of the dongles, bring your own clicker (usb) , plan for no presenter notes, always email yourself a pdf backup version&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955895439232028673&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;4 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 08:10:07 (UTC)&quot; href=&quot;https://twitter.com/CynthiaSavard/status/955895439232028673&quot;&gt;09:10 PM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Don&#39;t assume the organisers will provide the adaptor you need to connect your laptop! &lt;strong&gt;Bring it yourself just to be safe&lt;/strong&gt; (and label it with your name so nobody steals it).&lt;/p&gt;
&lt;h2 id=&quot;to-demo-or-not-to-demo%3F&quot; tabindex=&quot;-1&quot;&gt;To demo or not to demo?&lt;/h2&gt;
&lt;p&gt;This was a bit of a divisive one — should you have a live demo in your talk?&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/khanght&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1469049047981772803/wOmnrmf__normal.jpg&quot; alt=&quot;Avatar for khanght&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/khanght&quot;&gt;Khang Hoang &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/khanght&quot;&gt;@khanght&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/khanght/status/955595332993216512&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/dan_abramov&quot;&gt;@dan_abramov&lt;/a&gt; Demos won’t work&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955595332993216512&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;2 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:17:36 (UTC)&quot; href=&quot;https://twitter.com/khanght/status/955595332993216512&quot;&gt;01:17 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1336281436685541376/fRSl8uJP_normal.jpg&quot; alt=&quot;Avatar for dan_abramov&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;дэн &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;@dan_abramov&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/dan_abramov/status/955596853457969152&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/khanght&quot;&gt;@khanght&lt;/a&gt; &lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Mine worked tho&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955596853457969152&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;3 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:23:38 (UTC)&quot; href=&quot;https://twitter.com/dan_abramov/status/955596853457969152&quot;&gt;01:23 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;A demo can be a fantastic way of, well, demonstrating a technical concept. But there&#39;s always a risk that something will go wrong on the night — whether it&#39;s down to nerves, technical issues or just plain bad luck. You can avoid this by &lt;strong&gt;making a recording of it beforehand&lt;/strong&gt; that you can play to the audience and narrate what you&#39;re doing. Or have a &lt;strong&gt;working copy&lt;/strong&gt; that you can check out from Git in case of emergency (thanks to &lt;a href=&quot;https://twitter.com/wilslau&quot;&gt;Laura Wilson&lt;/a&gt; for that tip).&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1281071936605323266/wc1KRZLK_normal.jpg&quot; alt=&quot;Avatar for sarah_edo&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;Sarah Drasner &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;@sarah_edo&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/sarah_edo/status/955561991329923072&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/threepointone&quot;&gt;@threepointone&lt;/a&gt; make &#39;em work offline and have a backup screen recording of it in action&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955561991329923072&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;168 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 10:05:06 (UTC)&quot; href=&quot;https://twitter.com/sarah_edo/status/955561991329923072&quot;&gt;11:05 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Mac users can use &lt;a href=&quot;https://getkap.co/&quot;&gt;Kap&lt;/a&gt; to record screen captures in video or GIF format. There&#39;s also &lt;a href=&quot;https://launchpad.net/kazam&quot;&gt;Kazam&lt;/a&gt; for Linux and &lt;a href=&quot;https://camstudio.org/&quot;&gt;CamStudio&lt;/a&gt; for Windows.&lt;/p&gt;
&lt;p&gt;In some cases screen captures might even be better than live demos:&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/kyleshevlin&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/786039150667411456/t_0mWTZk_normal.jpg&quot; alt=&quot;Avatar for kyleshevlin&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/kyleshevlin&quot;&gt;Kyle Shevlin &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/kyleshevlin&quot;&gt;@kyleshevlin&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/kyleshevlin/status/955562633989562368&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/sarah_edo&quot;&gt;@sarah_edo&lt;/a&gt; &lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/threepointone&quot;&gt;@threepointone&lt;/a&gt; Yes, I don&#39;t recommend any live coding in your first one. No reason to add one more thing to be nervous about. And I&#39;ve seen Sarah&#39;s recordings, they work great for talks! She can describe what&#39;s going on without having to type at the same time.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955562633989562368&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;41 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 10:07:40 (UTC)&quot; href=&quot;https://twitter.com/kyleshevlin/status/955562633989562368&quot;&gt;11:07 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;And as &lt;a href=&quot;https://twitter.com/fforres/status/955624874298494976&quot;&gt;@fforres&lt;/a&gt; points out, don&#39;t rely on your audience to be sensible — if your demo involves live input from the audience, be warned, people might send in something rude!&lt;/p&gt;
&lt;h2 id=&quot;on-the-day&quot; tabindex=&quot;-1&quot;&gt;On the day&lt;/h2&gt;
&lt;p&gt;The dress code at tech conferences can be pretty casual, but if you&#39;re wearing a dress, make sure it has pockets as you&#39;ll need to attach a mic battery pack! &lt;a href=&quot;https://www.twitter.com/knitcodemonkey&quot;&gt;@knitcodemonkey&lt;/a&gt; says: &amp;quot;Wear something with a collar and a waistband for the mic. Wear comfy shoes.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bring a water bottle&lt;/strong&gt; and don&#39;t forget to drink from it to keep your voice happy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take off your lanyard&lt;/strong&gt; or any heavy jewellery before you go on, because microphones will pick up the sound of it rattling around.&lt;/p&gt;
&lt;p&gt;Make sure your laptop is ready for the talk: close all other programs, have the slides up and ready, and turn all notifications off. Put your laptop on airplane mode if you can. If you have a smart watch or phone on you, don&#39;t forget to silence that as well.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/HenriHelvetica&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/960605708202004481/MMNCgNgM_normal.jpg&quot; alt=&quot;Avatar for HenriHelvetica&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/HenriHelvetica&quot;&gt;Henri Helvetica 🚀 👨🏾‍🚀 🇭🇹 &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/HenriHelvetica&quot;&gt;@HenriHelvetica&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/HenriHelvetica/status/955733006349512704&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/keithjgrant&quot;&gt;@keithjgrant&lt;/a&gt; &lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; The lanyard bit is 100%! Add jewelry to that.&lt;br /&gt;Btw, ✈️ mode AND shut off wifi.&lt;br /&gt;Someone who loved my talk was kindly tweeting non stop about it and I kept getting notifications on my watch - I actually thought it was an emergency 🚨.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955733006349512704&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;8 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 09:24:40 (UTC)&quot; href=&quot;https://twitter.com/HenriHelvetica/status/955733006349512704&quot;&gt;10:24 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1336281436685541376/fRSl8uJP_normal.jpg&quot; alt=&quot;Avatar for dan_abramov&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;дэн &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;@dan_abramov&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/dan_abramov/status/955595076092260352&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/acdlite&quot;&gt;@acdlite&lt;/a&gt; And turn the notifications off! Otherwise you risk exposing private messages hopping on the screen during the talk 😛&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955595076092260352&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;20 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:16:34 (UTC)&quot; href=&quot;https://twitter.com/dan_abramov/status/955595076092260352&quot;&gt;01:16 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;As you&#39;re about to go on, you might feel the nerves. The audience is waiting! Take a deep breath and &lt;strong&gt;try to radiate confidence&lt;/strong&gt;, even if it doesn&#39;t come naturally to you. The audience won&#39;t know you&#39;re faking confidence (and soon you won&#39;t be). You know your stuff, you love your topic, you&#39;ve rehearsed it time and time again — &lt;strong&gt;you are ready&lt;/strong&gt;. Enjoy it.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1336281436685541376/fRSl8uJP_normal.jpg&quot; alt=&quot;Avatar for dan_abramov&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;дэн &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;@dan_abramov&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/dan_abramov/status/955590579148279809&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Peak scary is ten seconds before the talk. I didn’t anticipate it to be this scary. But once you get into your element (by talking about things you care about) the fear goes away completely, it even becomes fun. At least it did for me.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955590579148279809&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;69 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 11:58:42 (UTC)&quot; href=&quot;https://twitter.com/dan_abramov/status/955590579148279809&quot;&gt;12:58 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/jevakallio&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1530342542075695104/u546yO_I_normal.jpg&quot; alt=&quot;Avatar for jevakallio&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/jevakallio&quot;&gt;Jani Eväkallio &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/jevakallio&quot;&gt;@jevakallio&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/jevakallio/status/955555697223196672&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Projecting confidence is as good as having it. Even if you are not 100% happy with your talk, nobody knows what it was supposed to look like, so just rock your stuff and don&#39;t apologise for a thing&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955555697223196672&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;31 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 09:40:06 (UTC)&quot; href=&quot;https://twitter.com/jevakallio/status/955555697223196672&quot;&gt;10:40 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Be aware you might not be able to see anyone in the audience…&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/NikkitaFTW&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1407810876875419657/1PZPCpvD_normal.jpg&quot; alt=&quot;Avatar for NikkitaFTW&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/NikkitaFTW&quot;&gt;Sara Vieira &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/NikkitaFTW&quot;&gt;@NikkitaFTW&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/NikkitaFTW/status/955704311312519168&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/ReactFest&quot;&gt;@ReactFest&lt;/a&gt; One thing I didn&#39;t know and really surprised me is that you probably will not be able to see anything, the lights pointing at the stage will most likely almost blind you 🙁&lt;br /&gt;And you are going to rock!&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955704311312519168&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;4 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 07:30:38 (UTC)&quot; href=&quot;https://twitter.com/NikkitaFTW/status/955704311312519168&quot;&gt;08:30 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Move around a bit&lt;/strong&gt;, rather than standing still behind the podium. It can be tempting to just keep talking — don&#39;t forget to pause now and again.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1281071936605323266/wc1KRZLK_normal.jpg&quot; alt=&quot;Avatar for sarah_edo&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;Sarah Drasner &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;@sarah_edo&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/sarah_edo/status/955562218615025664&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Breathe.&lt;br /&gt;&lt;br /&gt;(seriously)&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955562218615025664&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;26 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 10:06:01 (UTC)&quot; href=&quot;https://twitter.com/sarah_edo/status/955562218615025664&quot;&gt;11:06 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/_davideast&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1429504343875670016/zjwrjcGY_normal.jpg&quot; alt=&quot;Avatar for _davideast&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/_davideast&quot;&gt;David East &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/_davideast&quot;&gt;@_davideast&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/_davideast/status/955597614560378880&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Plan out when you&#39;re going to pause during your talk. &quot;Letting it land&quot; is really important for the audience. It also keeps you from rambling at light speed (a habit I still have to unlearn for each and every talk)&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955597614560378880&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;39 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:26:40 (UTC)&quot; href=&quot;https://twitter.com/_davideast/status/955597614560378880&quot;&gt;01:26 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1336281436685541376/fRSl8uJP_normal.jpg&quot; alt=&quot;Avatar for dan_abramov&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;дэн &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/dan_abramov&quot;&gt;@dan_abramov&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/dan_abramov/status/955593635390808064&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/acdlite&quot;&gt;@acdlite&lt;/a&gt; Whenever you get nervous just take a pause. Breathe. Drink some water. It’s empowering to realize you can even make an awkward pause and everyone will just sit silently because you control the room 😎&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955593635390808064&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;75 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:10:51 (UTC)&quot; href=&quot;https://twitter.com/dan_abramov/status/955593635390808064&quot;&gt;01:10 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Be mindful how you address the audience — don&#39;t just fall back on &amp;quot;guys&amp;quot; considering your audience is likely to be a mix of genders (thanks &lt;a href=&quot;https://twitter.com/fforres/status/955624874298494976&quot;&gt;@fforres&lt;/a&gt;). Jokes are a fantastic way of lightening the mood and keeping the audience engaged, but avoid any risqué/potentially inappropriate jokes.&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/fuzzychef&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1450166432654712833/_tvvPyQ8_normal.jpg&quot; alt=&quot;Avatar for fuzzychef&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/fuzzychef&quot;&gt;Berkubernetus &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/fuzzychef&quot;&gt;@fuzzychef&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/fuzzychef/status/955660680765427712&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/Heronymus&quot;&gt;@Heronymus&lt;/a&gt; Risque&#39; jokes are a *really* bad idea in a public presentation.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955660680765427712&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;3 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 04:37:16 (UTC)&quot; href=&quot;https://twitter.com/fuzzychef/status/955660680765427712&quot;&gt;05:37 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Don&#39;t be put off if you make a mistake! If you leave something out or stumble over something, nobody will know. Keep going!&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/MandaLaceyS&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1520675351/me_normal.png&quot; alt=&quot;Avatar for MandaLaceyS&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/MandaLaceyS&quot;&gt;Amanda Stockwell &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/MandaLaceyS&quot;&gt;@MandaLaceyS&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/MandaLaceyS/status/955606916163604480&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/justjessdc&quot;&gt;@justjessdc&lt;/a&gt; You&#39;ll notice your own &quot;mistakes&quot; 100 times more than anyone else. But no one else knows what you were planning to say. So if you take a breath and keep going, probably no one else will know there was even a blip. Also, bring extra clothes. I spilled coffee😂&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955606916163604480&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;29 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 01:03:37 (UTC)&quot; href=&quot;https://twitter.com/MandaLaceyS/status/955606916163604480&quot;&gt;02:03 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/_s_hari&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1515077650557149195/ZoR5WdFD_normal.jpg&quot; alt=&quot;Avatar for _s_hari&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/_s_hari&quot;&gt;Santosh Hari 😷 &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/_s_hari&quot;&gt;@_s_hari&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/_s_hari/status/955760274623131649&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Prep! Whatever the content, prep till you can wake up in the middle of the night and do the talk from memory&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955760274623131649&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;2 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 11:13:01 (UTC)&quot; href=&quot;https://twitter.com/_s_hari/status/955760274623131649&quot;&gt;12:13 PM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;And don&#39;t forget the most important thing:&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/justinfagnani&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/378800000808710206/2dbdaa1cb7b0db02f997aea5b40f29b8_normal.jpeg&quot; alt=&quot;Avatar for justinfagnani&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/justinfagnani&quot;&gt;Justin Fagnani &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/justinfagnani&quot;&gt;@justinfagnani&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/justinfagnani/status/955556013943373824&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; &lt;a href=&quot;https://twitter.com/threepointone&quot;&gt;@threepointone&lt;/a&gt; Everyone&#39;s rooting for you&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955556013943373824&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;18 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 09:41:21 (UTC)&quot; href=&quot;https://twitter.com/justinfagnani/status/955556013943373824&quot;&gt;10:41 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/damovisa&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/982382127089041408/dPUE3zMX_normal.jpg&quot; alt=&quot;Avatar for damovisa&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/damovisa&quot;&gt;Damian Brady 🥑 💉 💉 💉 #AlwaysWasAlwaysWillBe &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/damovisa&quot;&gt;@damovisa&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/damovisa/status/955721090147303424&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; The audience is on your side. They want you to succeed.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955721090147303424&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;14 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 08:37:18 (UTC)&quot; href=&quot;https://twitter.com/damovisa/status/955721090147303424&quot;&gt;09:37 AM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/jonskeet&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/783726102996922368/4OTYaJ-o_normal.jpg&quot; alt=&quot;Avatar for jonskeet&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/jonskeet&quot;&gt;Jon Skeet &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/jonskeet&quot;&gt;@jonskeet&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/jonskeet/status/955574730421088257&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; If you enjoy yourself (and your topic) then other people will enjoy the talk. Enthusiasm is viral. People remember good talks. People forget bad talks. People really remember and hate on *nasty* (sexist, racist etc) talks; never be worse than yourself just to be memorable.&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955574730421088257&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;33 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 10:55:44 (UTC)&quot; href=&quot;https://twitter.com/jonskeet/status/955574730421088257&quot;&gt;11:55 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;You&#39;re at the conference because you love your topic, and so does everyone else there. You&#39;re all on the same team. As &lt;a href=&quot;https://twitter.com/tlakomy/status/955557815292227585&quot;&gt;@tlakomy&lt;/a&gt; assures me: &amp;quot;It&#39;s going to be okay&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;taking-questions%3F&quot; tabindex=&quot;-1&quot;&gt;Taking questions?&lt;/h2&gt;
&lt;p&gt;Sarah Drasner recommends not taking questions during your first talk:&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1281071936605323266/wc1KRZLK_normal.jpg&quot; alt=&quot;Avatar for sarah_edo&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;Sarah Drasner &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/sarah_edo&quot;&gt;@sarah_edo&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/sarah_edo/status/955564180970528768&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; oh! a better one: don&#39;t take questions your first time. I don&#39;t recommend it because you get done with the tada! and then it just kind of tapers off from there. plus the best questions aren&#39;t performative, they&#39;re the ones that happen off the stage face to face&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955564180970528768&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;65 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 22, 2018 10:13:48 (UTC)&quot; href=&quot;https://twitter.com/sarah_edo/status/955564180970528768&quot;&gt;11:13 PM · Jan 22, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;That said, it&#39;s a personal choice — if you feel comfortable (and time allows it) you can take as many questions as you want. An excellent tip from &lt;a href=&quot;https://www.twitter.com/bradwaynemartin&quot;&gt;@bradwaynemartin&lt;/a&gt;: &lt;strong&gt;always repeat the questions back to the audience&lt;/strong&gt;, as the microphone won&#39;t pick them up.&lt;/p&gt;
&lt;p&gt;But if anyone does challenge any decisions you made, you can fire this straight back:&lt;/p&gt;
&lt;blockquote class=&quot;tweet-card&quot;&gt;&lt;div class=&quot;tweet-header&quot;&gt;&lt;a class=&quot;tweet-profile&quot; href=&quot;https://twitter.com/hpcprogrammer&quot;&gt;&lt;img src=&quot;https://pbs.twimg.com/profile_images/1532932743939727360/x4owY3LL_normal.jpg&quot; alt=&quot;Avatar for hpcprogrammer&quot; /&gt;&lt;/a&gt;&lt;div class=&quot;tweet-author&quot;&gt;&lt;a class=&quot;tweet-author-name&quot; href=&quot;https://twitter.com/hpcprogrammer&quot;&gt;Fernanda Foertter | 🇧🇷🇺🇸🥑👩🏽‍💻🤓 &lt;/a&gt;&lt;a class=&quot;tweet-author-handle&quot; href=&quot;https://twitter.com/hpcprogrammer&quot;&gt;@hpcprogrammer&lt;/a&gt;&lt;/div&gt;&lt;a class=&quot;tweet-bird&quot; href=&quot;https://twitter.com/hpcprogrammer/status/955779489140703232&quot;&gt;&lt;div class=&quot;tweet-bird-icon&quot; role=&quot;presentation&quot; aria-label=&quot;View on Twitter&quot; title=&quot;View on Twitter&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;tweet-body&quot;&gt;&lt;a href=&quot;https://twitter.com/type__error&quot;&gt;@type__error&lt;/a&gt; Best answer I ever gave to a “why would you do it this way” was “why not? Seemed like a good place to start. Next question?” I don’t know why it took me so long to learn it&lt;/p&gt;&lt;div class=&quot;tweet-images&quot;&gt;&lt;/div&gt;&lt;div class=&quot;tweet-footer&quot;&gt;&lt;a class=&quot;tweet-like&quot; href=&quot;https://twitter.com/intent/like?tweet_id=955779489140703232&quot;&gt;&lt;div class=&quot;tweet-like-icon&quot; aria-label=&quot;Like&quot; title=&quot;Like&quot; role=&quot;img&quot;&gt;&lt;/div&gt;&lt;span class=&quot;tweet-like-count&quot;&gt;21 &lt;/span&gt;&lt;/a&gt;&lt;a class=&quot;tweet-date&quot; title=&quot;Time Posted: Jan 23, 2018 12:29:22 (UTC)&quot; href=&quot;https://twitter.com/hpcprogrammer/status/955779489140703232&quot;&gt;01:29 PM · Jan 23, 2018&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;h2 id=&quot;good-luck!&quot; tabindex=&quot;-1&quot;&gt;Good luck!&lt;/h2&gt;
&lt;p&gt;To all first-time or aspiring speakers: you&#39;ve got this!.&lt;/p&gt;
&lt;p&gt;If you&#39;re looking to get into the world of conference speaking, a great place to start is local developer meetups (if you can&#39;t find one, start one!). You might even start by giving talks at work to your colleagues. The more you do it, and the more feedback you gather, the more comfortable you&#39;ll become.&lt;/p&gt;
&lt;p&gt;I also recommend taking a look at Jo Francetti&#39;s &lt;a href=&quot;https://medium.com/samsung-internet-dev/public-speaking-for-beginners-8bdee16123ba&quot;&gt;guide to Public Speaking For Beginners&lt;/a&gt; and Emily Webber&#39;s &lt;a href=&quot;https://github.com/ewebber/whatspeakersneed/blob/master/index.md&quot;&gt;list of things that speakers need from conference organisers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thank you to everyone who contributed to the enormous Twitter thread that led to the creation of this post. If I have forgotten to credit anyone, or you would prefer not to be included, please get in touch.&lt;/p&gt;
</content>
  </entry>
</feed>