<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Schalk Neethling</title>
    <description>The latest articles on Forem by Schalk Neethling (@schalkneethling).</description>
    <link>https://forem.com/schalkneethling</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F94588%2F013d6c41-33f4-48bc-a21c-d043d4858c85.jpeg</url>
      <title>Forem: Schalk Neethling</title>
      <link>https://forem.com/schalkneethling</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/schalkneethling"/>
    <language>en</language>
    <item>
      <title>Raise The Red Flag Early: The Power of Explicit Return Types in TypeScript</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Sat, 28 Dec 2024 17:11:51 +0000</pubDate>
      <link>https://forem.com/schalkneethling/raise-the-red-flag-early-the-power-of-explicit-return-types-in-typescript-29lb</link>
      <guid>https://forem.com/schalkneethling/raise-the-red-flag-early-the-power-of-explicit-return-types-in-typescript-29lb</guid>
      <description>&lt;p&gt;As developers, we're always on the lookout for ways to prevent errors before they make their way into production. One of the ways TypeScript can be your friend here is through the use of explicit return type annotations. This seemingly simple feature can dramatically improve your code's reliability and provide a better developer experience, especially for consumers of an API, utility functions, or library.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Subtle Pitfall of Implicit Returns
&lt;/h2&gt;

&lt;p&gt;Consider a function that looks innocent enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastLogin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastLogin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inactive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, this function seems fine. But there's a hidden problem: if the conditions aren't met, the function will implicitly return &lt;code&gt;undefined&lt;/code&gt;. This can lead to runtime errors that may be difficult to track down. Also, instead of TypeScript raising an error right at the function definition, the error would only be raised at the call site.&lt;/p&gt;

&lt;p&gt;You can understand how frustrating it can be for developers using your code. So how would explicit return types help here?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Magic of Explicit Return Types
&lt;/h2&gt;

&lt;p&gt;By adding an explicit return type, TypeScript will raise the red flag immediately at the function definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastLogin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inactive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dormant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastLogin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inactive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you &lt;a href="https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAcwKZQKoGdUCcDKUAhlCFgBQA2RWUAMnMjGAFyIAiJqAlGwERFoMAG6o+iAD6I+zQbFHipfACZxcAWyJgo4gN4AoRIggJaiZUQCeWfMwioGTJAF5DRxOU5RUAOjBwAd3JuRABaRGpaR2YfNCgAFRh1VGCQgHoPAEYABlzEACpEADZsguLSwoAmABZuAG59NxhgDwtrW0gHRmZEAB5EAHYQg3dEXHQQXCQBIQUGowBfRqNm1qsbOy6nPsQAZmzhtyNx0inpWVmxecQlhaA" rel="noopener noreferrer"&gt;enter this code into the TypeScript Playground&lt;/a&gt;, you will immediately be presented with an error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Function lacks ending return statement and return type does not include 'undefined'.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You as the author of this function can now be proactive in addressing this &lt;em&gt;before&lt;/em&gt; it becomes a problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastLogin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inactive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dormant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastLogin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;daysSinceLogin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inactive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dormant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;The benefits are immediate and powerful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Early Error Detection&lt;/strong&gt;: TypeScript will highlight the issue at the function definition, not at the call site.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Forced Completeness&lt;/strong&gt;: By specifying a return type, you're essentially creating a contract that your function must fulfill. TypeScript becomes your code reviewer, ensuring you handle all possible scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Code Readability&lt;/strong&gt;: Explicit return types serve as documentation. They clearly communicate what a function is expected to return.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Update: 11 December 2024
&lt;/h3&gt;

&lt;p&gt;A reader (&lt;a href="https://hachyderm.io/@caillou@fosstodon.org" rel="noopener noreferrer"&gt;Pierre Spring&lt;/a&gt;) &lt;a href="https://hachyderm.io/@caillou@fosstodon.org/113633302092394767" rel="noopener noreferrer"&gt;reminded me on Mastodon&lt;/a&gt; that you can configure TypeScript to prevent you from not defining a return. You can do this by setting the &lt;code&gt;noImplicitReturns&lt;/code&gt; flag to &lt;code&gt;true&lt;/code&gt; in your &lt;code&gt;tsconfig.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noImplicitReturns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more about this flag in the &lt;a href="https://www.typescriptlang.org/tsconfig/#noImplicitReturns" rel="noopener noreferrer"&gt;TypeScript documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credit Where It's Due
&lt;/h2&gt;

&lt;p&gt;This approach was inspired by a lesson from &lt;a href="https://frontendmasters.com/courses/typescript-v4/" rel="noopener noreferrer"&gt;Mike North's TypeScript course on Frontend Masters&lt;/a&gt;. It's a testament to how small, intentional typing choices can significantly improve code quality and usability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Defining explicit return types is more than just a TypeScript feature; it encourages you to think through all possible code paths, make your intentions clear, and catch potential issues before they become pain points. I hope you found this helpful and that you will use this to make your functions more resilient. Happy coding! 🚀&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Introducing the Mycelium Network Junior Developer Hour</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Tue, 07 May 2024 15:47:17 +0000</pubDate>
      <link>https://forem.com/schalkneethling/introducing-the-mycelium-network-junior-developer-hour-3o6l</link>
      <guid>https://forem.com/schalkneethling/introducing-the-mycelium-network-junior-developer-hour-3o6l</guid>
      <description>&lt;p&gt;For almost two years I have been making a &lt;a href="https://schalkneethling.substack.com/s/the-mycelium-network-podcast" rel="noopener noreferrer"&gt;podcast called the Mycelium Network podcast&lt;/a&gt; that forms part of the Mycelium Network community.&lt;/p&gt;

&lt;p&gt;The primary goal of the community is to create a space for early-stage (entry-level, junior) web developers to find peers and mentors to help them through their learning journey. The primary goal of the podcast is to create a space where these same folks can share their stories and have a voice.&lt;/p&gt;

&lt;p&gt;A place where they can share their ups, their downs, and their dreams. The ultimate goal is to open up opportunities to break into the industry and start to build their dream life.&lt;/p&gt;

&lt;p&gt;So far, it has been mildly successful but has not achieved the goals I set out for it. With this in mind, I am pivoting how I am approaching this going forward. Instead of a pure audio podcast with me and a guest, this will now be a live-streamed event &lt;del&gt;every two weeks&lt;/del&gt; once a month, known as the Mycelium Network Junior Developer hour.&lt;/p&gt;

&lt;p&gt;Here is how it will work.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;Every two weeks&lt;/del&gt; Once a month on a Wednesday at 5 PM UTC I will host an hour-long live stream across YouTube, Twitch, and LinkedIn, &lt;a href="https://riverside.fm/" rel="noopener noreferrer"&gt;using Riverside.fm&lt;/a&gt;. I will invite another mentor to join me for the stream, but most importantly, I invite junior developers to join the stream.&lt;/p&gt;

&lt;p&gt;As a junior developer, you can participate in the stream in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Listen in&lt;/li&gt;
&lt;li&gt;You can contact me beforehand to express interest in sharing your story live on stream&lt;/li&gt;
&lt;li&gt;Bring your questions for us to answer hopefully&lt;/li&gt;
&lt;li&gt;You can do all this with your camera on or off and using your name or a pseudonym, whichever you feel most comfortable with.&lt;/li&gt;
&lt;li&gt;You can also email your questions or share your story, which we will read during the stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stream will be recorded and made available on YouTube and as an audio podcast (wherever you listen to podcasts) a week after the live stream. My hope is that this more interactive form of the podcast will be more effective, garner more interest, and provide a better platform for junior developers to share their stories and be noticed.&lt;/p&gt;

&lt;p&gt;The first Junior Developer Hour will be on &lt;del&gt;May 22&lt;/del&gt; May 29 at 5 PM UTC and you can email me at &lt;a href="mailto:juniordevhour@mechanical.ink"&gt;juniordevhour@mechanical.ink&lt;/a&gt; to express interest in sharing your story live on the stream, share your story in text format, or send along your questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Times in other regions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;9 PM - Dubai&lt;/li&gt;
&lt;li&gt;7 PM - South Africa&lt;/li&gt;
&lt;li&gt;5 PM - United Kingdom&lt;/li&gt;
&lt;li&gt;2 PM - Rio de Janeiro&lt;/li&gt;
&lt;li&gt;1 PM - New York&lt;/li&gt;
&lt;li&gt;11 AM - Denver, Colorado&lt;/li&gt;
&lt;li&gt;10 AM - San Francisco&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You will also be able to ask questions during the stream.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I look forward to experimenting with this new format, learning your stories, and building out the community. Comments, questions, suggestions? Please share them below.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Podcast: From Math Teacher to Web Developer: Adilson Sandoval's Inspiring Career Transition</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Fri, 03 May 2024 20:58:23 +0000</pubDate>
      <link>https://forem.com/schalkneethling/podcast-from-math-teacher-to-web-developer-adilson-sandovals-inspiring-career-transition-255h</link>
      <guid>https://forem.com/schalkneethling/podcast-from-math-teacher-to-web-developer-adilson-sandovals-inspiring-career-transition-255h</guid>
      <description>&lt;p&gt;Breaking into the web developer field can be a daunting task, especially for those without a traditional computer science background. Adilson Sandoval's story serves as an inspiration for anyone aspiring to transition into a tech career, regardless of their starting point.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LOYeH5hJGgo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Adilson's journey began as a mathematics teacher, a profession he had dedicated nearly a decade of his life to. However, the desire for remote work opportunities and a higher income prompted him to explore alternative career paths. With a background in programming and a passion for problem-solving, web development seemed like a natural fit.&lt;/p&gt;

&lt;p&gt;Undeterred by the challenges that lay ahead, Adilson embarked on a self-taught learning journey, leveraging free online resources like MDN Web Docs and JavaScript.info. These platforms not only provided comprehensive learning materials but also fostered a sense of community, allowing him to connect with fellow learners and seek guidance when needed.&lt;/p&gt;

&lt;p&gt;As Adilson delved deeper into the world of web development, he quickly realized that securing his first job would be no easy feat. Numerous rejections and a lack of feedback during the job-hunting process threatened to erode his motivation. However, his unwavering resilience and determination kept him moving forward.&lt;/p&gt;

&lt;p&gt;One of the key strategies that set Adilson apart was his commitment to contributing to open-source projects. By actively participating in these collaborative endeavors, he gained invaluable experience, showcased his skills, and demonstrated his ability to work in a team environment. This hands-on approach not only bolstered his portfolio but also allowed him to forge connections within the developer community.&lt;/p&gt;

&lt;p&gt;Throughout his journey, Adilson encountered obstacles that tested his perseverance, such as imposter syndrome and the stress of adapting to a professional work environment as a newcomer. However, he drew strength from supportive communities and networks, which provided motivation, feedback, and learning opportunities when he needed them most.&lt;/p&gt;

&lt;p&gt;One of the most valuable lessons Adilson imparts is the importance of embracing a growth mindset. As a web developer, continuous learning and adaptation are essential to keeping pace with the ever-evolving tech landscape. By prioritizing productivity, exploring opportunities for personal growth, and maintaining a healthy work-life balance, Adilson has created a sustainable and rewarding career path for himself.&lt;/p&gt;

&lt;p&gt;For those aspiring to follow in Adilson's footsteps, his journey serves as a powerful reminder that barriers can be overcome with determination, strategic planning, and a willingness to learn and adapt. By leveraging free online resources, contributing to open-source projects, and fostering a supportive network, individuals from diverse backgrounds can pave their way into the world of web development and unlock a multitude of career opportunities.&lt;/p&gt;




&lt;p&gt;What have been some of the biggest challenges you have faced as a junior or early-stage web developer? Share your journey in the comments.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://schalkneethling.substack.com/p/from-math-teacher-to-web-developer" rel="noopener noreferrer"&gt;Learn more on Substack&lt;/a&gt;, or listen wherever you listen to podcasts.&lt;/p&gt;

</description>
      <category>community</category>
      <category>codenewbie</category>
      <category>career</category>
    </item>
    <item>
      <title>What we lose at the gates</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Thu, 25 Apr 2024 20:46:08 +0000</pubDate>
      <link>https://forem.com/schalkneethling/what-we-lose-at-the-gates-45df</link>
      <guid>https://forem.com/schalkneethling/what-we-lose-at-the-gates-45df</guid>
      <description>&lt;p&gt;Perhaps it is the social bubble I find myself in, but it seems there is a lot of talk about gatekeeping happening at the moment. While the bubble metaphor does not quite work for what will follow, I do not have a better one, so humor me.&lt;/p&gt;

&lt;p&gt;I want to start by telling you a story.&lt;/p&gt;




&lt;p&gt;I know this person who, at age 15, discovered their love for music and guitar. At the time, it was hard rock, which evolved into heavy metal and later death metal. School was okay, and they did really well at some sports activities such as tennis and cricket, but their participation was mainly because of the fringe benefits bestowed upon those who excelled in these activities.&lt;/p&gt;

&lt;p&gt;What they could not wait for was to get home, pick up their axe (a common name for an electric guitar), play along with their favorite tunes, practice scales, sweeping, tapping, and write music. Even better was the weekends when the band got together and made music. There was no option to study music at school, so their interest in schoolwork declined over time, as did their grades.&lt;/p&gt;

&lt;p&gt;At the end of grade 9, they decided to leave school and go to a local college to study music (classical guitar) and music theory. Unfortunately, after only a year at college, the music department closed. They faced a choice: C'est la vie and go back to school and the way things were, or decide to take the road less traveled and do private tutoring for guitar and music theory.&lt;/p&gt;

&lt;p&gt;They chose the latter, and some might say it made all the difference.&lt;/p&gt;

&lt;p&gt;After a couple of years of dedication and hard work, they started winning one music competition after another, played at music festivals, and passed their grade 8 practical guitar exam with the highest grade in the institution's history. Wanting to pursue their performer's licentiate and possibly a teacher's licentiate, they encountered a hurdle (gate). Without a matric (grade 12), this was not possible. Not being one to give up easily, they signed up to do their grade 11 and 12 in one year and write their final year exams while studying through correspondence, all while continuing to study music theory and playing concerts.&lt;/p&gt;

&lt;p&gt;After completing the obligatory grade 12, they had the opportunity to attend classical guitar master classes in Bath, UK. Not something one could pass up, they jumped at the opportunity. Upon returning, they spent some time teaching guitar and music theory, played at local festivals, and met the woman of their dreams.&lt;/p&gt;

&lt;p&gt;They got married and started a life together. Another opportunity came knocking – the chance to travel to the Netherlands to play a house concert. After returning from the trip, another challenge awaited – their first child was on the way. After giving teaching a proper go and playing more concerts, it became clear that passion and love alone would not pay the bills.&lt;/p&gt;

&lt;p&gt;It was at this time that the internet was making itself known, and an interest started to form. This was not new, as they had always been interested in computers from the days of Visual Basic. They signed up for graphic design classes using the Corel suite of tools. This did not quite scratch the itch, and they decided to sign up for a 6-month course in web design. This, along with a tool called Macromedia Flash, unlocked a new world of possibilities. They could use their design skills and combine them with motion and sound to build multimedia pieces for clients from all over the world thanks to platforms such as Elance and the ability to reach across borders through the power of the internet.&lt;/p&gt;

&lt;p&gt;After some time, they signed up for a diploma in Java 2, which introduced them to the world of building software and software that could run in the browser through Java Applets. Java was also the technology that introduced them to open-source through projects such as the Apache Foundation and the Tomcat server. Through open source, they were introduced to the world of web standards and web accessibility.&lt;/p&gt;

&lt;p&gt;After some time working in the Java world, later dabbling with Java 2 Micro Edition (J2ME) to build software for the Blackberry, and then finally moving to enterprise Java (Java EE) using Tomcat and JBoss, they had worked at a variety of corporate companies, but something was missing – the passion they had back in the days of making music.&lt;/p&gt;

&lt;p&gt;Finally, in late 2011, they found the community that would reignite this passion. The community was built around open-source, the open web, web standards, and building a web based on &lt;a href="https://www.mozilla.org/en-US/about/manifesto/" rel="noopener noreferrer"&gt;10 principles known as the Mozilla Manifesto&lt;/a&gt;. They saw an opening for a front-end web developer at Mozilla (globally remote), applied for the role, and resigned from their current employer before having gotten the thumbs-up from Mozilla.&lt;/p&gt;

&lt;p&gt;Thankfully, the gods were smiling upon them and their family, and the offer from Mozilla came to be. They spent almost 12 years working at Mozilla on a wide variety of projects, from web to Firefox OS, the Firefox onboarding experience, the shape of the web project, and finally, MDN Web Docs.&lt;/p&gt;

&lt;p&gt;In late 2023, they made the difficult decision to leave Mozilla, tried to start their own company (during a time when the world economy was not great), realized the wheels were coming undone, and thankfully landed a role at the startup BoxyHQ.&lt;/p&gt;

&lt;p&gt;In April of 2024, their paths would diverge, and they are now on the precipice of something wonderful. What the next part of the journey will be, they do not yet know, but they are cautiously optimistic.&lt;/p&gt;




&lt;p&gt;If you have not yet realized, the protagonist in the story is me.&lt;/p&gt;

&lt;p&gt;This is my story.&lt;/p&gt;

&lt;p&gt;My name is Schalk Neethling, I live in Pretoria, South Africa, and I am a proudly self-taught frontend engineer. I got where I am today through perseverance and never allowing myself to give up. With that said, this would not have been possible without the incredible support from family, friends, and the wonderful open-source community I have now been a part of for going on 15 years.&lt;/p&gt;

&lt;p&gt;There is much more to my story, but I will save all the gory details for another day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did I choose to share all of this?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I shared it because at any point during this story, my journey could have been cut short, and things could have turned out very differently for me if I had been blocked from participating and applying to the opportunities that came my way because I did not finish school in the same way as many others, because I was not in the top 5% of those in Grade 12, or because I do not have a university degree.&lt;/p&gt;

&lt;p&gt;I do face limitations and have to swallow bitter pills from time to time when I cannot apply for a role because of where I live. Thankfully, there are enough companies with a big enough vision who embrace what it truly means to be a remote company. I have also felt discriminated against due to salary scales based on where you live and not your contribution to the company (by the way, I am here to tell you that this can lead to very uncomfortable conversations between peers).&lt;/p&gt;

&lt;p&gt;So what do we lose at the gate? While I do not consider myself the greatest software engineer, designer, contributor, or maker, I do know that I have something worthwhile to contribute to the world.&lt;/p&gt;

&lt;p&gt;When industries, companies, and individuals with seeming authority close the gates and slam shut the padlock on those who chose the road less traveled, these are the people we lose at the gate.&lt;/p&gt;

&lt;p&gt;These are the people who miss out on contributing their voice and their skills to the world. These are also the people those on the other side of the gate are missing out on working with and learning from.&lt;/p&gt;

&lt;p&gt;If we truly want a diverse, rich, welcoming, and vibrant global community of contributors and makers, it is time to unlock the padlock and open the gates.&lt;/p&gt;

</description>
      <category>career</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>How do you use git rebase? Let's go through one use case</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Tue, 23 Apr 2024 21:43:18 +0000</pubDate>
      <link>https://forem.com/schalkneethling/how-do-you-use-git-rebase-lets-go-through-one-use-case-28hl</link>
      <guid>https://forem.com/schalkneethling/how-do-you-use-git-rebase-lets-go-through-one-use-case-28hl</guid>
      <description>&lt;p&gt;I have been making these short (1 to 5-minute) videos covering a specific topic that I use daily or frequently. I have been posting them to my YouTube channel but they have not gained much traction over there so, I thought I would share them here along with an extended transcript.&lt;/p&gt;

&lt;p&gt;If you like this one and want to see more, please let me know in the comments. If there is something specific you would like me to cover, same deal. 😉 👍&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Hei6HrJslxQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Let's say you opened a pull request and then reviewed your code and realized there's something that you forgot or want to change. You could make the change, add a new commit, and push to your code hosting service of choice, but now you have two commits.&lt;/p&gt;

&lt;p&gt;While &lt;a href="https://www.youtube.com/watch?v=36p3Z0x8EhQ" rel="noopener noreferrer"&gt;using multiple commits can be incredibly useful&lt;/a&gt;, I like to start my initial pull (merge) request with a single commit. This is a general practice I picked up while working at Mozilla and it has served me well.&lt;/p&gt;

&lt;p&gt;Ok, good to know, but what do you do when you inevitably run into this scenario? In these instances, &lt;code&gt;git rebase&lt;/code&gt; is your friend.&lt;/p&gt;

&lt;p&gt;After you have added your new commit, type the following in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-i&lt;/code&gt; above will put you into interactive mode and &lt;code&gt;main&lt;/code&gt; is the branch against which you want to rebase. When you press enter, you will see something similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pick 4ad8867 page: identity federation product page
pick d57c578 small prose change

&lt;span class="c"&gt;# Rebase 2004347..396a1b6 onto 2004347 (2 commands)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will be followed with a lot of documentation concerning the command and the various options you have.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Addressing all of those is not in the scope of this post, but if you would like me to cover this in more detail, let me know.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this use case, I almost always use &lt;code&gt;fixup&lt;/code&gt; over the other options. The reason I use &lt;code&gt;fixup&lt;/code&gt; over &lt;code&gt;squash&lt;/code&gt; is that I only want to keep the commit message from the initial commit. That then is also the primary difference between these two options. Let's &lt;code&gt;fixup&lt;/code&gt; our commit history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pick 4ad8867 page: identity federation product page
f d57c578 small prose change

&lt;span class="c"&gt;# Rebase 2004347..396a1b6 onto 2004347 (2 commands)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have done the above, you will be left with a single commit and only the initial commit message. Great! All that is left to do is push this to the remote repository.&lt;/p&gt;

&lt;p&gt;If you try to do this using &lt;code&gt;git push origin branch-name&lt;/code&gt;, you will encounter an error message and Git will not allow you to push to the remote. This is because the above action changed the history (as mentioned above) and Git generally does not want to encourage this.&lt;/p&gt;

&lt;p&gt;However, we are okay with having changed the history so we can use the &lt;code&gt;-f&lt;/code&gt; (force) flag to tell Git that we know what we are doing and to allow our push to overwrite what exists on the remote branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-f&lt;/span&gt; origin branch-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we now have our most recent changes on the remote branch, but still only have a single commit using our initial commit message.&lt;/p&gt;




&lt;p&gt;I hope that you found this helpful. As mentioned earlier, if you would like more of these, have specific topics you would like me to cover, or have any other feedback, please let me know in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>git</category>
      <category>howto</category>
    </item>
    <item>
      <title>Seeking suggestions for virtual co-working</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Sun, 21 Apr 2024 11:41:54 +0000</pubDate>
      <link>https://forem.com/schalkneethling/seeking-suggestions-for-virtual-co-working-2c6f</link>
      <guid>https://forem.com/schalkneethling/seeking-suggestions-for-virtual-co-working-2c6f</guid>
      <description>&lt;p&gt;Hey All!&lt;/p&gt;

&lt;p&gt;I am curious if there are any communities or online platforms you all use for virtual co-working. Being able to work remotely has a lot of benefits, but sometimes, it can get a bit lonely. Human beings are generally social creatures and need some human interaction, accountability, or even just the sense that there is someone else around.&lt;/p&gt;

&lt;p&gt;This can be especially true late at night or during the early morning hours.  I am curious to learn if there are such services, if there is a need for such a service, or how you work around it.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>community</category>
    </item>
    <item>
      <title>10 Top accessibility errors and how to avoid and fix them</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Mon, 15 Apr 2024 20:55:15 +0000</pubDate>
      <link>https://forem.com/schalkneethling/10-top-accessibility-errors-and-how-to-avoid-and-fix-them-1ncd</link>
      <guid>https://forem.com/schalkneethling/10-top-accessibility-errors-and-how-to-avoid-and-fix-them-1ncd</guid>
      <description>&lt;p&gt;In late December of 2023, &lt;a href="https://www.tpgi.com/the-top-accessibility-errors-found-in-2023/" rel="noopener noreferrer"&gt;TPGi posted its list of the top accessibility errors&lt;/a&gt; found through its ARC automation tools in 2023. I am not just going to list them here as that will not be very useful to anyone. What I decided is that the only way there will be a chance that these do not end up on the list again at the end of 2024 is to explain these errors and offer a solution.&lt;/p&gt;

&lt;p&gt;So here we go. There are ten errors in total, but some are closely related and will be grouped in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  No link text, missing link alt attribute, or no label for button
&lt;/h2&gt;

&lt;p&gt;Links are the lifeblood of the web. It is how we link pages together, it is how crawlers index the web, and it is how we get around websites and applications.&lt;/p&gt;

&lt;p&gt;When link text is missing or is not meaningful, it becomes problematic for keyboard users and those using assistive technologies such as screen readers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:peter@example.com"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;svg&lt;/span&gt;
    &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;
    &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"16"&lt;/span&gt;
    &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"16"&lt;/span&gt;
    &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
    &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 16 16"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt;
      &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471z"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/svg&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might have seen code like this. We use an anchor link with a &lt;code&gt;mailto&lt;/code&gt; and then instead of text, we add an SVG icon. If you look at this visually, it is a rather well-known icon of a paper plane and without any styling, the SVG icon will be blue, which most people will recognize as a link. In addition, you can tab to it as it is an interactive element however, if you do so with a screen reader, the screen reader will read out something like, "link".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can get into the same problem when using a &lt;code&gt;button&lt;/code&gt; element and the solutions are the same. To not make this post longer than it already is, I will not dig into the details, but feel free to ask me for more information in the comments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/F4Pg_f84FXQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The screen reader user therefore has no idea what this link will do if they trigger it. With the SVG nested in the HTML, we can use the &lt;code&gt;title&lt;/code&gt; SVG element to fix the problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt;
  &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"16"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"16"&lt;/span&gt;
  &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
  &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 16 16"&lt;/span&gt;
  &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Email me&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt;
    &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471z"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You may have noticed that I added a &lt;code&gt;role&lt;/code&gt; of &lt;code&gt;img&lt;/code&gt; to the SVG. This is so that the browser will not attempt to read the contents of the SVG but treat it as an image.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/7b0xpSbNxIk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;What if the SVG is not inlined in the HTML but added as a background image using CSS? You have two options with the same result. The first is to add a class called &lt;code&gt;visually-hidden&lt;/code&gt; to your global CSS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.visually-hidden&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would then use the following HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:peter@example.com"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon icon-email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"visually-hidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email me&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CSS will hide the text visually, but the screen reader will still read it and use it as the accessible text of the link. Another option is to use &lt;code&gt;aria-label&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Email me"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:peter@example.com"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon icon-email"&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ba1333sfWTI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Great, but did I mean by links having meaningful text? Consider the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Learn more about writing meaningful link text. &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://wcag.com/blog/writing-meaningful-link-text/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click here&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look at this visually in the browser, you might not see the problem. However, for someone using a screen reader and either tabbing through the links on the page or using the links menu shown earlier, all they will hear is "Click here". This is what is meant by having meaningful text.&lt;/p&gt;

&lt;p&gt;It is very easy to fix though.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://wcag.com/blog/writing-meaningful-link-text/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Learn more about writing meaningful link text.&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The video below walks through this as well.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/c-vyPmUov6c"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Positive &lt;code&gt;tab-index&lt;/code&gt; and non-interactive elements in the tab order
&lt;/h2&gt;

&lt;p&gt;As mentioned, users who rely on a keyboard to navigate your site, power users, and those using assistive technologies such as screen readers very often use their tab key to move through your sites and applications.&lt;/p&gt;

&lt;p&gt;By default, the only elements that will receive focus are interactive elements such as links, buttons, and form elements. There are ways to force a non-interactive element to be added to the tab order or control the tab order, and there is also a way to make an element focusable without adding it to the tab order. This is commonly done when the focus state is managed via JavaScript. I will not touch on this last one here.&lt;/p&gt;

&lt;p&gt;You can control the natural tab order by using positive numbers with the &lt;code&gt;tab-index&lt;/code&gt; attribute. There is never a good reason for this. I very rarely use blanket statements like this, but I believe this is one of the instances where it is warranted. This practice is extremely brittle and can quickly break the user experience and user expectations. Instead, use semantic HTML and ensure that the HTML source order matches your desired tab order.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember you can also change the layout using CSS, but do not try to control the tab order, let the browser do the work for you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another way you can use &lt;code&gt;tab-index&lt;/code&gt; is with a value of 0 (zero). This allows you to add a non-interactive element into the "natural" tab order. I wrapped natural in quotes in the previous sentence because while the item will be added in the natural tab order, there is nothing natural about a non-interactive element being made focusable.&lt;/p&gt;

&lt;p&gt;This is another one where I would advise relying on sensible HTML source order and allowing the browser to take over from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Missing &lt;code&gt;alt&lt;/code&gt; text
&lt;/h2&gt;

&lt;p&gt;It is hard to believe that at the end of 2023 and therefore in 2024 this is still one of the top errors showing up in accessibility audits.&lt;/p&gt;

&lt;p&gt;The guidelines are clear, and adding the appropriate content for an &lt;code&gt;alt&lt;/code&gt; attribute is quick and easy. This leads me to believe that most of these are introduced not through user error but because of the lack of support from various tooling.&lt;/p&gt;

&lt;p&gt;I hate to call out a company, but I stopped using Buffer because their tools do not allow me to specify alternative text when adding an image to a scheduled social media post. Now, does the blame lie on the side of Buffer or on the side of the social media platforms that do not provide an API to specify alternative text? I do not know, but I would love to know. If you know, let me know in the comments.&lt;/p&gt;

&lt;p&gt;Whenever you can, please take a moment to provide alternative text for any media that conveys meaning and is not purely decorative. While there is no limit on the number of characters you can use in an &lt;code&gt;alt&lt;/code&gt; attribute, try to be descriptive but concise. Tools such as the various chatbots can also help you here if, for example, your first language is not English and you want to provide alternative text in English.&lt;/p&gt;

&lt;p&gt;As an example let's say the hero image for this post was the only place where the title was conveyed to the reader. In that case, I would markup the image as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"An image depicting people of various ages and abilities. Overlayed is the text, '10 Top accessibility errors and how to avoid and fix them'"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/media/hero.webp"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"1200"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seeing that the image is purely decorative and the title is available to screen readers as text, I would use an empty value for the &lt;code&gt;alt&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/media/hero.webp"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"1200"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lists not nested correctly
&lt;/h2&gt;

&lt;p&gt;The primary concern is that a developer does not use the most appropriate list type for the content. Let's say you are writing the instructions to make a pizza. Before making the pizza you would need to go to the store and buy the ingredients. Once you have the ingredients you need to follow the needed steps to ensure a successful and delicious pizza. However, the order you buy the ingredients is not important only that you buy them all.&lt;/p&gt;

&lt;p&gt;Now you could, and probably would, mark this up as two separate lists, but for the sake of the example let's use a primary list and one nested list.&lt;/p&gt;

&lt;p&gt;You could use an unordered list and nest another unordered list, but then you would have made the mistake that this error is all about. Instead, our primary list is an ordered list and our ingredient list is a nested unordered list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ol&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Head to the store and buy the following ingredients:
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Bread flour&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Dry yeast&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Extra virgin Greek olive oil&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Tomato sauce&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Cheese&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Fresh basil&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Proof the yeast&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Knead the dough&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Let the dough rise&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Preheat the pizza stone&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Prepare the toppings&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Flatten and stretch the dough&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Brush the dough with olive oil&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Spread with tomato sauce and sprinkle with toppings&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Slide pizza into the oven&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Bake&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Stuff thy face 🍕&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Duplicate labels used
&lt;/h2&gt;

&lt;p&gt;The labels here refer to the labels used with form elements. While it is critical to ensure your labels are unique and descriptive, I have found that it is still very often the case that people either do not specify labels (relying on the &lt;code&gt;placeholder&lt;/code&gt;) or specify a label, but do not associate the label with the &lt;code&gt;input&lt;/code&gt; element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Username&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Email address&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rPzNB9yr_sk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Please, please&lt;/strong&gt; ensure that you &lt;em&gt;always&lt;/em&gt; provide unique, clear label text, associated with the relevant input. What do I mean by associating a label with an input? This is achieved by a combination of the &lt;code&gt;for&lt;/code&gt; attribute on the &lt;code&gt;label&lt;/code&gt; element and an associated &lt;code&gt;id&lt;/code&gt; attribute on the form element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Username&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email address&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4BglwbSP-9Q"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Invalid &lt;code&gt;aria-labelledby&lt;/code&gt; and &lt;code&gt;aria-describedby&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;These errors are caused by the same underlying problem and are solved by the same solution so I will describe them together. Both of these attributes work in much the same way as we just discussed with associating a &lt;code&gt;label&lt;/code&gt; element and form element.&lt;/p&gt;

&lt;p&gt;Instead of the &lt;code&gt;for&lt;/code&gt; attribute, however, you use either &lt;code&gt;aria-labelledby&lt;/code&gt; or &lt;code&gt;aria-describedby&lt;/code&gt;. The value of these attributes must match the value of an &lt;code&gt;id&lt;/code&gt; attribute on another element. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"my-portfolio-section-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"my-portfolio-section-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My portfolio&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; A &lt;code&gt;section&lt;/code&gt; element without an accessible name has an implicit &lt;code&gt;generic&lt;/code&gt; role and therefore has no real semantic meaning. The example above does have an accessible name thanks to the &lt;code&gt;aria-labelledby&lt;/code&gt; attribute. In this case, the section has a role of &lt;code&gt;region&lt;/code&gt; and as such will show up in the landmark roles section of screen reader tools such as VoiceOver on macOS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An instance where using the technique above is incredibly useful is with the &lt;code&gt;nav&lt;/code&gt; element. On a documentation site, for example, you might have a header with your primary navigation, a sidebar with navigation for your documentation, a table of contents for the current page, and a secondary navigation in the footer. If all of these are marked up using the &lt;code&gt;nav&lt;/code&gt; element, you will have four landmarks, but they will all be identified as navigation without any distinguishing label. You can fix this with either an &lt;code&gt;aria-label&lt;/code&gt; or &lt;code&gt;aria-labelledby&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/1Lo5psclMkc"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;aside&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"sidebar-title-get-started"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"sidebar-title-get-started"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Get started&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    ...
  &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"sidebar-title-learn-astro"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"sidebar-title-learn-astro"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Learn Astro&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    ...
  &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4DULO2DLnf0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope you found all of this helpful and that it will help you avoid these very common errors and allow you to fix them when you do come across them. Now go and make the web awesome and accessible for all.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>a11y</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Here are the 10 projects I am contributing to over the next 6 months. Share yours</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Sat, 13 Apr 2024 16:20:28 +0000</pubDate>
      <link>https://forem.com/schalkneethling/here-are-the-10-projects-i-am-contributing-to-over-the-next-6-months-share-yours-4h0l</link>
      <guid>https://forem.com/schalkneethling/here-are-the-10-projects-i-am-contributing-to-over-the-next-6-months-share-yours-4h0l</guid>
      <description>&lt;p&gt;My contributions to open source projects have gone down in the last nine months or so and I do not like it. Thankfully, it is one of those things in my control, so I am changing that.&lt;/p&gt;

&lt;p&gt;Here are the 10 projects I picked to contribute to over the next 6 months. Which projects are you contributing to?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Update: One thing we are all allowed to do is change our minds or realize we have overcommitted ourselves. As such I am reducing the number of projects I intend to contribute to.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mdn/content" rel="noopener noreferrer"&gt;MDN Web Docs content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/withastro/docs" rel="noopener noreferrer"&gt;Astro Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/withastro/starlight" rel="noopener noreferrer"&gt;Startlight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/w3c/aria-practices" rel="noopener noreferrer"&gt;W3C Aria Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whatwg/html" rel="noopener noreferrer"&gt;WHAT-WG HTML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Someday/Maybe
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nodejs/node" rel="noopener noreferrer"&gt;Nodejs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/canonical/vanilla-framework/" rel="noopener noreferrer"&gt;Canonical's Vanilla Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/canonical/react-components" rel="noopener noreferrer"&gt;Canonical's React Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vuejs/vue" rel="noopener noreferrer"&gt;Vuejs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mdn/browser-compat-data" rel="noopener noreferrer"&gt;Browser Compat Data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also have five of my own projects which you are welcome to contribute to!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/schalkneethling/developer-toolchest" rel="noopener noreferrer"&gt;Developer Toolchest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/schalkneethling/html-comprehensive-guide" rel="noopener noreferrer"&gt;HTML Comprehensive Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/schalkneethling/qilin-open-source-project-starter-template" rel="noopener noreferrer"&gt;Qilin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/schalkneethling/minimalist" rel="noopener noreferrer"&gt;Minimalist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mechanical-ink/indiecaster-core" rel="noopener noreferrer"&gt;IndieCaster&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>HTML: A Comprehensive Guide - Chapter One</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Wed, 10 Apr 2024 00:27:53 +0000</pubDate>
      <link>https://forem.com/schalkneethling/html-a-comprehensive-guide-chapter-one-pfg</link>
      <guid>https://forem.com/schalkneethling/html-a-comprehensive-guide-chapter-one-pfg</guid>
      <description>&lt;p&gt;Today I am super proud to announce that I have finally picked up the task of finishing my book titled, "HTML: A Comprehensive Guide". It feels wonderful to write that and put it out in the public domain (there is a hidden pun here). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You all now have the job of keeping me accountable.&lt;/strong&gt; 😃&lt;/p&gt;

&lt;p&gt;Here is the resolution of the pun. I am writing the book in public and releasing it under the MIT license (not quite public domain but close). This means that the book is open source. Yup, you read that correctly. With that said...&lt;/p&gt;

&lt;p&gt;Writing a book takes a lot of time and dedication. I believe I have the dedication and the curiosity, but time is hard to come by these days as I am sure you are all aware. However, if you find the work I am doing on the book helpful and would like to support the work, here are a few things you can do.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Share it widely.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/schalkneethling/html-comprehensive-guide" rel="noopener noreferrer"&gt;Read it, use it, and provide feedback&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Contribute by &lt;a href="https://github.com/schalkneethling/html-comprehensive-guide/issues" rel="noopener noreferrer"&gt;raising an issue&lt;/a&gt; or even addressing an existing issue.&lt;/li&gt;
&lt;li&gt;Support me financially by&lt;a href="https://www.patreon.com/SchalkNeethling" rel="noopener noreferrer"&gt; signing up for any of the tiers on Patreon&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In so doing I hope to be able to dedicate more and more time not only to writing the book, but to &lt;a href="https://www.youtube.com/channel/UCaIC2hpfo9av8-R7g9qE2sw" rel="noopener noreferrer"&gt;teaching others who want to learn web development&lt;/a&gt;, continuing to &lt;a href="https://schalkneethling.substack.com/" rel="noopener noreferrer"&gt;produce the podcasts&lt;/a&gt;, and managing the Mycelium Network community (&lt;a href="https://join.slack.com/t/mechanical-ink-group/shared_invite/zt-22yg9uryr-YiNd2tO1E5qrckQldruWsw" rel="noopener noreferrer"&gt;Join on Slack&lt;/a&gt; or &lt;a href="https://discord.gg/zEwvvZVhGF" rel="noopener noreferrer"&gt;Join on Discord&lt;/a&gt;). Creating in the open and teaching others to build standards-compliant and accessible websites is a passion of mine that fuels everything I do. I thank you for your interest and support and look forward to teaching and learning from all of you.&lt;/p&gt;

&lt;p&gt;With that, here is the first chapter to give you a sense of what the book will be like. If you want more, follow the link below (I just published chapter two!).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://schalkneethling.github.io/html-comprehensive-guide/" rel="noopener noreferrer"&gt;Read, HTML: A Comprehensive Guide today!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Chapter 1: Getting Started with HTML
&lt;/h2&gt;

&lt;p&gt;If one has always thought of HTML as just some form elements, div and span elements, links, and paragraph tags, it seems strange that one would dedicate an entire book to the language. As you will see throughout this book, there is a &lt;strong&gt;lot&lt;/strong&gt; more to the HTML language.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HTML?
&lt;/h2&gt;

&lt;p&gt;HTML stands for &lt;strong&gt;H&lt;/strong&gt;yper &lt;strong&gt;T&lt;/strong&gt;ext &lt;strong&gt;M&lt;/strong&gt;arkup &lt;strong&gt;L&lt;/strong&gt;anguage and has been at the core of &lt;a href="https://en.wikipedia.org/wiki/World_Wide_Web" rel="noopener noreferrer"&gt;the web&lt;/a&gt; since its very inception in 1989. It forms the basis of all things on the web no matter how simple or how complex. Without HTML, there are no web pages or applications. HTML also provides the &lt;a href="https://webaim.org/techniques/semanticstructure/" rel="noopener noreferrer"&gt;semantic structure of our documents and applications&lt;/a&gt; and this is where knowing the language really pays off. Semantic structure is also critical when it comes to the accessibility of your documents, a topic I will cover throughout the book.&lt;/p&gt;

&lt;p&gt;There is a lot to HTML and some aspects of the language such as &lt;code&gt;canvas&lt;/code&gt; can take up an entire book on their own. For some topics such as this, I will provide an overview and then provide resources for further reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;html&lt;/code&gt; element
&lt;/h2&gt;

&lt;p&gt;We will start with the first element in every HTML document, the &lt;code&gt;html&lt;/code&gt; element.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What about the &lt;code&gt;DOCTYPE&lt;/code&gt;? That is a good question. While the &lt;code&gt;DOCTYPE&lt;/code&gt; is the very first entry in our HTML documents, it is in fact not an HTML element. The sole purpose of the &lt;code&gt;DOCTYPE&lt;/code&gt; is to ensure that the browser does not switch into what is commonly known as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Quirks_Mode_and_Standards_Mode" rel="noopener noreferrer"&gt;quirks mode&lt;/a&gt;, but instead, makes a best effort attempt at following the relevant specification. I say, "best effort attempt", as not all browsers have implemented the entirety of the HTML specification. This is especially true of older browsers and so, these browsers will do their best to interpret the language and use a fallback where it does not understand the specific syntax.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;DOCTYPE&lt;/code&gt; is required for all HTML documents and takes the following form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;There is an &lt;a href="https://html.spec.whatwg.org/multipage/syntax.html#the-doctype" rel="noopener noreferrer"&gt;extended legacy form&lt;/a&gt;, but the above is all that you will ever need to be concerned with.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that the browser knows that what follows will be HTML, we start our document with our root element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;lang&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Being at the root of our document, there is one attribute that should always be set on the &lt;code&gt;html&lt;/code&gt; element. The &lt;code&gt;lang&lt;/code&gt; attribute on the &lt;code&gt;html&lt;/code&gt; element indicates the primary natural language the document is written in. It also assists speech synthesis tools in what pronunciations to use and helps translation tools select the rules they should apply. This is critical for the overall accessibility of your documents. It takes the following form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should you not want your entire document to be localizable through translation tools, you can specify the &lt;a href="https://html.spec.whatwg.org/#attr-translate" rel="noopener noreferrer"&gt;&lt;code&gt;translate&lt;/code&gt; property&lt;/a&gt;, setting its value to &lt;code&gt;no&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt; &lt;span class="na"&gt;translate=&lt;/span&gt;&lt;span class="s"&gt;"no"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The &lt;code&gt;head&lt;/code&gt; element
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;head&lt;/code&gt; of our HTML document contains metadata about the document. So what is metadata? In short, it is &lt;a href="https://en.wikipedia.org/wiki/Metadata" rel="noopener noreferrer"&gt;“data about data”&lt;/a&gt;. Not all metadata lives in the &lt;code&gt;head&lt;/code&gt; though, and not all metadata that lives in the &lt;code&gt;head&lt;/code&gt; is necessarily descriptive, more on this later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    ...
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The &lt;code&gt;title&lt;/code&gt; element
&lt;/h2&gt;

&lt;p&gt;The first piece of metadata we will add to our web pages is the &lt;code&gt;title&lt;/code&gt; tag. Seems like such a simple element, and it is, but while simple, it is critical to orient a user. The &lt;code&gt;title&lt;/code&gt; uniquely identifies the current page in the browser's history, is the first piece of information read to users using screen readers; is the title shown to users in search results, when sharing on social media, and is crucial &lt;a href="https://moz.com/learn/seo/title-tag" rel="noopener noreferrer"&gt;for SEO&lt;/a&gt;(search engine optimization).&lt;/p&gt;

&lt;p&gt;With that said, keep the following guidelines in mind when writing your title:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be concise when writing your titles and aim to keep the total character count at around 60.&lt;/li&gt;
&lt;li&gt;Remember that document titles should make sense when read out of context.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;See the web content accessibility guidelines (WCAG) for more information on &lt;a href="https://www.w3.org/WAI/WCAG22/Techniques/general/G88.html" rel="noopener noreferrer"&gt;providing descriptive titles for web pages&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, the title for this chapter would read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;
      Chapter 1: Getting Started with HTML - HTML Comprehensive Guide
    &lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;title&lt;/code&gt; tag does not have any special attributes but supports all the global attributes, one of which is &lt;code&gt;translate&lt;/code&gt;. Using this attribute, you can prevent translation tools from localizing your page title.&lt;/p&gt;

&lt;p&gt;Why would you want to do that? Your page title could be the title of a poem or a song. In those cases, you do not want the title translated. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;title&lt;/span&gt; &lt;span class="na"&gt;translate=&lt;/span&gt;&lt;span class="s"&gt;"no"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Revoir Paris | Roland Dyens&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, it would also be prudent to add a &lt;code&gt;lang&lt;/code&gt; attribute indicating the primary language used in the &lt;code&gt;title&lt;/code&gt; tag. As mentioned earlier, this will assist speech synthesis tools in what pronunciations to use. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;title&lt;/span&gt; &lt;span class="na"&gt;translate=&lt;/span&gt;&lt;span class="s"&gt;"no"&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"fr"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Revoir Paris | Roland Dyens&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The &lt;code&gt;base&lt;/code&gt; element
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;base&lt;/code&gt; element is written as a self-closing, or void, tag. This means that, while a lot of tags in HTML are written as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My page title&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A self-closing tag is written like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://html-comprehensive-guide.dev/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;base&lt;/code&gt; element allows you to set a base URL for all links on the current page, set a base browsing context, or both, for all links on the page. Let’s look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/book/show/11588.The_Shining"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Shining&lt;span class="nt"&gt;&amp;lt;/a&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/book/show/149267.The_Stand"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Stand&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/book/show/10614.Misery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Misery&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/book/show/10592.Carrie"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Carrie&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of those links share the same &lt;strong&gt;base&lt;/strong&gt; URL. Using the &lt;code&gt;base&lt;/code&gt; element, you can avoid repeating the base URL in every link tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;I got your base&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/11588.The_Shining"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Shining&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/149267.The_Stand"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Stand&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/10614.Misery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Misery&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/10592.Carrie"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Carrie&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: If the HTML above was on a page that was hosted as part of the Goodreads website, you would not include the URL as part of the link and instead, opt for using relative URLs. In other words, instead of &lt;code&gt;https://www.goodreads.com/book/show/11588.The_Shining&lt;/code&gt; you will do just &lt;code&gt;book/show/11588.The_Shining&lt;/code&gt;. The &lt;code&gt;base&lt;/code&gt; element would therefore not be useful in this case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, you may also want those links to always open in a new tab (browsing context). One option is to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/11588.The_Shining"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Shining&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/149267.The_Stand"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Stand&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/10614.Misery"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Misery&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/10592.Carrie"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Carrie&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned, there is a second attribute you can set on the &lt;code&gt;base&lt;/code&gt; element, and that attribute is the &lt;code&gt;target&lt;/code&gt; attribute. We can therefore avoid repeating &lt;code&gt;target&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Be careful here as this could negatively impact the user experience and accessibility as there is nothing indicating to the user that all links will open in a new window or tab. While not a blanket statement, I almost always prefer to leave the choice of whether a link should open in the same or a different tab or window up to the user.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;I got your base&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/11588.The_Shining"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Shining&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/149267.The_Stand"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The Stand&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/10614.Misery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Misery&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"book/show/10592.Carrie"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Carrie&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above in place, &lt;strong&gt;all&lt;/strong&gt; links on the current page will use &lt;code&gt;https://www.googreads.com&lt;/code&gt; as its base URL and all links will open in a new tab. The thing is, it does mean that &lt;strong&gt;all&lt;/strong&gt; "links" will have this behavior. Not only are anchor tags affected but &lt;em&gt;all&lt;/em&gt; elements with a &lt;code&gt;href&lt;/code&gt; attribute are affected. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"css/pink.css"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"screen"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above scenario, the browser will attempt to load the stylesheet from the Goodreads website, which is probably not what you intended. Thankfully, the &lt;code&gt;base&lt;/code&gt; element only affects elements below it in source order, so changing the above as follows will solve the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"css/pink.css"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"screen"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.goodreads.com/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember that &lt;code&gt;_blank&lt;/code&gt; is not the only possible value for the &lt;code&gt;target&lt;/code&gt; attribute. One other value is &lt;code&gt;_top&lt;/code&gt;. Using &lt;code&gt;_top&lt;/code&gt; as the value of &lt;code&gt;target&lt;/code&gt; might be useful as a means of &lt;a href="https://en.wikipedia.org/wiki/Framekiller" rel="noopener noreferrer"&gt;frame busting&lt;/a&gt; aka, prevent your site from being displayed in an &lt;code&gt;iframe&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_top"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this will not prevent the site from initially being loaded in an &lt;code&gt;iframe&lt;/code&gt;, it &lt;em&gt;will&lt;/em&gt; cause clicks on any links in the page to bust out of the &lt;code&gt;iframe&lt;/code&gt; by setting its browsing context to the topmost browsing context i.e. the browser window itself.&lt;/p&gt;

&lt;p&gt;I will close this chapter with an example use case that might be a bit of a stretch. I am using a combination of the &lt;code&gt;base&lt;/code&gt; element, a specific CSS &lt;code&gt;class&lt;/code&gt; on certain elements, and some JavaScript. The result is something that could be useful in a web application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;The HTML base element&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"css/pink.css"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"screen"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"native"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"add-book"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Add Book&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"native"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"view"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;View Bookshelf&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://amzn.to/3Olm2de"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Misery&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://amzn.to/3OlsCQM"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Carrie&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above, clicking on any link that has a &lt;code&gt;class&lt;/code&gt; attribute with the value &lt;code&gt;native&lt;/code&gt; will be intercepted by JavaScript and opened in the same tab/window. All other links will open in a new tab. One interesting aspect to note about the above is that, even when intercepted by JavaScript, the value of &lt;code&gt;event.target.href&lt;/code&gt; will use the base &lt;code&gt;href&lt;/code&gt; value defined on the &lt;code&gt;base&lt;/code&gt; element, for example, &lt;code&gt;https://www.goodreads.com/add-book&lt;/code&gt;. So be careful 😄&lt;/p&gt;

&lt;p&gt;Some final notes on the &lt;code&gt;base&lt;/code&gt; element. There must be no more than one &lt;code&gt;base&lt;/code&gt; element per page. If there are multiple, all but the first will be ignored. As with &lt;code&gt;href&lt;/code&gt;, all elements that have a &lt;code&gt;target&lt;/code&gt; attribute set are affected by the value of the &lt;code&gt;target&lt;/code&gt; attribute of the &lt;code&gt;base&lt;/code&gt; element. This means that forms with a &lt;code&gt;target&lt;/code&gt; will also be affected.&lt;/p&gt;

&lt;p&gt;In case you are interested, here is the URL parsing algorithm (from the W3C documentation):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;base&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.example.com/news/index.html"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"archives.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;archives&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- The above URL will be https://www.example.com/news/archives.html --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/blog/archives.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;archives&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- The above URL will be https://www.example.com/blog/archives.html --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./blog/archives.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;archives&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- The above URL will be https://www.example.com/news/blog/archives.html --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.otherwebsite.com/blog/archives.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;archives&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- The above URL will be https://www.otherwebsite.com/blog/archives.html --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Related Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html" rel="noopener noreferrer"&gt;The &lt;code&gt;html&lt;/code&gt; element on MDN Web Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/WCAG22/Understanding/page-titled.html" rel="noopener noreferrer"&gt;Understanding Success Criterion 2.4.2: Page Titled&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title" rel="noopener noreferrer"&gt;title element on MDN Web Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base" rel="noopener noreferrer"&gt;base element on MDN Web Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>html</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>12 Free Courses To Help You Develop More Secure Software - Shift Security Left</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Mon, 08 Apr 2024 20:24:16 +0000</pubDate>
      <link>https://forem.com/schalkneethling/12-free-courses-to-help-you-develop-more-secure-software-shift-security-left-j2i</link>
      <guid>https://forem.com/schalkneethling/12-free-courses-to-help-you-develop-more-secure-software-shift-security-left-j2i</guid>
      <description>&lt;p&gt;With the recent backdoor exploit of the &lt;code&gt;xz&lt;/code&gt; package, security is on several people's minds. It has always been critical to be aware of security topics such as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;Cross-Origin Resource Sharing&lt;/a&gt; (CORS), &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" rel="noopener noreferrer"&gt;Content Security Policies&lt;/a&gt; (CSP), avoiding &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting" rel="noopener noreferrer"&gt;cross-site scripting attacks&lt;/a&gt; (XSS), and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity" rel="noopener noreferrer"&gt;subresource integrity&lt;/a&gt; among other security topics. Still, many of us either do not have the time or the money to learn these and other related security topics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://socket.dev/blog/how-to-use-socket-to-find-out-if-you-were-affected-by-the-backdoored-xz-package" rel="noopener noreferrer"&gt;How to determine whether you are affected by the &lt;code&gt;xz&lt;/code&gt; backdoor using Socket.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sovereigntechfund.de/news/xz-structural-change" rel="noopener noreferrer"&gt;The deeper need the &lt;code&gt;xz&lt;/code&gt; exploit demonstrates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ossf/wg-vulnerability-disclosures/issues/142" rel="noopener noreferrer"&gt;Resources to help protect developers (humans) from attacks similar to the xz backdoor compromise&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.to/schalkneethling/why-do-i-love-open-source-4nj2"&gt;With my involvement in the open-source world&lt;/a&gt; and wanting to ensure that the projects I maintain and contribute to are secure, I decided to take a look at what the &lt;a href="https://training.linuxfoundation.org/full-catalog/" rel="noopener noreferrer"&gt;Linux Foundation has to offer in terms of course material&lt;/a&gt;. Having previously studied for and taken the &lt;a href="https://training.linuxfoundation.org/certification/jsnad/" rel="noopener noreferrer"&gt;Node.js Developer exam&lt;/a&gt;, I found their content to be good and up-to-date.&lt;/p&gt;

&lt;p&gt;I was pleasantly surprised to find that they have quite a few courses aimed at what they have classified as beginner (we are all beginners at some time) friendly courses. Not only that, but all of these courses are free! I am planning to work my way through them so, I thought I would share the list of courses here for ease of access for myself, and all of you who might be interested in sharpening your security knowledge.&lt;/p&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/QSYQTAOu56Q"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/secure-software-development-requirements-design-and-reuse-lfd104/" rel="noopener noreferrer"&gt;Secure Software Development: Requirements, Design, and Reuse&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This course discusses the basics of security, such as what risk management really means. It discusses how to consider security as part of the requirements of a system, and what potential security requirements you might consider. This part then focuses on how to design software to be secure, including various secure design principles that will help you avoid bad designs and embrace good ones. It also considers how to secure your software supply chain, that is, how to more securely select and acquire reused software (including open source software) to enhance security.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/secure-software-development-implementation-lfd105/" rel="noopener noreferrer"&gt;The Secure Software Development: Implementation&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This course focuses on key implementation issues: input validation (such as why allowlists should be used and not denylists), processing data securely, calling out to other programs, sending output, and error handling. It focuses on practical steps that you (as a developer) can take to counter the most common kinds of attacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/secure-software-development-verification-and-more-specialized-topics-lfd106/" rel="noopener noreferrer"&gt;Secure Software Development: Verification and More Specialized Topics&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This course discusses how to verify software for security. In particular, it discusses the various static and dynamic analysis approaches, as well as how to apply them (e.g., in a continuous integration pipeline). It also discusses more specialized topics, such as the basics of how to develop a threat model and how to apply various cryptographic capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/developing-secure-software-lfd121/" rel="noopener noreferrer"&gt;Developing Secure Software&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Modern software is under constant attack, but many software developers have never been told how to effectively counter those attacks. This course works to solve that problem, by explaining the fundamentals of developing secure software. This course covers the following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This first part of the course focuses on how to design software to be secure, including various secure design principles.&lt;/li&gt;
&lt;li&gt;How to secure your software supply chain, that is, how to more securely select and acquire reused software including open source software.&lt;/li&gt;
&lt;li&gt;The second part of this course focuses on key implementation issues such as input validation, processing data securely, calling out to other programs, sending output, and error handling.&lt;/li&gt;
&lt;li&gt;The third part of the course discusses how to verify software for security using static and dynamic analysis approaches.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/securing-your-software-supply-chain-with-sigstore-lfs182x/" rel="noopener noreferrer"&gt;Securing Your Software Supply Chain with Sigstore&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This course will introduce you to Cosign, Fulcio, Rekor, and the Policy Controller, the tools under the Sigstore umbrella, explaining how they support a more secure software supply chain. You will learn how to employ these tools throughout your software development, testing, and distribution processes. Additionally, those who use or implement your software will be able to verify its authenticity through tamper-resistant public logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/owasp-top-ten-security-threats-skf100/" rel="noopener noreferrer"&gt;Understanding the OWASP® Top 10 Security Threats&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;By the end of this course, participants will acquire a comprehensive understanding of the OWASP Top 10 Security Threats, empowering them to identify and mitigate vulnerabilities, understand exploitation techniques, and apply risk management for web app security.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/github-supply-chain-security-using-gitgat-lfd122x/" rel="noopener noreferrer"&gt;GitHub Supply Chain Security Using GitGat&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This course starts by providing an understanding of the risks regarding a GitHub account, Github’s account types and their security ramifications, Github’s access controls, Github branch-protection rules, and OPA concepts. This course will equip you with the knowledge to correctly assess your own your organization’s GitHub account security posture using the &lt;a href="https://github.com/scribe-public/gitgat" rel="noopener noreferrer"&gt;GitGat open-source tool&lt;/a&gt;, correctly set up basic GitHub security posture, whether you’re an individual or run a GitHub organization, and set up the state for the GitGat project and know how to set up a continuous security audit of your repositories.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/cybersecurity-essentials-lfc108/" rel="noopener noreferrer"&gt;Cybersecurity Essentials&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The course discusses security precautions and risks when using technology for personal and professional purposes. It covers strategies to protect information during everyday activities and transactions, prevent exposure to account and data compromises, and identify what to do if a data breach occurs. The course includes real-world scenarios highlighting personal and professional situations and the implications of unsafe practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/express-learning/security-self-assessments-for-open-source-projects-lfel1005/" rel="noopener noreferrer"&gt;Security Self-Assessments for Open Source Projects&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You should be able to articulate the value and initiate the process of a security self-assessment for your project to expedite future joint assessments or security audits.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/express-learning/securing-projects-with-openssf-scorecard-lfel1006/" rel="noopener noreferrer"&gt;Securing Projects with OpenSSF Scorecard&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You will learn about the different checks provided by &lt;a href="https://openssf.org/" rel="noopener noreferrer"&gt;OpenSSF&lt;/a&gt; Scorecard, how to configure the checks for your environment, and how to automate their implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/express-learning/automating-supply-chain-security-sboms-and-signatures-lfel1007/" rel="noopener noreferrer"&gt;Automating Supply Chain Security: SBOMs and Signatures&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Learn about software provenance, the role of source control, dependency tracking, and the creation of SBOMs. Get familiar with SBOM and signatory tools, and apply to cosign and SLSA workflows with GitHub Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://training.linuxfoundation.org/training/introduction-to-zero-trust-lfs183x/" rel="noopener noreferrer"&gt;Introduction to Zero Trust&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This course discusses the features and characteristics of a Zero Trust Architecture, the different models of trust and use cases, and provides opportunities for hands-on practice with open source tools such as SPIFFE/SPIRE, Open Policy Agent, and Istio service mesh.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That is quite a lot of courses and it is going to take time to work through them, but I believe it is time that we all shift security left and take some of the responsibility of securing our software on us, the software engineers. I also believe this is the case whether you are a frontend, backend, or full-stack engineer. &lt;a href="https://dev.to/schalkneethling/why-i-care-deeply-about-web-accessibility-and-you-should-too-274a"&gt;Just like with accessibility&lt;/a&gt;, we all need to do our part.&lt;/p&gt;

&lt;p&gt;If you are planning on working through all or some of these courses and want a study buddy or start a study group, let me know in the comments. I would love to join you.&lt;/p&gt;

</description>
      <category>security</category>
      <category>learning</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why are my table rows rendered outside the table? DOM template parsing caveats in Vuejs</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Sun, 07 Apr 2024 20:38:30 +0000</pubDate>
      <link>https://forem.com/schalkneethling/why-are-my-table-rows-rendered-outside-the-table-dom-template-parsing-caveats-in-vuejs-k1o</link>
      <guid>https://forem.com/schalkneethling/why-are-my-table-rows-rendered-outside-the-table-dom-template-parsing-caveats-in-vuejs-k1o</guid>
      <description>&lt;p&gt;The problem described here might not be something you run into often, as it mainly applies to situations where you write your HTML template directly in your HTML document. If you use a &lt;a href="https://vuejs.org/guide/essentials/component-basics.html#dom-template-parsing-caveats" rel="noopener noreferrer"&gt;string template or a single file component&lt;/a&gt;, you will not encounter this problem.&lt;/p&gt;

&lt;p&gt;When learning or wanting to prototype an idea when using Vuejs quickly, you may choose to place all of your code in a single &lt;code&gt;.html&lt;/code&gt; document. Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;WaterBear&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;caption&amp;gt;&lt;/span&gt;
      Contributors
    &lt;span class="nt"&gt;&amp;lt;/caption&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Username&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/vue@3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/axios/dist/axios.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;usernames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;schalkneethling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;github-user-row&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#github-user-row-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userAPI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.github.com/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userAPI&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Filling in the template
&lt;/h2&gt;

&lt;p&gt;You will notice that the &lt;code&gt;tbody&lt;/code&gt; is currently empty. For our rows, we might want to use an &lt;code&gt;x-template&lt;/code&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"github-user-row-template"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/x-template"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user.avatar_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user.html_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/tr&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would then use the template inside the &lt;code&gt;table&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;github&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;
  &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username in usernames&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/github-user-row&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will loop over the &lt;code&gt;usernames&lt;/code&gt; array and output a row for each.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;If you open this page in a browser, you will find that the rows are rendered outside the &lt;code&gt;table&lt;/code&gt; element. Why is this? You have just experienced a DOM parsing caveat when using Vue this way.&lt;/p&gt;

&lt;p&gt;What is happening is that the browser sees the following when it parses the document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;caption&amp;gt;&lt;/span&gt;
    Contributors
  &lt;span class="nt"&gt;&amp;lt;/caption&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Username&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;github-user-row&lt;/span&gt;
      &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"username in usernames"&lt;/span&gt;
      &lt;span class="na"&gt;:username=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&amp;lt;/github-user-row&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later in &lt;a href="https://vuejs.org/api/options-lifecycle.html#options-lifecycle" rel="noopener noreferrer"&gt;Vuejs’s lifecycle&lt;/a&gt;, it will replace the component with our HTML but right now, the browser does not recognize the component, marks it as invalid, and hoists it outside of the table, producing the following HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;github-user-row&lt;/span&gt;
  &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"username in usernames"&lt;/span&gt;
  &lt;span class="na"&gt;:username=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/github-user-row&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;caption&amp;gt;&lt;/span&gt;
    Contributors
  &lt;span class="nt"&gt;&amp;lt;/caption&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Username&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When Vue reaches the stage in its lifecycle where it will replace the component with the HTML, you end up with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"user.avatar_url"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;:href=&lt;/span&gt;&lt;span class="s"&gt;"user.html_url"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ user.name }}&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;caption&amp;gt;&lt;/span&gt;
    Contributors
  &lt;span class="nt"&gt;&amp;lt;/caption&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Username&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;The way to address this problem is to use the special &lt;a href="https://vuejs.org/api/built-in-special-attributes.html#is" rel="noopener noreferrer"&gt;&lt;code&gt;is&lt;/code&gt; attribute&lt;/a&gt; inside the &lt;code&gt;table&lt;/code&gt; element as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt;
    &lt;span class="na"&gt;is=&lt;/span&gt;&lt;span class="s"&gt;"vue:github-user-row"&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"username in usernames"&lt;/span&gt;
    &lt;span class="na"&gt;:username=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;vue:&lt;/code&gt; used in front of the template name. If you open the page in a browser, your table will render as expected. I hope you found this helpful and that it saved you some time in debugging.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a Managed Service Provider Business With Open Source</title>
      <dc:creator>Schalk Neethling</dc:creator>
      <pubDate>Thu, 04 Apr 2024 16:15:41 +0000</pubDate>
      <link>https://forem.com/schalkneethling/building-a-managed-service-provider-business-with-open-source-1olk</link>
      <guid>https://forem.com/schalkneethling/building-a-managed-service-provider-business-with-open-source-1olk</guid>
      <description>&lt;p&gt;Let's start by answering the question you may have off the bat. What is a Managed Service Provider? Instead of trying to explain it, I will &lt;a href="https://www.techtarget.com/searchitchannel/definition/managed-service-provider" rel="noopener noreferrer"&gt;quote from TechTarget&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A managed service provider (MSP) is a third-party company that remotely manages a customer's information technology (IT) infrastructure and end-user systems. Small and medium-sized businesses (SMBs), nonprofits, and government agencies hire MSPs to perform a defined set of day-to-day management services. These services may include network and infrastructure management, security, and monitoring.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Open Source?
&lt;/h2&gt;

&lt;p&gt;This one I am qualified to answer. There are a couple of reasons why you would want to choose open-source when starting your MSP. These include, but are not limited to the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speed up time to market.&lt;/li&gt;
&lt;li&gt;No need to reinvent the wheel.&lt;/li&gt;
&lt;li&gt;Learn from others who have come before you.&lt;/li&gt;
&lt;li&gt;Cost savings.&lt;/li&gt;
&lt;li&gt;Well-tested and proven to work effectively by real users.&lt;/li&gt;
&lt;li&gt;Transparency, privacy, and security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How did this article come about?
&lt;/h2&gt;

&lt;p&gt;Before I go any further, I must let you know that this article is 100% inspired by and features projects mentioned by &lt;a href="https://www.linkedin.com/in/brianmcgonagill/" rel="noopener noreferrer"&gt;Brian McGonagill&lt;/a&gt; from &lt;a href="https://www.youtube.com/@AwesomeOpenSource" rel="noopener noreferrer"&gt;Awesome Open Source&lt;/a&gt;. Brian was a guest on &lt;a href="https://schalkneethling.substack.com/p/open-source-advocacy-cultivating" rel="noopener noreferrer"&gt;the Mechanical Ink podcast&lt;/a&gt; and I have been following his work and YouTube channel for some time now.&lt;/p&gt;

&lt;p&gt;When I saw him &lt;a href="https://youtu.be/zhK0sARGhYc?si=PQ1ekixe_jyz9ihm" rel="noopener noreferrer"&gt;starting this series&lt;/a&gt;, I was intrigued and immediately started watching. After the first episode of the series, I thought I would write a post introducing folks to the series, list the tools Brian mentioned in this episode, and highlight an option I feel would be a perfect fit for the SSO portion of the video as Brian did not mention a specific solution here.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/zhK0sARGhYc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A VPN (Virtual Private Network)
&lt;/h3&gt;

&lt;p&gt;This is to ensure the security of your and your customer's data and infrastructure. Some suggestions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.wireguard.com/" rel="noopener noreferrer"&gt;WireGaurd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/juanfont/headscale" rel="noopener noreferrer"&gt;Headscale&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailscale.com/" rel="noopener noreferrer"&gt;Tailscale&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remote Monitoring and Management (RMM)
&lt;/h3&gt;

&lt;p&gt;This is going to be key and the core of the tools you will be using as part of your business so, it is important to choose carefully here. Some suggestions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Ylianst/MeshCentral" rel="noopener noreferrer"&gt;MeshCentral&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zabbix.com/" rel="noopener noreferrer"&gt;Zabbix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://checkmk.com/" rel="noopener noreferrer"&gt;CheckMK&lt;/a&gt; - &lt;a href="https://github.com/Checkmk/checkmk" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remote Support (Desktop Support)
&lt;/h3&gt;

&lt;p&gt;Again, another key piece of your business is the ability to not only monitor but be able to log in remotely and provide support to people in real-time on their machines, securely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://rustdesk.com/" rel="noopener noreferrer"&gt;RustDesk&lt;/a&gt; - &lt;a href="https://github.com/rustdesk/rustdesk" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Backups
&lt;/h3&gt;

&lt;p&gt;I do not think I need to say much here. No backups are a sure way to lose clients. As Brian mentions, this will be heavily client-dependent, but some options you may want to consider include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nextcloud.com/" rel="noopener noreferrer"&gt;NextCloud&lt;/a&gt; - &lt;a href="https://github.com/nextcloud" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://restic.net/" rel="noopener noreferrer"&gt;Restic&lt;/a&gt; - &lt;a href="https://github.com/restic/restic" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kopia.io/" rel="noopener noreferrer"&gt;Kopia&lt;/a&gt; - &lt;a href="https://github.com/kopia/kopia" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Invoicing
&lt;/h3&gt;

&lt;p&gt;You need a way to invoice your clients, keep track of invoicing, and collect payments. This aspect of a business is often overlooked by those of us who would prefer to code, design, or manage infrastructure. That said, if you let this slip, your business will quickly become a drain on your energy and your wallet. Some suggestions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://invoiceninja.com/" rel="noopener noreferrer"&gt;InvoiceNinja&lt;/a&gt; - &lt;a href="https://github.com/invoiceninja/invoiceninja" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://crater.financial/" rel="noopener noreferrer"&gt;Crater&lt;/a&gt; - &lt;a href="https://github.com/crater-invoice/crater" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Single Sign-On (SSO)
&lt;/h3&gt;

&lt;p&gt;This brings us to single sign-on or SSO for short which I mentioned at the top of the article. Why would you need SSO? Other than the obvious security benefit of not having to manage multiple accounts across services, SSO improves the user experience for the very same reason.&lt;/p&gt;

&lt;p&gt;In addition, having and supporting single sign-on will be a requirement should you ever want to do business with enterprise companies. As you onboard new employees, easily provisioning and de-provision accounts through a combination of SSO and Directory Sync will make your life and business security much easier and save you money. My suggestion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://boxyhq.com/enterprise-sso" rel="noopener noreferrer"&gt;BoxyHQ SAML Jackson&lt;/a&gt; - &lt;a href="https://github.com/boxyhq/jackson" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Say Thank You:&lt;/strong&gt; Do as I did and as you go through these amazing open-source projects. Visit their home on GitHub and give them a star to show your support and appreciation. It is how others find and support them.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;This is going to get you off to a great start and ready for the rest of Brian's series. Are there any other tools you would recommend? Did Brian or I miss anything? Let me know in the comments.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>tools</category>
    </item>
  </channel>
</rss>
