<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Seth Falco - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Seth Falco - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 17 Jun 2026 20:47:27 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/sethfalco/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Pick a Font – An In-Depth Guide for Developers ]]>
                </title>
                <description>
                    <![CDATA[ Fonts are not always free. If you're fetching a font that isn't already on your user's phone or computer, they'll have to download it. And this will impact performance. In documents and subtitles, emb ]]>
                </description>
                <link>https://www.freecodecamp.org/news/things-to-consider-when-picking-fonts/</link>
                <guid isPermaLink="false">66d460f88812486a37369d5c</guid>
                
                    <category>
                        <![CDATA[ fonts ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Wed, 13 Sep 2023 11:18:31 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/12ee3390-c16b-4467-8437-67706712a2e5.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Fonts are not always free. If you're fetching a font that isn't already on your user's phone or computer, they'll have to download it. And this will impact performance.</p>
<p>In documents and subtitles, embedding fonts can easily increase the file size tenfold. As for the web, here are some popular fonts and a potential network impact:</p>
<table>
<thead>
<tr>
<th>Font</th>
<th>Size</th>
<th>Wi-Fi</th>
<th>Regular 4G/LTE</th>
<th>Regular 3G</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://fonts.bunny.net/family/roboto">Roboto</a></td>
<td>160 KB</td>
<td>0.04 s</td>
<td>0.34 s</td>
<td>1.81 s</td>
</tr>
<tr>
<td><a href="https://fonts.bunny.net/family/montserrat">Montserrat</a></td>
<td>217 KB</td>
<td>0.06 s</td>
<td>0.45 s</td>
<td>2.41 s</td>
</tr>
<tr>
<td><a href="https://fonts.bunny.net/family/inter">Inter</a></td>
<td>253 KB</td>
<td>0.07 s</td>
<td>0.53 s</td>
<td>2.80 s</td>
</tr>
<tr>
<td><a href="https://fonts.bunny.net/family/noto-sans">Noto Sans</a></td>
<td>292 KB</td>
<td>0.08 s</td>
<td>0.60 s</td>
<td>3.21 s</td>
</tr>
<tr>
<td><a href="https://fonts.bunny.net/family/jetbrains-mono">JetBrains Mono</a></td>
<td>125 KB</td>
<td>0.04 s</td>
<td>0.27 s</td>
<td>1.43 s</td>
</tr>
</tbody></table>
<p><em>Size is based on rendering "Hello, Čihař!" in regular, bold, italic, and bold italic – it varies based on what characters you use. The estimated network speeds and latency are taken from</em> <a href="https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/throttling/index.html"><em>Throttling - Firefox Source Docs</em></a><em>.</em></p>
<p>On the modern web, we've normalized fetching fonts from client-side, or embedding fonts in resources that are served to users. While this may be tempting, it actually makes very little sense for most use-cases.</p>
<p>This isn't suggesting to never use external fonts. Just a reminder that fonts aren't free, and that it's a good idea to review if it's worth packaging or fetching external fonts when it's avoidable.</p>
<p>Instead, I'd recommend you consider an expansive font selection, featuring typefaces available across operating systems. There are times we should fetch external fonts, but it shouldn't be the default attitude in everything that we build.</p>
<p>In short, you may just need an arbitrary typeface to show arbitrary text on your website. That's fine. But it's worth sticking to the wide array of typefaces already installed on the client's operating system.</p>
<p>In other words… only fetch an external font when it actually enhances the user experience!</p>
<h2 id="heading-why">Why?</h2>
<p>Given the number of typefaces available on all operating systems, there are likely many suitable options for your use-case.</p>
<p>There's no need to specifically fetch Roboto, Inter, or another font that's similar enough to the preinstalled options.</p>
<p>This is particularly relevant to corporate websites, blogs, forums, and web applications.</p>
<p>The user is there to consume content or get a task done. Unless you're looking to be creative, the average user doesn't know, and doesn't care, what typeface it has so long as it's legible.</p>
<p>Meanwhile, they may care for other things impacted by your font choices…</p>
<h3 id="heading-performance">Performance</h3>
<p>Whether we're talking about embedding fonts in offline documents, or fetching fonts on the web, it increases the overall size and load time of resources.</p>
<p>Typefaces can be upwards of 160 KB per font face. The impact of this can be significant on slower networks or old mobile devices.</p>
<p>Particularly on the web, you'd derive more value building a lightning-fast user experience, than fetching a typeface the user didn't ask for.</p>
<p>Until the typeface has finished fetching, sites can choose to block rendering or swap, neither of which is ideal.</p>
<p>Font swapping is when the font changes shortly after visiting the site, leading to a flicker and an increase in <a href="https://web.dev/articles/cls">Cumulative Layout Shift</a>.</p>
<img src="https://www.freecodecamp.org/news/content/images/2023/09/mdn-font-swap.gif" alt="mdn-font-swap" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>A demo of blocking and font swapping on the MDN website. I refreshed with the cache disabled on a high-spec laptop connected to Wi-Fi with no throttling.</em></p>
<img src="https://www.freecodecamp.org/news/content/images/2023/09/out.gif" alt="out" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>A demo of the MDN website using Nimbus Sans, based on Helvetica, instead of external fonts. I refreshed under the same conditions.</em></p>
<p>Dropping external fonts is pretty simple, but can improve load time, reduce bandwidth usage, and avoid font swapping, which all improve your <a href="https://web.dev/articles/vitals">Core Web Vitals</a> and SEO.</p>
<h3 id="heading-privacy">Privacy</h3>
<p>When fetching fonts from a third-party server such as Google Fonts, client information is leaked to the third party. This includes the <a href="https://developer.mozilla.org/en-US/docs/Glossary/IP_Address">IP Address</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent">User-Agent</a>, and <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referer">Referer</a>, among other headers.</p>
<p>Every website that loads a typeface from Google Fonts has given Google the potential to track the visitor. The domain you visited, the time you accessed it, what browser and operating system you're on, and so on. They can form a timeline of the websites you visit from the fonts alone.</p>
<p>Google states that they don't track or store this information. But given the nature of the internet, they inevitably must receive it.</p>
<p>A German court has actually ruled that websites that load Google Fonts are violating GDPR:</p>
<blockquote>
<p>"A regional court in the German city of Munich has ordered a website operator to pay €100 in damages for transferring a user's personal data — i.e., IP address — to Google via the search giant's Fonts library without the individual's consent." (Source: <a href="https://thehackernews.com/2022/01/german-court-rules-websites-embedding.html">German Court Rules Websites Embedding Google Fonts Violates GDPR</a>)</p>
</blockquote>
<p>This problem can be avoided by self-hosting fonts. If you're going to use an external font, make sure you consider this.</p>
<p>But you should also know that some users <a href="https://support.mozilla.org/en-US/kb/change-fonts-and-colors-websites-use#w_custom-fonts">disable custom fonts</a> or <a href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-remote-fonts">block third-party fonts</a>, so you should still specify at least a generic family name regardless.</p>
<blockquote>
<p>"You should always include at least one generic family name in a <code>font-family</code> list, since there's no guarantee that any given font is available. This lets the browser select an acceptable fallback font when necessary.‌‌‌‌‌‌‌‌" (Source: <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/font-family#try_it">MDN Documentation for font-family</a>)</p>
</blockquote>
<h3 id="heading-familiarity">Familiarity</h3>
<p>Users are familiar with the experience of their operating system.</p>
<p>Maybe not how it works under the hood, or even how to perform simple operations, but they do encounter the welcome screen, context menus, and their preinstalled applications regularly.</p>
<p>It's safer to stick with typefaces the user already has access to because these are the typefaces the user is already accustomed to reading from.</p>
<p>This argument is in a similar vein to why it's a good idea to use the system date picker, color picker, or modal/dialog boxes instead of creating custom ones.</p>
<p>Users are familiar with their system!</p>
<p>From my experience, often one of the following occurs:</p>
<ul>
<li><p>The user couldn't tell that an external font was used, making it largely redundant. Most non-specialists experience this everyday, it's hard to even tell that websites are using different fonts from each other unless you're conscious of it.</p>
</li>
<li><p>The user was able to tell, and thus has a different reading experience than what they're used to. The potential for disruption depends on the needs of the user, but that risk is often unnecessary.</p>
</li>
</ul>
<p>Unless you have a reason to change it, it's best to stick with what the user is familiar with.</p>
<h2 id="heading-who-else-does-this">Who Else Does This?</h2>
<p>Wikipedia is the most notable example, and they even have a page elaborating on the topic: <a href="https://en.wikipedia.org/wiki/Wikipedia:Typography">Meta page on Wikipedia's use of typography</a>.</p>
<p>Some of the most popular sites don't fetch a single font on their landing page, in favor of using system fonts only:</p>
<table>
<thead>
<tr>
<th>Site</th>
<th>Font Stack</th>
</tr>
</thead>
<tbody><tr>
<td>Instagram</td>
<td><code>-apple-system,&nbsp;BlinkMacSystemFont,&nbsp;"Segoe UI",&nbsp;Roboto,&nbsp;Helvetica,&nbsp;Arial,&nbsp;sans-serif</code></td>
</tr>
<tr>
<td>Wikipedia</td>
<td><code>-apple-system,&nbsp;'BlinkMacSystemFont',&nbsp;'Segoe UI',&nbsp;'Roboto',&nbsp;'Inter',&nbsp;'Helvetica',&nbsp;'Arial',&nbsp;sans-serif</code></td>
</tr>
<tr>
<td>Reddit</td>
<td><code>-apple-system,&nbsp;BlinkMacSystemFont,&nbsp;"Segoe UI",&nbsp;Roboto,&nbsp;"Helvetica Neue",&nbsp;Arial,&nbsp;"Apple Color Emoji",&nbsp;"Segoe UI Emoji",&nbsp;"Segoe UI Symbol",&nbsp;sans-serif</code></td>
</tr>
<tr>
<td>Bing</td>
<td><code>"-apple-system",&nbsp;HelveticaNeue,&nbsp;Roboto,&nbsp;Arial,&nbsp;sans-serif</code></td>
</tr>
</tbody></table>
<p>You can verify for yourself by inspecting the site with your browser's development tools.</p>
<p>There are no outgoing network requests for fonts, and the <code>font-family</code> properties are set to system fonts only.</p>
<h2 id="heading-exceptions">Exceptions</h2>
<p>There are times loading and embedding fonts does make sense, particularly if the look and feel you're after is significantly different from common system fonts:</p>
<ul>
<li><p>You're targeting an environment that doesn't have typefaces available.</p>
</li>
<li><p>To fit with existing branding, like an in-house font.</p>
</li>
<li><p>A creative or unique design, especially relevant for gaming and artsy sites.</p>
</li>
<li><p>Icon fonts like <a href="https://openmoji.org">OpenMoji</a>, but note that most clients come with emojis already.</p>
</li>
<li><p>A website that's literally for distributing, displaying, and testing fonts.</p>
</li>
</ul>
<h2 id="heading-consequences">Consequences</h2>
<p>If you apply a local font stack, your text content may not look pixel-for-pixel identical across clients. But you should measure success by the user experience.</p>
<p>It's important for the site to feel familiar, but there are more significant changes between clients already, like the human-interface, resolutions, and DPI.</p>
<p>Compared to this, it's fine if the arch of the <code>a</code> has a slightly different radius, or the tick on the <code>l</code> is a few pixels longer. In fact, this is unlikely to get noticed, so it's unlikely to impact the user experience at all.</p>
<p>Users would sooner have qualms with the difference in speed or a flicker, before the difference between similar typefaces.</p>
<p>Another argument is that allowing different typefaces may make the layout difficult to manage. Glyphs can have different widths, and therefore take up varying space.</p>
<p>But modern sites should be following <a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Responsive_Design">responsive design</a>, so you should be taking the time to make the pages fluid anyway.</p>
<p>To minimize impact, you can use <a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Text_styling/Fundamentals#web_safe_fonts">web safe fonts</a>.</p>
<p>If you dislike how limiting that is, pick a typeface included with your operating system, and find similar typefaces on other operating systems.</p>
<p>Even better if you can pick <a href="https://en.wikipedia.org/wiki/Typeface#Font_metrics">metrically compatible typefaces</a>.</p>
<h3 id="heading-comparison">Comparison</h3>
<p>Let's visit a website and see what it's like to disable downloadable fonts.</p>
<p>I'll also replace all font stacks to use Helvetica.</p>
<p>Note, my computer doesn't actually have Helvetica installed, so my operating system automatically translates this to Nimbus Sans, which is based on Helvetica. Nimbus Sans is preinstalled on <a href="https://www.debian.org">Debian</a>.</p>
<p>In the case of MDN, is the second version really so undesirable that we need to load a 252 KB font, given the penalties and demonstrations raised above? Ultimately, this one is down to user preference, so I'll let you decide.</p>
<img src="https://www.freecodecamp.org/news/content/images/2023/09/1.png" alt="1" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>MDN, with the Inter typeface fetched from client-side.</em></p>
<img src="https://www.freecodecamp.org/news/content/images/2023/09/1-1.png" alt="1-1" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>MDN, with the font-family overridden to use Helvetica.</em></p>
<p>On the flip side, that doesn't mean to never fetch fonts. There are examples where the aesthetic may be more valuable to the user experience than the performance penalty.</p>
<p>Let's look at <a href="https://framasoft.org">Framasoft</a>. They went for a more creative look and feel, also featuring a lot of <a href="https://www.davidrevoy.com">David Revoy's</a> illustrations.</p>
<p>Using Tovari Sans was a design choice which enhances the user experience, and isn't easily replaceable with a local font stack.</p>
<p>If we were to take that font away, the page feels inconsistent and unpolished. Even if we cleaned up the CSS, we'd still be detracting from the theme of the website.</p>
<img src="https://www.freecodecamp.org/news/content/images/2023/09/1-2.png" alt="1-2" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Framasoft, with the Tovari Sans typeface fetched from client-side.</em></p>
<img src="https://www.freecodecamp.org/news/content/images/2023/09/1-4.png" alt="1-4" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Framasoft, with the font-family overridden to use Helvetica.</em></p>
<h2 id="heading-resources">Resources</h2>
<p>Whether you want to go local, or just need to specify some fallback fonts, here are some helpful resources for picking out your font stack:</p>
<ul>
<li><p><a href="https://developer.apple.com/fonts/system-fonts/">List of typefaces included with Apple operating systems</a></p>
</li>
<li><p><a href="https://learn.microsoft.com/en-us/typography/fonts/windows_11_font_list#introduction">List of typefaces included with Windows</a></p>
</li>
<li><p><a href="https://en.wikipedia.org/wiki/Croscore_fonts">Core typefaces included with ChromeOS</a></p>
</li>
<li><p><a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Text_styling/Fundamentals#web_safe_fonts">Documentation for web safe fonts</a></p>
</li>
</ul>
<h2 id="heading-cross-platform-font-stacks">Cross-Platform Font Stacks</h2>
<p>There are countless articles and resources available online that feature predefined font lists you can use. These are referred to as <em>"font stacks"</em>.</p>
<p>In particular, I'd like to highlight a resource by <a href="https://danklammer.com">Dan Klammer</a>, a designer and web developer who created <a href="https://modernfontstacks.com">Modern Font Stacks</a> (<a href="https://github.com/system-fonts/modern-font-stacks">GitHub repository</a>), a website that helps you pick out native font stacks for your project.</p>
<p>Modern Font Stacks proposes a list of fonts for a variety of styles like Neo-Grotesque (a style of sans-serif) or Monospace Code (a style of monospace) and offers a visualization of how it will look across operating systems. It runs through a description of each stack, the CSS to use it, metadata like the weights available, and which of the fonts you personally have installed.</p>
<p>Some font classifications don't explicitly include a font from every operating system that exists, but remember that the generic font family (<code>sans-serif</code>, <code>serif</code>, <code>monospace</code>, <code>cursive</code>, and so on) at the end will have you covered.</p>
<p>If you like the stack, you can run with it. But don't feel constrained either, you can also use it as a starting point and tweak the font stack to your needs.</p>
<p>I've included images from the GitHub repository (at the time of writing), featuring proposed font stacks for two of the most common styles used on the internet today:</p>
<img src="https://www.freecodecamp.org/news/content/images/2024/05/neo-grotesque.png" alt="neo-grotesque" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Base font stack proposed by Modern Font Stacks for the Neo-Grotesque style, a type of sans-serif font.</em></p>
<img src="https://www.freecodecamp.org/news/content/images/2024/05/monospace-code.png" alt="monospace-code" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Base font stack proposed by Modern Font Stacks for the Monospace Code style, a type of monospace font.</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In the end, the user experience is what matters most. Sometimes that means prioritizing visual design, other times that means prioritizing performance.</p>
<p>I hope this was worth your time, and that with the knowledge you can make an informed decision when choosing fonts for your next project.</p>
<p>Feedback and questions welcome, you can hit me up on <a href="https://github.com/SethFalco">GitHub</a> or <a href="https://fosstodon.org/@sethi">Mastodon</a>.</p>
<p><em>Cover art illustrated by</em> <a href="https://hashrock.info"><em>hashrock</em></a> <em>and released under</em> <a href="https://creativecommons.org/licenses/by/4.0/"><em>CC BY 4.0</em></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Share Links that Anchor to Any Text on a Webpage ]]>
                </title>
                <description>
                    <![CDATA[ Did you know that there's an unofficial draft specification for a feature that would allow arbitrary text to be passed to the fragment (#) of a URL? This would allow users to share links that point to any particular text on a webpage! What's a URI fr... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-you-can-share-links-that-anchor-to-any-text-on-a-webpage/</link>
                <guid isPermaLink="false">66d460f433b83c4378a5183f</guid>
                
                    <category>
                        <![CDATA[ url ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Tue, 09 Aug 2022 19:54:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/untitled.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Did you know that there's an <a target="_blank" href="https://wicg.github.io/scroll-to-text-fragment/">unofficial draft</a> specification for a feature that would allow arbitrary text to be passed to the fragment (<code>#</code>) of a URL?</p>
<p>This would allow users to share links that point to any particular text on a webpage!</p>
<h2 id="heading-whats-a-uri-fragment">What's a URI fragment?</h2>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/URI_fragment">URI fragment</a> is the optional part at the end of a URL which starts with a hash (<code>#</code>) character. It lets you refer to a specific part of the document you've accessed.</p>
<p>For example, if you visit the following link, you'll automatically scroll to the top of the section you're reading right now!</p>
<p><a class="post-section-overview" href="#heading-whats-a-uri-fragment">What's a URI fragment?</a></p>
<p>Assuming you're consuming this article in the browser, you'll notice the URL changes too. It's now appended with <code>#what-s-a-uri-fragment</code>, which is the ID that the <a target="_blank" href="https://ghost.org/">Ghost CMS</a> assigned to the heading.</p>
<h2 id="heading-whats-changing">What's Changing?</h2>
<p>Before, the primary way to anchor links to part of a page was by specifying the ID of an HTML element in the fragment (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id">source</a>).</p>
<p>This put readers at the whim of the web developer or content writer. If writers didn't provide appropriate IDs, there'd be no way to anchor links to that section.</p>
<p>Some websites or tools provide a non-standard way of handling this, namely highlighting. For example, in <a target="_blank" href="https://readthedocs.org/">Read the Docs</a> you can pass the <code>highlight</code> query parameter to highlight any particular text on the page.</p>
<p>You can try it out in the <a target="_blank" href="https://docs.weblate.org/en/latest/">Weblate documentation</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-186.png" alt="The Weblate documentation open on the Machine Translations page. The highlight query parameters is specified, so all instances of the word &quot;LibreTranslate&quot;, not case-sensitive, are highlighted." width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://docs.weblate.org/en/latest/admin/machine.html?highlight=libretranslate#libretranslate"><em>This is what you see when you specify the</em> <code>highlight</code> query parameter on the Weblate documentation.</a></p>
<p>Text Fragments are a relatively new proposal which extend the usability of URI fragments to query and highlight any arbitrary text as well.</p>
<h2 id="heading-why-would-this-be-useful">Why Would This Be Useful?</h2>
<p>Can you relate to one or more of these scenarios?</p>
<ul>
<li><p>When sourcing information, you can link directly to the quote or content you cited.</p>
</li>
<li><p>As a member of support staff, you can link to and highlight a particular excerpt of the documentation or FAQ for the user.</p>
</li>
<li><p>Text fragments can be used with any arbitrary text document that can't store anchor metadata, such as plaintext or configuration files.</p>
</li>
<li><p>You're a web developer who implemented a custom solution for this, but can now just let the browser handle it for you.</p>
</li>
</ul>
<p>If so, then this might help better attribute content on the web, highlight information your users need, or relieve some maintenance effort for developers.</p>
<h2 id="heading-the-proposal">The Proposal</h2>
<p>You can specify either literal text, or the start and end of a range of text. The spec includes a pseudo-diagram that demonstrates what the syntax looks like:</p>
<pre><code class="lang-plaintext">:~:text=[prefix-,]textStart[,textEnd][,-suffix]

         context  |-------match-----|  context
</code></pre>
<p>Or alternatively, a more digestible version:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Section</td><td>Required</td><td>Description</td><td>Notes</td></tr>
</thead>
<tbody>
<tr>
<td><code>prefix</code></td><td>false</td><td>Value must appear before the text, but won't be highlighted.</td><td>Must end with <code>-</code>.</td></tr>
<tr>
<td><code>textStart</code></td><td>true</td><td>If <code>textEnd</code> is not specified, matches literally, otherwise used in combination with <code>textEnd</code> to match a range.</td><td></td></tr>
<tr>
<td><code>textEnd</code></td><td>false</td><td>Used in combination with <code>textStart</code> to match a range of text.</td><td></td></tr>
<tr>
<td><code>suffix</code></td><td>false</td><td>Value must appear after the text, but won't be highlighted.</td><td>Must start with <code>-</code>.</td></tr>
</tbody>
</table>
</div><p>The sections <code>prefix</code> and <code>suffix</code> are used for context, so if the text you want to match appears multiple times on a page, you can use them to indicate to the browser which instance you want to match.</p>
<p>To provide some examples, let's suppose we open the Web Monetization website which includes the following text.</p>
<blockquote>
<p>A JavaScript browser API that allows the creation of a payment stream from the user agent to the website</p>
<p>— <a target="_blank" href="https://webmonetization.org/">https://webmonetization.org/</a></p>
</blockquote>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Example</td><td>Highlights</td></tr>
</thead>
<tbody>
<tr>
<td><code>:~:text=javascript</code></td><td>JavaScript</td></tr>
<tr>
<td><code>:~:text=api,stream</code></td><td>API that allows the creation of a payment stream</td></tr>
<tr>
<td><code>:~:text=javascript-,browser</code></td><td>browser</td></tr>
<tr>
<td><code>:~:text=a-,javascript,api</code></td><td>JavaScript browser API</td></tr>
<tr>
<td><code>:~:text=that-,allows,stream,-from</code></td><td>allows the creation of a payment stream</td></tr>
</tbody>
</table>
</div><p>For longer excerpts of text, a range is preferred to avoid bloating the URL. Usually, developers will aim to keep the total length of URLs below 2,000~ characters anyway. This avoids potential issues with older user-agents, especially after accounting for the length of the domain and query parameters.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Untitled-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Matrix_(protocol)#:~:text=KDE,client%20Konversation"><em>Here is how highlighting looks on Chromium when you visit a webpage with a text fragment.</em></a></p>
<h3 id="heading-implementation-details">Implementation Details</h3>
<p>From reading the spec, and testing manually in a Chromium browser, here are some of the finer details with querying content in a text fragment.</p>
<ul>
<li><p>The sections are not case-sensitive, and accents are ignored (<a target="_blank" href="https://wicg.github.io/scroll-to-text-fragment/#finding-ranges-in-a-document">source</a>)</p>
</li>
<li><p>All sections match whole words only, so you can't partially match</p>
</li>
<li><p>Only the first match will be highlighted if there are multiple (<a target="_blank" href="https://wicg.github.io/scroll-to-text-fragment/#syntax">source</a>)</p>
</li>
</ul>
<h2 id="heading-compatibility">Compatibility</h2>
<p>Text fragments are available in most Chromium browsers, as this was implemented in <a target="_blank" href="https://chromestatus.com/feature/4733392803332096">Chromium itself in 2020</a>.</p>
<p>Text fragments are not available in Firefox at all yet. Mozilla will hopefully have this implemented in the future – in February 2022 they <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1753933">opened a ticket to track progress</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://caniuse.com/url-scroll-to-text-fragment">https://caniuse.com/url-scroll-to-text-fragment</a></div>
<p> </p>
<h2 id="heading-privacy-and-security">Privacy and Security</h2>
<p>Some concerns have been raised with the specifications, namely that automatically scrolling to parts of the page may reveal certain details about the user.</p>
<p>An interesting thing about URI fragments is that they shouldn't be sent to web servers for processing. URI fragments are intended to be a client-side/user-agent only mechanism to be handled locally by the browser or web application.</p>
<p>To verify this, we can run a small Express server that just logs the URL. We'll see if it includes the fragment:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> port = <span class="hljs-number">3000</span>;

app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
   <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'URL:'</span>, req.url);
   res.status(<span class="hljs-number">204</span>).send();
});

app.listen(port, <span class="hljs-function">() =&gt;</span> {
   <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port <span class="hljs-subst">${port}</span>.`</span>); 
});
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Peek-2022-08-06-18-12.gif" alt="Running a webserver and executing curl commands to hit it. When we specify a fragment in the URL in curl, the web server doesn't receive it." width="600" height="400" loading="lazy"></p>
<p><em>The results of each request via curl. The same strings would've printed had I executed the requests in a browser.</em></p>
<p>Some websites take advantage of this to improve privacy and reduce the bandwidth sent to web servers.</p>
<p>For example, if you look at <a target="_blank" href="https://www.typescriptlang.org/play">TypeScript Playground</a>, you'll notice instead of using query parameters or building a short URL, they just encode the TypeScript and store it in the URI fragment.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/Untitled.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Observe how the URL includes a URI fragment. It's actually just</em> <code>console.log('Hello, World!');</code> but encoded.</p>
<p>With an implementation like this, you can bookmark or share the link with anyone, and their web server won't know or care about the code. However, any services you use to share the link could, of course, decode and read it.</p>
<p>However, the concern raised with text fragments is that, if a user-agent will automatically scroll down to a given section of a page, while the text fragment wouldn't have been shared with the web server, network requests may've been induced such as loading images on that part of the site. This would allow the web server to derive that you were linked to that section of the page (<a target="_blank" href="https://github.com/WICG/scroll-to-text-fragment/issues/76">source</a>).</p>
<p>Despite these concerns, it appears to me that URI fragments as a whole have been susceptible to this for a long-time, not just text fragments.</p>
<p>Regardless, it's a good thing to keep in mind until browser developers and security researchers give this more thought.</p>
<h2 id="heading-link-to-text-fragment-extension">Link to Text Fragment Extension</h2>
<p>Google has also developed an <a target="_blank" href="https://github.com/GoogleChromeLabs/link-to-text-fragment">extension</a> which provides a UI to link any arbitrary text as a URL.</p>
<p>The extension adds "Copy Link to Selected Text" to the context-menu when you select text and secondary-click on it. You can see it in action on the following video.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Y5DmGqnzvBI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://chrome.google.com/webstore/detail/link-to-text-fragment/pbcodcjpfjdpcineamnnmbkkmkdpajjg">https://chrome.google.com/webstore/detail/link-to-text-fragment/pbcodcjpfjdpcineamnnmbkkmkdpajjg</a></div>
<p> </p>
<p>The extension also ships for Firefox, and polyfills an implementation of text fragments into each webpage, so it'll even scroll to and highlight the matched text too.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://addons.mozilla.org/en-US/firefox/addon/link-to-text-fragment/">https://addons.mozilla.org/en-US/firefox/addon/link-to-text-fragment/</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this gives more incite on URI fragments as a whole, and especially text fragments.</p>
<p>If you have any ideas for how the specification can be improved, feel free to review the open issues on the browser's and WICG's repositories and provide your thoughts.</p>
<p>I'm eager to see more browsers support this, as it makes the experience of citing, attributing, and linking to content on the web a lot more convenient.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Participate in Hacktoberfest – Even if You Don't Write Code ]]>
                </title>
                <description>
                    <![CDATA[ Hacktoberfest is an event hosted by DigitalOcean that partners with many organizations. The goal is to give back and contribute to open-source projects. The organizers offer little incentives for a job well done, like a shirt and stickers. Other orga... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-anyone-can-participate-in-hacktoberfest/</link>
                <guid isPermaLink="false">66d460ee3a8352b6c5a2aafb</guid>
                
                    <category>
                        <![CDATA[ hacktoberfest ]]>
                    </category>
                
                    <category>
                        <![CDATA[ open source ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Wed, 06 Oct 2021 15:14:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/untitled.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://hacktoberfest.digitalocean.com/">Hacktoberfest</a> is an event hosted by <a target="_blank" href="https://www.digitalocean.com/">DigitalOcean</a> that partners with many organizations. The goal is to give back and contribute to open-source projects. The organizers offer little incentives for a job well done, like a shirt and stickers.</p>
<p>Other organizations also get involved by offering their own rewards. You can find a community-sourced list of organizations offering incentives to contribute on <a target="_blank" href="https://hacktoberfest-swag.com/">Hacktoberfest Swag</a>.</p>
<p>Only meaningful contributions will count toward the total 4 required. Take your time and show common courtesy with maintainers to ensure your pull requests get merged. More on this in <a class="post-section-overview" href="#heading-lets-avoid-turning-it-into-spamtoberfest">Let's Avoid Turning it into Spamtoberfest</a> below.</p>
<h2 id="heading-how-you-can-participate-in-hacktoberfest">How you can Participate in Hacktoberfest</h2>
<p>It's important to note that Hacktoberfest is for making any <strong>quality</strong> contribution to open-source projects. No one said it has to be code!</p>
<p>Everyone is capable of putting something forward:</p>
<ul>
<li><p>Authors</p>
</li>
<li><p>Artists</p>
</li>
<li><p>Software Developers</p>
</li>
<li><p>Technical Writers</p>
</li>
<li><p>Translators</p>
</li>
</ul>
<h3 id="heading-recommended-projects-for-hacktoberfest-contributions">Recommended Projects for Hacktoberfest Contributions</h3>
<p>I'm not going to explicitly list repositories for contributing code because that's easy enough to find. All repositories listed on the following links have opted-in to Hacktoberfest.</p>
<ul>
<li><p><a target="_blank" href="https://gitlab.com/explore/projects?topic=hacktoberfest">GitLab</a> (All repositories with the topic <code>hacktoberfest</code> on GitLab.)</p>
</li>
<li><p><a target="_blank" href="https://github.com/topics/hacktoberfest">GitHub</a> (All repositories with the topic <code>hacktoberfest</code> on GitHub.)</p>
</li>
</ul>
<p>Below are projects I recommend if you don't know how to code but still want to contribute to open-source (or <a target="_blank" href="https://creativecommons.org/">Creative Commons</a>) projects. It only includes projects that have manually opted-in to Hacktoberfest.</p>
<p>You shouldn't need to know any programming languages or HTML to contribute to them. You will be expected to know how to commit your work with Git, though, which we'll cover later.</p>
<h4 id="heading-art">Art</h4>
<p>Projects that need art or animations:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/jmhobbs/cultofthepartyparrot.com">Cult of the Party Parrot</a> — Animated parrot emojis.</p>
</li>
<li><p><a target="_blank" href="https://gitlab.com/Elypia/elypia-emotes">Elypia Emotes</a> — Red panda emojis.</p>
</li>
</ul>
<h4 id="heading-awesome-lists">Awesome Lists</h4>
<p>Community-maintained lists of resources:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/BenRoe/awesome-mechanical-keyboard">Awesome Mechanical Keyboard</a> ­— List of open-source keyboards.</p>
</li>
<li><p><a target="_blank" href="https://github.com/EbookFoundation/free-programming-books/">Free Programming Books</a> — List of free books anyone can access.</p>
</li>
<li><p><a target="_blank" href="https://github.com/EbookFoundation/free-science-books">Free Science Books</a> — List of free books anyone can access.</p>
</li>
<li><p><a target="_blank" href="https://github.com/remoteintech/remote-jobs">Remote-Friendly Companies</a> — List of remote-friendly companies.</p>
</li>
</ul>
<h4 id="heading-books">Books</h4>
<p>Free eBooks maintained with a docs-as-code approach:</p>
<ul>
<li><a target="_blank" href="https://github.com/bobbyiliev/introduction-to-bash-scripting">Introduction to Bash Scripting</a> — Free eBook for Bash.</li>
</ul>
<h4 id="heading-configuration">Configuration</h4>
<p>Projects that revolve around configuration files. A contribution could just be appending an entry to a JSON file:</p>
<ul>
<li><a target="_blank" href="https://github.com/2factorauth/twofactorauth">2fa.directory</a> — List of sites with 2FA. (<a target="_blank" href="https://github.com/2factorauth/twofactorauth/tree/master/entries">More Info</a>)</li>
</ul>
<h4 id="heading-documentation">Documentation</h4>
<p>Projects where you just have to type in plain English. Programming and technical knowledge will help, but there's no need for a specialized skill.</p>
<p>This only includes repositories that maintain documentation in a format that would be simple for most users, like <a target="_blank" href="https://commonmark.org/help/">Markdown</a>.</p>
<ul>
<li><p><a target="_blank" href="https://github.com/dotnet/docs">.NET Docs</a> — Documentation for .NET.</p>
</li>
<li><p><a target="_blank" href="https://github.com/github/docs">GitHub Docs</a> — Documentation for GitHub.</p>
</li>
<li><p><a target="_blank" href="https://github.com/jellyfin/jellyfin-docs">Jellyfin Docs</a> — Documentation for Jellyfin.</p>
</li>
<li><p><a target="_blank" href="https://github.com/nextcloud/documentation">Nextcloud Docs</a> — Documentation for Nextcloud.</p>
</li>
<li><p><a target="_blank" href="https://github.com/tldr-pages/tldr">tldr-pages</a> — Cheat sheets for CLI applications.</p>
</li>
</ul>
<h4 id="heading-translations">Translations</h4>
<p>Projects that need text translated from English to other languages.</p>
<p>Projects that use crowd-translations platforms like <a target="_blank" href="https://weblate.org/">Weblate</a> aren't included here, since the translator doesn't create the pull request. Unfortunately, Hacktoberfest only considers whoever opened the pull request, not the authors of the changes.</p>
<p>Please make sure that you only contribute human-reviewed translations – so either translated by a human, or machine-translated but verified by a human. Again, quality is important.</p>
<ul>
<li><p><a target="_blank" href="https://github.com/EbookFoundation/free-programming-books/">Free Programming Books</a> — Translate health files.</p>
</li>
<li><p><a target="_blank" href="https://github.com/tldr-pages/tldr">tldr-pages</a> — Translate cheat sheets.</p>
</li>
</ul>
<h4 id="heading-miscellaneous">Miscellaneous</h4>
<p>Projects that are one of a kind:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/duffn/dumb-password-rules">Dumb Password Rules</a> — List of sites with dumb password rules.</p>
</li>
<li><p><a target="_blank" href="https://github.com/benbarth/hacktoberfest-swag">Hacktoberfest Swag</a> — List of projects rewarding contributors.</p>
</li>
</ul>
<h2 id="heading-lets-avoid-turning-it-into-spamtoberfest">Let's Avoid Turning it into Spamtoberfest</h2>
<p>Unfortunately, Hacktoberfest has developed a bit of a bad reputation among some projects due to spam. Sometimes contributors can be a bit eager to complete Hacktoberfest and miss the point. ^-^'</p>
<p>From 2020, if a user makes 2 pull requests that get assigned a label with the word <code>spam</code> or <code>invalid</code> in it, the contributor will be banned from Hacktoberfest indefinitely, including future events.</p>
<p><a target="_blank" href="https://github.com/Anuken/Mindustry">Mindustry</a> handles this the best in my opinion with the <a target="_blank" href="https://github.com/Anuken/Mindustry/pulls?q=label%3A%22hacktoberfest+hall+of+shame+%28invalid%29%22+">Hacktoberfest Hall of Shame</a>.</p>
<p>From 2021, Hacktoberfest is doing more to crack down on spam by excluding projects that encourage pull requests with no value.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The goal of giving back to open-source gets undermined if most contributions just go to "Complete Hacktoberfest!" repositories.</em></p>
<h3 id="heading-how-to-make-valuable-hacktoberfest-contributions">How to make valuable Hacktoberfest contributions</h3>
<ul>
<li><p>You have a month to make the 4 pull requests. Use it! They're more likely to get merged if you make fewer good quality pull requests.</p>
</li>
<li><p>Don't assume every pull request you make will be merged before Hacktoberfest is over. Try to do more than 4 if you can!</p>
</li>
</ul>
<h3 id="heading-practice-common-courtesy">Practice common courtesy</h3>
<p>Open-source maintainers have a life too. They don't always have time to review all pull requests, especially towards the end of Hacktoberfest.</p>
<p>Don't make maintainers feel bad, don't rush them, and don't demand attention. Just work on something else if they're busy.</p>
<h2 id="heading-how-to-commit-work-and-open-a-pull-request">How to Commit Work and Open a Pull Request</h2>
<p>Now that you know how to be a helpful Hacktoberfest participant, and you've learned about some projects you'll be able to contribute too, the only thing left is to actually learn how to contribute.</p>
<p>GitHub and GitLab both provide ways to simplify contributing for small changes. We're not going to use them because it'll be simpler to show a single set of instructions that will work everywhere rather than rely on platform-specific features.</p>
<p>Before you continue, pick a repository that you want to contribute to. If you're multilingual then tldr-pages will be easiest, otherwise consider Free Programming Books.</p>
<p>I'm going to use Free Programming Books in my examples.</p>
<h3 id="heading-how-to-install-git">How to install Git</h3>
<p>First, you should install Git which is a version control system. This is the tool that projects are using to manage changes.</p>
<p>Windows users can download it from the <a target="_blank" href="https://git-scm.com/">git-scm</a> website. Linux users can install it using their preferred package manager.</p>
<p>Once you have Git installed, verify it's installed correctly with <code>git --version</code>.</p>
<p>Now configure your name and email address. The name doesn't matter, but you should specify the same email address you're using for Hacktoberfest.</p>
<pre><code class="lang-plaintext">git config --global user.name "Your Name"
git config --global user.email "your@email.org"
</code></pre>
<p>Note that the email address you specify here will be considered public information once your pull request has been merged. Anyone can view the details of a commit which includes the author details.</p>
<p>For example, my email address is in the output when I do <code>git log</code> on one of my commits.</p>
<pre><code class="lang-sh">commit 9647912b202a57474b4cd0ce796126c462c1ecc0 (HEAD -&gt; added-react-book, develop/added-react-book)
Author: Seth Falco &lt;seth@falco.fun&gt;
Date:   Tue Oct 5 14:04:25 2021 +0200

    added a react book from digitalocean
</code></pre>
<p>If this is a problem, both <a target="_blank" href="https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-user-account/managing-email-preferences/setting-your-commit-email-address#setting-your-commit-email-address-on-github">GitHub</a> and <a target="_blank" href="https://docs.gitlab.com/ee/user/profile/index.html#use-an-automatically-generated-private-commit-email">GitLab</a> provide a feature to hide your email address by giving you a disposable one. You can enable the feature and use that email address in <code>git config</code> instead.</p>
<h3 id="heading-how-to-fork-and-clone-a-repository">How to fork and clone a repository</h3>
<p>Next, you'll want to fork the repository. You won't be allowed to push changes directly to the repository, so instead you'll make a fork which is a copy of the project that's under your control.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The "Fork" button is at the top-right of the repository page.</em></p>
<p>Next, clone the repository locally. This pulls a copy of everything in the repository to your machine so you can start working on it.</p>
<p>We'll do this in the terminal. If you're on Windows you can use Command Prompt or <a target="_blank" href="https://docs.microsoft.com/en-us/powershell/">PowerShell</a>.</p>
<p>Go to an appropriate location on your file system like your <code>Downloads</code> or <code>Documents</code> directory, then execute this following:</p>
<ul>
<li><p>Clone the repository you want to work on.</p>
</li>
<li><p>Enter the directory in the terminal.</p>
</li>
<li><p>Link the repository with the fork on your account.</p>
</li>
</ul>
<pre><code class="lang-sh">git <span class="hljs-built_in">clone</span> https://github.com/EbookFoundation/free-programming-books.git
<span class="hljs-built_in">cd</span> free-programming-books
git remote add develop https://github.com/{YOUR_USERNAME}/free-programming-books.md
</code></pre>
<h3 id="heading-how-to-work-with-the-project">How to work with the project</h3>
<p>Now that you've cloned the repository locally, you can start working with it. With most repositories, it's best to open it up in a code editor like <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a>, but you can technically work with any text editor including Notepad.</p>
<p>Open the directory containing the repository you cloned in your editor. By default, it's named after the repository name, for example I now have a folder named <code>free-programming-books</code>.</p>
<p>Now you can make changes:</p>
<ul>
<li><p>If you're not sure what to do, check if there's anything specific they need by looking under the "Issues" tab on the repository.</p>
</li>
<li><p>Alternatively, make whatever <em>meaningful</em> change you want.</p>
</li>
</ul>
<p>With Free Programming Books, it's a repository for maintaining a list of free eBooks, so we can add more resources to it.</p>
<p><a target="_blank" href="https://www.digitalocean.com/community/tags/book">DigitalOcean</a> has some great books in the community section of their website, so we can just add one or more of them to the repository. I've picked out <a target="_blank" href="https://www.digitalocean.com/community/books/how-to-code-in-react-js-ebook">How To Code in React.js</a> for this example.</p>
<p>I can go to the respective section in the project which is the <code>books/free-programming-books-langs.md</code> file, and add the resource under the <code>React</code> section of the document.</p>
<p>The line I added looks like this:</p>
<pre><code class="lang-md"><span class="hljs-bullet">*</span> [<span class="hljs-string">How To Code in React.js</span>](<span class="hljs-link">https://www.digitalocean.com/community/books/how-to-code-in-react-js-ebook</span>) - Joe Morgan
</code></pre>
<h3 id="heading-how-to-commit-your-work">How to commit your work</h3>
<p>Now that you've made a change, you'll want to actually commit and push your work back up.</p>
<p>You've only made the change <em>locally</em> so far – now we want to send a pull request. This basically means you'll send a request asking the maintainer of the repository to include your changes in their repository.</p>
<p>In your terminal, we'll execute the following which will:</p>
<ul>
<li><p>Create a new branch.</p>
</li>
<li><p>Tell Git you want to stage all changes to be saved.</p>
</li>
<li><p>Commit the change with a message describing what you did.</p>
</li>
<li><p>Push the changes to your fork.</p>
</li>
</ul>
<pre><code class="lang-sh">git checkout -b added-react-book
git add .
git commit -m <span class="hljs-string">"added a react book from digitalocean"</span>
git push develop added-react-book
</code></pre>
<p>This should hopefully produce output like the following:</p>
<pre><code class="lang-sh">Enumerating objects: 7, <span class="hljs-keyword">done</span>.
Counting objects: 100% (7/7), <span class="hljs-keyword">done</span>.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), <span class="hljs-keyword">done</span>.
Writing objects: 100% (4/4), 1.07 KiB | 1.07 MiB/s, <span class="hljs-keyword">done</span>.
Total 4 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 3 <span class="hljs-built_in">local</span> objects.
remote: 
remote: Create a pull request <span class="hljs-keyword">for</span> <span class="hljs-string">'added-react-book'</span> on GitHub by visiting:
remote:      https://github.com/SethFalco/free-programming-books/pull/new/added-react-book
remote: 
To github.com:SethFalco/free-programming-books.git
 * [new branch]        added-react-book -&gt; added-react-book
</code></pre>
<h3 id="heading-how-to-create-a-pull-request">How to create a pull request</h3>
<p>Both GitHub and GitLab will drop a link in the output of the command above that will take you to open a pull request.</p>
<p>If you click that link (you may need to hold <code>CTRL</code>), it'll take you to a page where you can provide more information and submit your pull request.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/image-11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Just fill in the details requested and click "Create pull request". All that's left is to wait for the maintainers to review it.</p>
<h3 id="heading-clean-up-the-code">Clean up the code</h3>
<p>As soon as you've finished a pull request, you should leave your branch and go back to the primary branch of the repository.</p>
<p>Execute the following commands in your terminal:</p>
<ul>
<li><p>Check if the primary branch is <code>main</code> or <code>master</code>.</p>
</li>
<li><p>Switch to the primary branch of the repository.</p>
</li>
<li><p>Update your local copy to be in sync with the repository.</p>
</li>
</ul>
<pre><code class="lang-sh">git branch
git checkout main
git pull
</code></pre>
<p>Restart from the "How to work with the project" step to make more changes.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this gives more information about Hacktoberfest, and that you feel more confident participating with the open-source community even if you don't write software.</p>
<p>Best of luck with your pull requests!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Block Annoying Content From Web Pages Using uBlock Origin ]]>
                </title>
                <description>
                    <![CDATA[ You can use extensions in your browser to remove parts of a webpage you don't want to see. Removing annoyances, distractions, and irrelevant content is a great way to stay focused and remain efficient while you consume information on the internet. Th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-block-content-from-web-pages-using-ublock-origin/</link>
                <guid isPermaLink="false">66d460f0768263422736e8b1</guid>
                
                    <category>
                        <![CDATA[ Browsers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Tue, 24 Aug 2021 19:39:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/untitled-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You can use extensions in your browser to remove parts of a webpage you don't want to see. Removing annoyances, distractions, and irrelevant content is a great way to stay focused and remain efficient while you consume information on the internet.</p>
<p>There are many extensions that add this functionality to your browser. I'll be focusing on <a target="_blank" href="https://ublockorigin.com/">uBlock Origin,</a> as many will already have it. If you don't, then I'd strongly recommend installing it.</p>
<h2 id="heading-what-is-ublock-origin">What is uBlock Origin?</h2>
<p><a target="_blank" href="https://ublockorigin.com/">uBlock Origin</a> is a free and open-source ad blocker available for all major browsers. It also includes an <a target="_blank" href="https://github.com/gorhill/uBlock/wiki/Element-picker">element picker</a> tool that can remove custom elements, which is what we'll be using in this article.</p>
<p>Having knowledge of CSS selectors or XPath will help you go through this tutorial, but isn't required. uBlock Origin provides visual tools to select elements without technical knowledge. Still, writing the selector manually will usually be more reliable.</p>
<h2 id="heading-why-blocking-elements-is-useful">Why Blocking Elements Is Useful</h2>
<p>On the internet, we're constantly consuming information, but quite often it's information that simply isn't relevant to us.</p>
<p>If you access particular websites frequently, it can be a big boost to productivity if you can conditionally single out the information you know you won't need and never consume it in the first place.</p>
<ul>
<li><p>Removing certain types of events from activity or social media feeds.</p>
</li>
<li><p>Removing popups that ask you to do things you don't want to.</p>
</li>
<li><p>Removing posts from particular authors on YouTube or social media.</p>
</li>
<li><p>Removing distractions or dynamic elements that draw your attention.</p>
</li>
</ul>
<h2 id="heading-how-to-filter-html-elements">How to Filter HTML Elements</h2>
<p>To filter elements, you can click the uBlock Origin icon at the top of your browser, then click the element picker, the one with the eye drop icon. (<a target="_blank" href="https://github.com/gorhill/uBlock/wiki/Element-picker">More Info</a>)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/Untitled.png" alt="The uBlock Origin interface, it contains all actions that can be performed such as blocking media, fonts, or elements on the current page." width="600" height="400" loading="lazy"></p>
<p><em>The uBlock Origin interface, this appears if you click the icon in your browser's toolbar.</em></p>
<p>You can start by selecting the content you want to remove. Even if the selection isn't perfect, it's just a starting point.</p>
<p>Once the box appears at the bottom-right, you can use the visual tools with the "Pick" button and sliders, or manually specify a selector.</p>
<p>The content highlighted in red is what will be removed once you select the "Create" button. These changes will persist even after refreshing or revisiting the page at a later date. Let's see how this works.</p>
<h3 id="heading-css-selectors">CSS Selectors</h3>
<p>You can remove most elements you want to remove easily using CSS selectors. This is great for removing static content on the page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-93.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Removes all release and push events from appearing in my GitHub activity feed. (</em><code>##div.news div.release, div.news div.push</code>)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-85.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Removes the banner to download Slack. (</em><code>##.p-client__banners</code>)</p>
<h3 id="heading-xpath">XPath</h3>
<p>You'll usually want to use XPath for one of two reasons:</p>
<ul>
<li><p>You need to check against the value of an element.</p>
</li>
<li><p>You need to select an element based on the attributes of its children.</p>
</li>
</ul>
<p>This is useful for removing dynamic or user-generated content. We want to remove the entire element, but only if something inside it matches the criteria rather than the element itself.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-57.png" alt="Using the uBlock Origin cosmetic filter tool to highlight all elements that would be deleted from my current selection." width="600" height="400" loading="lazy"></p>
<p><em>Removes all plugins from DevilBro. (</em><code>##:xpath(//a[./div/div/p/object/a = "DevilBro"])</code>)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-58.png" alt="Using the uBlock Origin cosmetic filter tool to remove all elements I don't want to see. The site now displays as if they were never there." width="600" height="400" loading="lazy"></p>
<p><em>How it looks after removing all plugins by DevilBro.</em></p>
<h3 id="heading-troubleshooting-your-filters">Troubleshooting your filters</h3>
<p>When filtering elements, your selectors can break at any time. Websites change for various reasons, in most cases due to maintenance or updates.</p>
<p>Don't let that deter you from doing what you want, though. It just means you should keep this in mind when you remove elements.</p>
<p>Try to keep your selectors local to what you actually want to remove, but strict enough that it won't falsely select other elements on the page.</p>
<p>There are also many websites that don't appreciate client-side modifications, and try to hinder this by arbitrarily changing HTML attribute values or obfuscating them.</p>
<p>In these cases, it's best to specify <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors">CSS attribute selectors</a> or use XPath to partially match attribute values.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-91.png" alt="Selecting the &quot;Active Now&quot; view on Discord using a CSS attribute selector. The &quot;Active Now&quot; component is highlighed in red to indicate it will be removed." width="600" height="400" loading="lazy"></p>
<p><em>Removing the "Active Now" view on Discord using an attribute selector, (</em><code>##div[class^="nowPlayingColumn"]</code>)</p>
<h3 id="heading-how-to-remove-filters">How to Remove Filters</h3>
<p>If you no longer want to block something, or the website has changed, you can go to the settings to remove the old filter before making a new one.</p>
<p>To remove a custom filter:</p>
<ol>
<li><p>Navigate to the uBlock Origin settings.</p>
</li>
<li><p>Select the "My filters" tab.</p>
</li>
<li><p>Delete the lines with the filter(s) you want removed.</p>
</li>
<li><p>Click "Apply changes" at the top.</p>
</li>
<li><p>Refresh the page you were on.</p>
</li>
</ol>
<h2 id="heading-other-helpful-browser-extensions">Other Helpful Browser Extensions</h2>
<p>There are other extensions you can use to remove specific types of content on websites, too.</p>
<h3 id="heading-highlight-or-hide-search-engine-results">Highlight or Hide Search Engine Results</h3>
<p><a target="_blank" href="https://github.com/pistom/hohser">Highlight or Hide Search Engine Results</a> (HOHSER) supports all major search engines, including <a target="_blank" href="https://duckduckgo.com/">DuckDuckGo</a> and Google.</p>
<p>I believe domain blacklisting should be a native user-setting available in search engines, but until that's a thing, you can use this extension to hide results under domains you don't like.</p>
<ul>
<li><p>Websites with re-hosted or shady download links.</p>
</li>
<li><p>Search engine optimized junk, like fake coupon websites.</p>
</li>
<li><p>Websites that block users in the EU.</p>
</li>
</ul>
<h3 id="heading-i-still-dont-care-about-cookies">I still don't care about cookies</h3>
<p><a target="_blank" href="https://github.com/OhMyGuus/I-Still-Dont-Care-About-Cookies">I still don't care about cookies</a> removes cookie warnings from appearing on most websites, that way you don't have to deal with them yourself.</p>
<p>The extension will attempt to hide the cookie message, only accepting cookies if necessary.</p>
<p>I strongly recommend only using this in combination with extensions like uBlock Origin and Privacy Badger, to prevent undesirable cookies from being saved.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope you're not in a situation where you feel the need to block a significant amount of content from the pages you load.</p>
<p>But if you do feel the need, I hope this makes browsing the internet just a little more bearable for you.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Why You Should Use EditorConfig to Standardize Code Styles ]]>
                </title>
                <description>
                    <![CDATA[ You use EditorConfig to define formatting conventions for textual files in a project. It's great because it's widely supported, and it's not tied to any particular language, framework, or code editor. EditorConfig on its own is just a vendor-agnostic... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-editorconfig-to-standardize-code-styles/</link>
                <guid isPermaLink="false">66d460f2d1ffc3d3eb89de58</guid>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ configuration ]]>
                    </category>
                
                    <category>
                        <![CDATA[ configuring settings ]]>
                    </category>
                
                    <category>
                        <![CDATA[ editor ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Wed, 21 Jul 2021 21:28:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/07/untitled.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You use <a target="_blank" href="https://editorconfig.org/">EditorConfig</a> to define formatting conventions for textual files in a project. It's great because it's widely supported, and it's not tied to any particular language, framework, or code editor.</p>
<p>EditorConfig on its own is just a vendor-agnostic configuration file. It relies on third-party tools or integrations to implement support for the rules declared in the file.</p>
<p>They can be read by IDEs (Integrated Development Environments), code editors, or build tools to enforce or apply formatting conventions.</p>
<h2 id="heading-what-does-editorconfig-solve">What Does EditorConfig Solve?</h2>
<p>Users usually configure the code style settings in an editor to <em>their</em> preferences. Unfortunately, their preferences probably don't correlate with yours.</p>
<p>What happens when they're contributing to a shared project? This might be a project at work, or an open-source project on GitLab or GitHub.</p>
<p>The user's style settings get applied to the files they modify. This can result in projects feeling inconsistent or messy, with some or all of the following issues:</p>
<ul>
<li><p>Mixed use of tabs and spaces.</p>
</li>
<li><p>Mixed use of line endings. (Usually not a significant issue with <a target="_blank" href="https://git-scm.com/">Git</a>.)</p>
</li>
<li><p>Files may not have the desired character encoding.</p>
</li>
<li><p>Various indentation sizes across files.</p>
</li>
</ul>
<p>Without consistency, the code can appear untidy and be a pain to read, depending on a user's development environment.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://github.com/eclipse/eclipse.jdt.ls/blob/master/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/EventNotification.java?ts=8"><em>eclipse.jdt.ls</em></a> <em>mixes tabs and spaces, here's how it looks on GitHub with a tab size of 8.</em></p>
<p>A common solution is to share editor settings as part of the project, but this assumes all committers are using the same editor as you, which probably isn't the case.</p>
<p>For Java development alone, the following are all popular choices:</p>
<ul>
<li><p><a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a> (What I use!)</p>
</li>
<li><p><a target="_blank" href="https://www.eclipse.org/">Eclipse</a></p>
</li>
<li><p><a target="_blank" href="https://www.jetbrains.com/idea/">IntelliJ</a></p>
</li>
<li><p><a target="_blank" href="https://netbeans.apache.org/">NetBeans</a></p>
</li>
</ul>
<p>You'll bloat your project with unrelated files if you add the configuration for every editor someone might use.</p>
<p>So, how about a vendor-agnostic solution where editors are responsible for utilizing a shared configuration instead?</p>
<h2 id="heading-how-editorconfig-helps">How EditorConfig Helps</h2>
<p>Defining conventions helps everyone throughout a project's life-cycle. There are namely three ways it saves time.</p>
<h3 id="heading-editorconfig-makes-code-more-readable">EditorConfig Makes Code More Readable</h3>
<p>Making code more readable is by far the most important reason to use it. This improves the maintainability of the project, and the speed that people can work.</p>
<blockquote>
<p>“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code… Therefore, making it easy to read makes it easier to write.”<br>― Robert C. Martin</p>
</blockquote>
<p>There are many other reasons someone might be reading the code outside of development too:</p>
<ul>
<li><p>Researchers that need to better understand how the project works.</p>
</li>
<li><p>Security analysts that are checking for vulnerabilities.</p>
</li>
<li><p>Technical writers that are documenting application behavior.</p>
</li>
</ul>
<p>People will be able to perform their role more effectively if your code is kept tidy, consistent, and human-readable.</p>
<h3 id="heading-editorconfig-makes-code-reviews-easier">EditorConfig Makes Code Reviews Easier</h3>
<p>As a project maintainer, you'll inevitably have to review code contributed by others. They might be a fellow team member, or open-source contributors that discover your project.</p>
<p>Enforcing formatting should be delegated to software. This will make reading and reviewing the code more efficient, and avoids the need to request changes based on formatting.</p>
<p>Reducing the feedback loop ultimately saves everyone time.</p>
<h3 id="heading-editorconfig-makes-development-easier">EditorConfig Makes Development Easier</h3>
<p>Developers can save a lot of headache by having conventions that are automatically applied by their editor.</p>
<p>Without it, they have to find a contribution guide, style guide, or check other code manually to learn project conventions.</p>
<p>Even when the conventions are known, they may conflict with a developer's settings. Then they'll have to code against the editor's automatic formatting, or frequently change settings between projects.</p>
<p>This is especially useful for developers that jump between projects a lot. For example, open-source contributors frequently write code for projects across organizations that follow different coding conventions.</p>
<h2 id="heading-how-editorconfig-works">How EditorConfig Works</h2>
<p>EditorConfig uses a simple <a target="_blank" href="https://en.wikipedia.org/wiki/INI_file">INI</a>-like file named <code>.editorconfig</code>. This file declares rules that will be translated to settings in your editor, or perform formatting over your workspace.</p>
<p>For example, in my editor I use 2-space indentations for XML files, but a project I contribute to might prefer 4-space indentations.</p>
<pre><code class="lang-plaintext">[*.xml]
indent_size = 4
</code></pre>
<p>When I open the project, my editor will see the <code>.editorconfig</code> file, and override the settings to suit the project's conventions.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/1.png" alt="Instance of Visual Studio Code. There is an XML file on the left side which uses spaces as defined in the EditorConfig, but my default indentation size of 2." width="600" height="400" loading="lazy"></p>
<p><em>Writing an XML file with my default editor settings. I use spaces for indentation with a size of 2.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/2-1.png" alt="Instance of Visual Studio Code. The EditorConfig configuration includes an XML section that sets the indentation style to tab and size to 4. The XML file on the left is reformmated to reflect this change." width="600" height="400" loading="lazy"></p>
<p><em>Automatically reformatting the file after overriding the XML formatting settings.</em></p>
<h2 id="heading-how-to-use-editorconfig">How to Use EditorConfig</h2>
<p>Depending on your editor of choice, it may have native support for EditorConfig already. There is a list of "<a target="_blank" href="https://editorconfig.org/#pre-installed">No Plugin Necessary</a>" editors on the website, which includes JetBrains IDEs and Visual Studio.</p>
<p>If your editor doesn't have native support, you'll likely be able to add it with a plugin. Editors like Visual Studio Code and Eclipse support it this way, which can also be found on the EditorConfig website under "<a target="_blank" href="https://editorconfig.org/#download">Download a Plugin</a>".</p>
<p>Once installed, your editor should automatically find the EditorConfig file in your project if it exists, and start applying the rules.</p>
<h2 id="heading-how-to-define-rules-in-editorconfig">How to Define Rules in EditorConfig</h2>
<p>You can find a list of rules on the <a target="_blank" href="https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties">EditorConfig Wiki</a>. It contains all officially supported rules, as well as proposals for domain-specific rules that may be supported by certain implementations.</p>
<p>Not all implementations support every rule. This is especially true for domain-specific rules like <code>curly_bracket_next_line</code>. It can still be worth declaring these properties anyway for users that can utilize it, or to at least document the preference.</p>
<p>You must set <code>root</code> to <code>true</code> for the top level EditorConfig in the project, which is normally in the root of your project directory.</p>
<p>Additional EditorConfig files can be defined in nested directories, but shouldn't set <code>root</code> to <code>true</code>.</p>
<p>Then you can define a header that selects files, with rules for what to apply to matching files.</p>
<pre><code class="lang-plaintext"># Declares that this is the top-level configuration
root = true

# Applies to all files
[*]
indent_style = space
indent_size = 2

# Applies to all Markdown files
[*.md]
trim_trailing_whitespace = false

# Applies to all C# and Java files, overriding rules declared before
[*.{cs,java}]
indent_size = 4
</code></pre>
<p>There are no standard conventions for how to write an <code>.editorconfig</code> file, but there are two notable approaches you can take.</p>
<h3 id="heading-define-rules-per-project">Define Rules Per Project</h3>
<p>Just add to it as you need to. This means just defining rules, or appending file formats as your project grows.</p>
<p>You can start by generating the file with your editor, or just create a file named <code>.editorconfig</code> manually. You can copy-and-paste the <a target="_blank" href="https://editorconfig.org/#example-file">example</a> from the official website.</p>
<h3 id="heading-define-rules-for-all-projects">Define Rules for All Projects</h3>
<p>Alternatively, you can put together all of your preferences and plan the ideal configuration for all files you might interact with.</p>
<p>You can work from scratch, or start with mine and make the necessary adjustments.</p>
<pre><code class="lang-plaintext">root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
curly_bracket_next_line = false
spaces_around_operators = true

[*.bat]
end_of_line = crlf

[*.cs]
curly_bracket_next_line = true

[*.{cpp,cs,gradle,java,kt,py,rs}]
indent_size = 4

[*.{js,ts}]
quote_type = single

[*.md]
trim_trailing_whitespace = false

[*.tsv]
indent_style = tab
</code></pre>
<h2 id="heading-editorconfig-rule-recommendations">EditorConfig Rule Recommendations</h2>
<p>These are rules I'd objectively recommend declaring, if your project contains the respective file format. It'll help you avoid tedious issues that can occur due to a user's development environment.</p>
<h3 id="heading-batch">Batch</h3>
<p>Line endings need to have a textual representation when stored. This is usually something you wouldn't see or have to worry about.</p>
<p>However, different systems use different characters to represent the end of a line. (<a target="_blank" href="https://en.wikipedia.org/wiki/Newline#Representation">More Info</a>)</p>
<ul>
<li><p>Unix systems use a line feed. (<code>lf</code> or <code>\n</code>)</p>
</li>
<li><p>Windows uses a carriage return and line feed. (<code>crlf</code> or <code>\r\n</code>)</p>
</li>
</ul>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Batch_file">Batch</a> files can have unexpected behavior if they end with Unix line endings. You can avoid this by setting <code>end_of_line</code> to <code>crlf</code> to ensure they have Windows line endings instead. (<a target="_blank" href="https://serverfault.com/questions/429594/is-it-safe-to-write-batch-files-with-unix-line-endings">More Info</a>)</p>
<pre><code class="lang-plaintext">[*.bat]
end_of_line = crlf
</code></pre>
<h3 id="heading-markdown">Markdown</h3>
<p>In <a target="_blank" href="https://en.wikipedia.org/wiki/Markdown">Markdown</a>, you can write a line break in the current paragraph by adding 2 spaces at the end of a line. (<a target="_blank" href="https://en.wikipedia.org/wiki/Markdown#Example">More Info</a>)</p>
<p>You'll want to set <code>trim_trailing_whitespace</code> to <code>false</code> to avoid having your editor remove those spaces when you save.</p>
<pre><code class="lang-plaintext">[*.md]
trim_trailing_whitespace = false
</code></pre>
<h3 id="heading-tab-separated-values">Tab Separated Values</h3>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Tab-separated_values">TSV</a> (Tab Separated Values) files are very similar to <a target="_blank" href="https://en.wikipedia.org/wiki/Comma-separated_values">CSV</a> (Comma Separated Values), but use tabs instead of commas as the column delimiter.</p>
<p>It's very common for developers to have tabs automatically convert to spaces. You should set <code>indent_style</code> to <code>tab</code> to avoid the delimiter from being replaced, otherwise your entire table might become a single column.</p>
<pre><code class="lang-plaintext">[*.tsv]
indent_style = tab
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you're a maintainer, either working in a collaborative environment or in open-source, I strongly recommend adding an <code>.editorconfig</code> file defining the project's conventions to the root of your repository.</p>
<p>Maintainers can then spend more time reviewing clean pull requests that adhere to the style guide, as the editor will automatically start enforcing or applying the conventions.</p>
<p>Committers get a better experience, as the project will override their workspace settings. This reduces the need to reformat code or work against preconfigured editor settings.</p>
<p>And projects will be cleaner, as the conventions will be in a single vendor-agnostic file, rather than editor-specific files that only certain contributors can use anyway.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What are Bookmarklets? How to Use JavaScript to Make a Bookmarklet in Chromium and Firefox ]]>
                </title>
                <description>
                    <![CDATA[ Bookmarklets are browser bookmarks that execute JavaScript instead of opening a webpage. They're also known as bookmark applets, favlets, or JavaScript bookmarks. Bookmarklets are natively available in all major browsers, including Mozilla Firefox an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-are-bookmarklets/</link>
                <guid isPermaLink="false">66d460fa47a8245f78752ac7</guid>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google Chrome ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Firefox ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Thu, 17 Jun 2021 00:53:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/06/cover-defectivefox-o-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://en.wikipedia.org/wiki/Bookmarklet">Bookmarklets</a> are browser bookmarks that execute JavaScript instead of opening a webpage. They're also known as bookmark applets, favlets, or JavaScript bookmarks.</p>
<p>Bookmarklets are natively available in all major browsers, including Mozilla Firefox and Chromium-based browsers like Chrome or Brave.</p>
<h2 id="heading-scripting-with-javascript">Scripting with JavaScript</h2>
<p>Learning how to write scripts provides many benefits, namely the huge time-savings from automating repetitive or tedious tasks.</p>
<p>If you aren't a developer, the idea of learning to code might be intimidating, however scripting doesn't require software engineering knowledge or design patterns. The goal isn't to make scalable software, but rather to automate specialized or trivial tasks.</p>
<p>Regardless of profession, even if you've never written code before, consider what you do in your browser. If you ever feel what you do is repetitive or robotic, consider the possibility of delegating the task to an actual robot.</p>
<h2 id="heading-use-cases-for-bookmarklets">Use Cases for Bookmarklets</h2>
<p>With bookmarklets, you can manipulate the current page as the function will have the context of the current tab. This means you can:</p>
<ul>
<li><p>Click buttons virtually</p>
</li>
<li><p>Modify the content</p>
</li>
<li><p>Use the content of the page to open a new page</p>
</li>
<li><p>Remove elements from the page</p>
</li>
</ul>
<p>You can also make bookmarks that don't utilize the context at all, such as conditionally opening a URL, or generating HTML for a new tab.</p>
<p>You'll find some bookmarklets I made for this article in <a class="post-section-overview" href="#heading-example-bookmarklets">Example Bookmarklets</a>. They're just for demonstration, but should make the capabilities and implementations apparent.</p>
<h2 id="heading-how-to-create-bookmarklets">How to Create Bookmarklets</h2>
<p>Creating a bookmarklet is almost identical to creating a regular bookmark. The only difference is that you'll write JavaScript in the URL field instead of an HTTP/HTTPS URL.</p>
<h3 id="heading-navigate-to-the-bookmark-menu">Navigate to the Bookmark Menu</h3>
<h4 id="heading-mozilla-firefox">Mozilla Firefox</h4>
<p>Either in your bookmarks bar, or in the Bookmarks sidebar (<code>CTRL</code> + <code>B</code>), you can right-click, then click "Add Bookmark...":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/firefox-1.png" alt="The &quot;Add bookmark&quot; modal when creating a new bookmark in Firefox." width="600" height="400" loading="lazy"></p>
<h4 id="heading-chromium">Chromium</h4>
<p>You can right-click your bookmarks bar, then click "Add page...". Alternatively, you can go to your Bookmarks manager, then right-click and click "Add new bookmark":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/chromium.png" alt="The &quot;Edit bookmark&quot; modal when creating a new bookmark in Chromium." width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-write-a-bookmarklet">How to Write a Bookmarklet</h2>
<p>In the URL field of the bookmark modal, write a JavaScript function in the following format.</p>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Your code here!</span>
})();
</code></pre>
<p><code>javascript:</code> is the URL's protocol. This indicates that the browser should execute the bookmark as JavaScript.</p>
<p><code>(() =&gt; { })</code> defines an anonymous function (lambda). You should write the code you want to execute between the curly braces.</p>
<p><code>();</code> will execute the anonymous function you just created.</p>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  alert(<span class="hljs-string">'Hello, World!'</span>);
})();
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-147-1.png" alt="A browser alert with the message: &quot;Hello, World!&quot;" width="600" height="400" loading="lazy"></p>
<p>You can also make it generate HTML and open it as an HTML document:</p>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-string">'&lt;h1 style="color: white; background-color: black;"&gt;Hello, World!&lt;/h1&gt;'</span>;
})();
</code></pre>
<h3 id="heading-spacing-for-bookmarklets">Spacing for Bookmarklets</h3>
<p>Most browsers don't allow a multiline input field in the bookmark URL, so you'll usually have to make strict use of curly braces (<code>{</code> and <code>}</code>) and semi-colons (<code>;</code>) when writing bookmarklets. This is especially important when scoping conditional constructs (<code>if</code>/<code>for</code>/<code>while</code>).</p>
<p>Other than this, spacing doesn't matter. Don't be afraid to have a lot of code in one line because that's all you've got:</p>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {   <span class="hljs-keyword">const</span> documentHTML = <span class="hljs-built_in">document</span>.documentElement.outerHTML;   <span class="hljs-keyword">const</span> matches = documentHTML.matchAll(<span class="hljs-regexp">/[\w.+=~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*/g</span>);   <span class="hljs-keyword">const</span> flatMatches = <span class="hljs-built_in">Array</span>.from(matches).map(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item[<span class="hljs-number">0</span>]);   <span class="hljs-keyword">const</span> uniqueMatches = <span class="hljs-built_in">Array</span>.from(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>(flatMatches));      <span class="hljs-keyword">if</span> (uniqueMatches.length &gt; <span class="hljs-number">0</span>) {     <span class="hljs-keyword">const</span> result = uniqueMatches.join(<span class="hljs-string">'\n'</span>);     alert(result);   } <span class="hljs-keyword">else</span> {     alert(<span class="hljs-string">'No emails found!'</span>);   } })();
</code></pre>
<p>If your script is complex, it'll be easier to maintain your bookmarklet in a code editor like <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a>. You can copy and paste it over to your browser when it's ready.</p>
<h3 id="heading-how-to-interact-with-websites">How to Interact with Websites</h3>
<p>The most common thing you'd do with bookmarklets is manipulating or interacting with websites you have open.</p>
<h4 id="heading-the-global-document-object">The Global Document Object</h4>
<p>As the bookmarklet has the context of the page you're on, you have access to the <code>[document](https://developer.mozilla.org/en-US/docs/Web/API/Document)</code> object.</p>
<p>The ideal functions for selecting elements for our use case are:</p>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector"><code>querySelector</code></a> to select a single element by CSS selector.</p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll"><code>querySelectorAll</code></a> to select all matching elements by CSS selector.</p>
</li>
<li><p><code>[evaluate](https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate)</code> to select all matching elements by XPath.</p>
</li>
</ul>
<p>There are other functions like <code>[getElementById](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)</code> and <code>[getElementsByClassName](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName)</code>, but we want to avoid false-positives, so we'll always make a strict selection using multiple element attributes.</p>
<h4 id="heading-css-selectors-and-xpath">CSS Selectors and XPath</h4>
<p>If you're only selecting elements based on element names, IDs, classes, and other attributes, using a CSS selector will be simple and efficient.</p>
<p>CSS selectors are used to select elements in HTML documents to apply styles. If you're familiar with web development or CSS in general, then you already know how to use CSS selectors. (More Info: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors">MDN</a>, <a target="_blank" href="https://www.freecodecamp.org/news/css-selectors-cheat-sheet/">freeCodeCamp</a>)</p>
<p>If you need to match the text content of an element as well, then you'll have to use XPath instead.</p>
<p>XPath is used to traverse XML documents, it provides all the capabilities of CSS selectors and more, including comparing the content of elements or using a regular expression to match it. (More Info: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/XPath">MDN</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/XPath">Wikipedia</a>)</p>
<h4 id="heading-how-to-select-elements-from-the-webpage">How to Select Elements from the Webpage</h4>
<p>One of the most common uses for bookmarklets is manipulating webpages. To interact with, manipulate, or remove elements from the page, you'll always have to select the elements first.</p>
<ol>
<li><p>First open the browser development tools by pressing <code>F12</code>, or <code>CTRL</code> + <code>SHIFT</code> + <code>I</code>.</p>
</li>
<li><p>Click the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector">Inspector</a>/<a target="_blank" href="https://developer.chrome.com/docs/devtools/dom/">Elements</a> tab, which displays the full HTML document of the page you have open.</p>
</li>
<li><p>Use the element selector tool (<code>CTRL</code> + <code>SHIFT</code> + <code>C</code>) and click on the element you want to interact with. The document viewer will scroll to the element you clicked in the HTML document. You'll see the element ID, classes, and attributes.</p>
</li>
<li><p>Check if you're on the correct element. Elements can be nested where it's easier to navigate to it manually in the HTML. For example, you may have clicked an <code>svg</code> element, but actually needed the <code>button</code> or <code>div</code> it was inside of.</p>
</li>
<li><p>Define a CSS selector or XPath that matches everything you want, you might want to make it more strict than necessary to avoid potential false-positives.</p>
</li>
</ol>
<p>For example, suppose I wanted to dismiss all topic suggestions on Twitter because they're annoying. Here is how a clickable element to dismiss a topic looks like.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/Screen-Shot-2021-06-16-at-04.19.17.png" alt="Twitter topic suggestions, with an X button to mark it as &quot;Not interested&quot;." width="600" height="400" loading="lazy"></p>
<p><em>Twitter topic suggestions, with an X button to mark it as "Not interested".</em></p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Dismiss"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"..."</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- The parent div element has the click listener. --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"..."</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"..."</span>&gt;</span>
      <span class="hljs-comment">&lt;!-- The actual X icon. --&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>An appropriate selector is <code>div[aria-label=Dismiss][role=button]</code>.</p>
<p>We need to use the <code>querySelectorAll</code> function from <a class="post-section-overview" href="#heading-the-global-document-object">The Global Document Object</a>, then call the <code>[click](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click)</code> method to simulate a click.</p>
<p>A bookmarklet can be implemented to select every dismiss button, and trigger a click event to all of them with a 250ms interval.</p>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> selector = <span class="hljs-string">'div[aria-label=Dismiss][role=button]'</span>;
  <span class="hljs-keyword">const</span> topics = <span class="hljs-built_in">document</span>.querySelectorAll(selector);

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; topics.length; i++) {
    <span class="hljs-keyword">let</span> topic = topics[i];
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> topic.click(), i * <span class="hljs-number">250</span>);
  }
})();
</code></pre>
<h2 id="heading-how-to-redistribute-bookmarklets">How to Redistribute Bookmarklets</h2>
<p>To "install" a bookmarklet, users create a bookmark on their browser and copy and paste the code to it.</p>
<p>This can be inconvenient, so it's common to link bookmarklets when sharing. This is as simple as putting it in the <code>href</code> attribute of your link anchor.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"javascript: (() =&gt; {   alert('Hello, World!'); })();"</span>&gt;</span>
  Hello, World!
<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</code></pre>
<p>Now users can right-click and "Bookmark Link", or drag it to the bookmarks bar for easy access.</p>
<p>Clicking the link on the web page will execute the script immediately. Ensure it's not going to obstruct what a user is trying to achieve on your site if they accidentally click it.</p>
<p>For example, the following link will display an alert with "Hello, World!".</p>
<h3 id="heading-user-content-and-content-security-policy-bypass">User Content and Content Security Policy Bypass</h3>
<p>If you run a service that allows user-generated content to contain custom HTML, it's important to sanitize link anchors (<code>a</code>).</p>
<p>The bookmarklet is executing like code in the developer tools console, and bypasses the configured <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">Content Security Policy</a> (CSP).</p>
<p>The "Hello, World!" link can just as easily send data to another server, including the input of form fields, or cookies.</p>
<p>As a service provider, it's important to be wary that users can exploit this to share malicious code on your platform. If their link anchor is running on a page under your domain, it can access sensitive information on the page and <code>[document.cookies](https://developer.mozilla.org/en-US/docs/web/api/document/cookie)</code>.</p>
<p>You can try it yourself in a sandbox environment:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"javascript: (() =&gt; {   alert(document.cookie); })();"</span>&gt;</span>
  EvilScript
<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</code></pre>
<h3 id="heading-only-run-code-you-trust">Only Run Code You Trust</h3>
<p>As a user, it's important to note that any code can be malicious, only click or add bookmarklets where at least one of the following are true:</p>
<ul>
<li><p>It came from a reputable source.</p>
</li>
<li><p>You know JavaScript, and you reviewed what it does.</p>
</li>
<li><p>Someone you trust knows JavaScript, and they reviewed it for you.</p>
</li>
</ul>
<h2 id="heading-privacy-and-security">Privacy and Security</h2>
<p>Bookmarklets can be handy, but we also have <a target="_blank" href="https://en.wikipedia.org/wiki/Browser_extension">web extensions</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Userscript">user scripts</a> too. What makes them different?</p>
<p>Web extensions are incredibly user-friendly and flexible. Bookmarklets can't block network requests, update content as the page changes, or manage tabs.</p>
<p>However, there're some benefits to using bookmarklets over anything else, namely for privacy and security.</p>
<p>An extension that modifies the font on all pages must get permission to access all data on all web pages. On Firefox and Chrome, this includes all input and password fields. (More Info: <a target="_blank" href="https://support.mozilla.org/kb/permission-request-messages-firefox-extensions#w_access-your-data-for-all-websites">Mozilla</a>, <a target="_blank" href="https://developer.chrome.com/docs/extensions/mv3/permission_warnings/#permissions_with_warnings">Google</a>)</p>
<p>In contrast, a bookmarklet only has access to the page for the very moment it's executing, and only when manually triggered by the user.</p>
<p>This results in less risk of malware, a rogue employee can't push a malicious update, and data won't silently get sent to other servers.</p>
<p>The Chrome Web Store has previously had several malicious extensions which had to be taken down. Some of which had millions of installations before being removed. (<a target="_blank" href="https://en.wikipedia.org/wiki/Chrome_Web_Store#Malware">More Info</a>)</p>
<h2 id="heading-example-bookmarklets">Example Bookmarklets</h2>
<p>Here's a list of bookmarklet ideas, along with the code that implements it. You can copy and paste them into new bookmarks to try them out.</p>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> documentHTML = <span class="hljs-built_in">document</span>.documentElement.outerHTML;
  <span class="hljs-keyword">const</span> matches = documentHTML.matchAll(<span class="hljs-regexp">/[\w.+=~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*/g</span>);
  <span class="hljs-keyword">const</span> flatMatches = <span class="hljs-built_in">Array</span>.from(matches).map(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item[<span class="hljs-number">0</span>]);
  <span class="hljs-keyword">const</span> uniqueMatches = <span class="hljs-built_in">Array</span>.from(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>(flatMatches));

  <span class="hljs-keyword">if</span> (uniqueMatches.length &gt; <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">const</span> result = uniqueMatches.join(<span class="hljs-string">'\n'</span>);
    alert(result);
  } <span class="hljs-keyword">else</span> {
    alert(<span class="hljs-string">'No emails found!'</span>);
  }
})();
</code></pre>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> xpath = <span class="hljs-string">"//a [contains(., 'Jobs') or contains(., 'Careers') or contains(., 'Hiring')]"</span>;
  <span class="hljs-keyword">const</span> elements = <span class="hljs-built_in">document</span>.evaluate(xpath, <span class="hljs-built_in">document</span>);
  <span class="hljs-keyword">const</span> element = elements.iterateNext();

  <span class="hljs-keyword">if</span> (element) {
    element.click();
  } <span class="hljs-keyword">else</span> {
    alert(<span class="hljs-string">'No links for jobs found!'</span>);
  }
})();
</code></pre>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> allElements = <span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string">'*'</span>);

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> element <span class="hljs-keyword">of</span> allElements) {
    element.style.fontFamily = <span class="hljs-string">'Comic Sans MS'</span>;
  }
})();
</code></pre>
<pre><code class="lang-js">javascript: (<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> destination = <span class="hljs-string">"https://www.freecodecamp.org/"</span>;
  <span class="hljs-keyword">const</span> alternate = <span class="hljs-string">"https://tenor.com/Y6jj.gif"</span>;

  <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
  <span class="hljs-keyword">const</span> hours = date.getHours();

  <span class="hljs-keyword">if</span> (hours &lt; <span class="hljs-number">3</span> || hours &gt;= <span class="hljs-number">6</span>) {
    <span class="hljs-built_in">window</span>.open(destination);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">window</span>.open(alternate);
  }
})();
</code></pre>
<p>Thank you for reading! Now go forth and create your own bookmarklets.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Schofield's Laws of Computing – What they Are and Why You Should Know Them ]]>
                </title>
                <description>
                    <![CDATA[ Schofield's Laws of Computing are principles that anyone who works with computers should know. They're focused on data portability, integrity, and security. Jack Schofield was a prolific journalist who wrote for The Guardian and covered technology fo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/schofields-laws-of-computing/</link>
                <guid isPermaLink="false">66d460f651f567b42d9f84af</guid>
                
                    <category>
                        <![CDATA[ Application Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #infosec ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Thu, 03 Jun 2021 18:46:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/schofield-cover-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Schofield's Laws of Computing are principles that anyone who works with computers should know. They're focused on data portability, integrity, and security.</p>
<p><a target="_blank" href="https://wikipedia.org/wiki/Jack_Schofield_(journalist)">Jack Schofield</a> was a prolific journalist who wrote for The Guardian and covered technology for nearly four decades. During that time, he wrote three particular articles called "Schofield's Laws of Computing".</p>
<p>Jack didn't create these principles all at once, but they were rather an accumulation of "discoveries" that he had encountered throughout his career.</p>
<p>Individually, the principles aren't special or revolutionary – in fact, they're pretty basic. However, they're valuable lessons that you should adhere to, especially in an organizational setting.</p>
<h2 id="heading-schofields-first-law-of-computing">Schofield's First Law of Computing</h2>
<blockquote>
<p>"Never put data into a program unless you can see exactly how to get it out." ― <a target="_blank" href="https://www.theguardian.com/technology/2003/jul/24/onlinesupplement.columnists">Jack Schofield</a> (2003)</p>
</blockquote>
<p>Schofield's First Law states that when you depend on an organization, you should verify that it'll be easy to move your data to another organization.</p>
<p>Common reasons you might want to change providers could be:</p>
<ul>
<li><p>A change in the terms of service.</p>
</li>
<li><p>Another company with a different vision takes it over.</p>
</li>
<li><p>Price hikes or a shift to a less favorable business model.</p>
</li>
<li><p>The service shuts down, or software becomes abandonware.</p>
</li>
</ul>
<p>For example:</p>
<ul>
<li><p>LastPass limiting free users to one type of device. (<a target="_blank" href="https://wikipedia.org/wiki/LastPass#Reception">More Info</a>)</p>
</li>
<li><p>ArtStation getting acquired by Epic Games. (<a target="_blank" href="https://wikipedia.org/wiki/Epic_Games#Acquisitions">More Info</a>)</p>
</li>
<li><p>Adobe shifting to a software as a service business model. (<a target="_blank" href="https://wikipedia.org/wiki/Adobe_Creative_Cloud#Criticism">More Info</a>)</p>
</li>
<li><p>Megaupload shutdown and seized by governing bodies. (<a target="_blank" href="https://wikipedia.org/wiki/Megaupload#2012_indictments_by_the_United_States">More Info</a>)</p>
</li>
</ul>
<p>Data portability is an essential feature for software and services. It's the primary solution when you need to avoid vendor lock-ins or must budget for costly migration processes.</p>
<h3 id="heading-what-are-vendor-lock-ins">What are Vendor Lock-ins?</h3>
<p>Vendor lock-ins are when companies tie users down to their software. They can put practices in place to add friction when migrating to competing software.</p>
<p>The aim is to compel users to stay, even if there are better options for them, by making steps to leave inconvenient, time-consuming, or tedious.</p>
<p>When you're choosing software or services to use, you'll want to keep an eye out for such practices. This can come in a variety of forms:</p>
<ul>
<li><p>Not allowing you to export personal data or user-generated content.</p>
</li>
<li><p>Not allowing files to be exported to open or human-readable formats.</p>
</li>
<li><p>Making software incompatible with existing open-standards.</p>
</li>
</ul>
<h3 id="heading-the-right-to-data-portability">The Right to Data Portability</h3>
<p>The <a target="_blank" href="https://wikipedia.org/wiki/General_Data_Protection_Regulation">General Data Protection Regulation</a> (GDPR) has helped with this. It's led companies like Discord, Instagram, and Twitter to add automated tools for users to export their content.</p>
<p>Article 20 of GDPR is the "right to data portability", which is the right to have the means to move your personal data from a data controller to a standard format that you can give to another data controller.</p>
<p>Despite the fact that GDPR is specific to personal data, this has promoted data portability in general, including user-generated content. While it's debatable how easy it is to enforce GDPR outside the EU, these tools are usually accessible to members of other jurisdictions, too.</p>
<p>If you're representing an organization or a freelancer and you're in charge of picking software, keep this in mind!</p>
<h2 id="heading-schofields-second-law-of-computing">Schofield's Second Law of Computing</h2>
<blockquote>
<p>"Data doesn't really exist unless you have at least two copies of it."<br>― <a target="_blank" href="https://www.theguardian.com/technology/2008/feb/14/email.yahoo">Jack Schofield</a> (2008)</p>
</blockquote>
<p>Backing up data is a chore that most individuals procrastinate until it's too late. But fortunately organizations have proven to be a bit more mature with this.</p>
<p>Schofield's Second Law of Computing suggests that unless you have <em>at least</em> 2 copies of your data, you should treat it like it doesn't exist.</p>
<p>Ideally, you should keep both copies in different physical locations – and by that, I don't mean different drives, but ideally different countries or continents.</p>
<p>For data in your possession, such as your desktop, laptop, or flash drives:</p>
<ul>
<li><p>Devices or your whole inventory could get lost or stolen.</p>
</li>
<li><p>If you have full-disk encryption, you could forget your password.</p>
</li>
<li><p>Your hardware may fail on you, resulting in data loss.</p>
</li>
<li><p>Disasters such as fires or floods may destroy everything on-premise.</p>
</li>
</ul>
<p>It could even be due to user-error. No matter how technical you are, you could "Overwrite" instead of "Save As", flash an operating system to the wrong drive, or a developer might forcefully push to the wrong branch after amending a commit.</p>
<p>You should always be prepared for the scenario that may lead to loss of data. While not everyone has disposable income lying around, physical goods are generally easy to replace with enough money, potentially years worth of accumulated data is irrecoverable.</p>
<h3 id="heading-data-in-the-cloud">Data in the Cloud</h3>
<p>Schofield's Second Law doesn't only target data in your possession, but also data you keep in the cloud. For example, you should store your cloud storage, emails, and media content in a second location as well.</p>
<p>This is especially important when using services that don't take responsibility for backing up your data, or close your account after a period of inactivity. This is common with companies that provide truly free services, free of cost and free of tracking, like Nextcloud providers or Tutanota.</p>
<p>Don't assume your data is safe just because it's in the cloud. A recent example of this is the fire that started in one of OVH's datacenters resulting in the loss of data. OVH Public Cloud provides unmanaged servers, which means the user is responsible for managing and backing up their servers. (<a target="_blank" href="https://wikipedia.org/wiki/OVHcloud#Incidents">More Info</a>)</p>
<p>There is also the risk of vulnerabilities that allow unauthorized access to your account.</p>
<p>For example, last year hackers obtained access to Twitter's administrative tools which granted them access to many high-profile accounts. Using such tools, it would've been just as easy to delete previous posts and media. (<a target="_blank" href="https://wikipedia.org/wiki/2020_Twitter_account_hijacking">More Info</a>)</p>
<h3 id="heading-sync-your-data">Sync Your Data</h3>
<p>You can solve some of these problems by using solutions that sync your data between your computer and a server. This offers protection from any hardware related failures, or physical damage.</p>
<p>Data that would have detrimental consequences if lost should be encrypted and synced to cloud storage. Some software like Bitwarden or Thunderbird natively rely on syncing as well, so even if the server were to disappear, you'll still have a recent copy on your device.</p>
<p>However, syncing doesn't solve all problems – it's ideal to have an isolated backup as well. Syncing will automatically send all changes, including user-errors, or even changes made by malware or ransomware. Having regular cold storage backups would be handy for cases like this.</p>
<h2 id="heading-schofields-third-law-of-computing">Schofield's Third Law of Computing</h2>
<blockquote>
<p>"The easier it is for you to access your data, the easier it is for someone else to access your data." ― <a target="_blank" href="https://www.theguardian.com/technology/2008/jul/10/it.security">Jack Schofield</a> (2008)</p>
</blockquote>
<p>Protecting data has always involved finding a balance between security and convenience. We want data to be easy to access for us, but hard to access for others.</p>
<p>This conflict has led to issues regarding data negligence.</p>
<p>When you put data on the cloud, you automatically make it easier for others to access. Your cloud provider could have vulnerabilities, someone might guess your password, or an employee could go rouge and compromise or sell your data.</p>
<p>You might be able to blame someone or get compensation for the incident, but your data and potentially your clients' data is still out there, and you'd be the one who ultimately allowed it to happen.</p>
<p>Increasing security tends to be inconvenient, but these are the inconveniences that others bet on when looking to compromise accounts:</p>
<ul>
<li><p><a target="_blank" href="https://wikipedia.org/wiki/Brute-force_attack">Brute-force Attacks</a> – Bet on short passwords, as it's quicker to type.</p>
</li>
<li><p><a target="_blank" href="https://wikipedia.org/wiki/Credential_stuffing">Credential Stuffing</a> – Bet on password reuse, as it's more convenient than managing multiple.</p>
</li>
<li><p><a target="_blank" href="https://wikipedia.org/wiki/Dictionary_attack">Dictionary Attacks</a> – Bet on logical passwords, as it's easier to recall.</p>
</li>
</ul>
<p>Furthermore, these attacks rely on users not enabling 2FA, and that the data on the other side isn't obfuscated or encrypted.</p>
<p>You or your organization should be using a password manager, enforcing 2FA on all systems, and where possible encrypting data before it's sent to third-party servers.</p>
<p>Even better, remove data that is no longer relevant. It's always better to erase data than to worry about protecting it.</p>
<p>This might include chat histories, emails, or files that contain confidential information, social media passwords, and client or employee data. Especially if they're months or years old and no longer relevant. If you don't need them, nobody else does either.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>These principles were established over 10 years ago, and apply more today than ever before.</p>
<p>Technology and open-standards have evolved, so they are easier to adhere to. But with the growth of cloud infrastructure, we're increasingly trusting third-parties with our data. In many cases, we may be too comfortable with where it's being left and who has access to it.</p>
<p>Unfortunately, Jack Schofield died in March 2020, but he supported many in the tech community. I hope through sharing his experiences, others may continue to learn from them.</p>
<h2 id="heading-meta">Meta</h2>
<p>This article was discussed on The Hedge, a technology and business podcast led by network engineers. I recommend giving it a listen if you enjoyed this, as their input and real-world experience add a lot of value to the topic.</p>
<p><a target="_blank" href="https://rule11.tech/hedge-116/">Embedded content</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Commit Signing in Git? ]]>
                </title>
                <description>
                    <![CDATA[ Git has a feature to "sign" commits, but what is signing, and what are the benefits? TL;DR: If you don't care for the details, and just need to get commit signing setup quickly, skip to How to Sign Commits. Signing, or code signing specifically, is t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-commit-signing-in-git/</link>
                <guid isPermaLink="false">66d460fc51f567b42d9f84bc</guid>
                
                    <category>
                        <![CDATA[ Cryptography ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Seth Falco ]]>
                </dc:creator>
                <pubDate>Wed, 02 Jun 2021 23:14:01 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/cover-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://git-scm.com/">Git</a> has a feature to "sign" commits, but what is signing, and what are the benefits?</p>
<p><strong>TL;DR:</strong> If you don't care for the details, and just need to get commit signing setup quickly, skip to <a class="post-section-overview" href="#heading-how-to-sign-commits-in-git">How to Sign Commits</a>.</p>
<p>Signing, or code signing specifically, is the process of using cryptography to digitally add a signature to data. The receiver of the data can verify that the signature is authentic, and therefore must've come from the signatory.</p>
<p>It's like physical signatures, but digital and more reliable.</p>
<h1 id="heading-gits-default-behavior">Git's Default Behavior</h1>
<p>First let's note that all commits have the following properties:</p>
<ul>
<li><p>Author – The contributor who did the work, this is <em>informational.</em></p>
</li>
<li><p>Committer – The user who committed the change.</p>
</li>
</ul>
<p>In most cases, these will be the same, but they can be overridden when committing, so it's important to note the difference.</p>
<p>When you first installed Git, you probably had to configure a few settings, namely <code>user.email</code> and <code>user.name</code>. This may've been handled for you depending on your Git client.</p>
<p>In the command line, this requires executing the following commands:</p>
<pre><code class="lang-shell">git config --global user.email "seth@example.org"
git config --global user.name "Seth Falco"
</code></pre>
<p>Git commits are trust-based, so it'll assume you put in your real email and name. You can then commit and push to remote providers like GitHub and GitLab with the details provided.</p>
<p>What happens when someone else uses your email address, and then pushes changes remotely?</p>
<pre><code class="lang-shell">git config --global user.email "seth@example.org"
git commit -m "Jen did this."
git push origin main
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-1-c.png" alt="Jen made a commit, but it shows my name and links to my GitHub profile." width="600" height="400" loading="lazy"></p>
<p>The result looks normal, but I'm not the one who did this commit. Jen committed to her repository, authenticating with her GitHub credentials, but it's showing my name and linking to my profile. The default behavior sets both the author and committer to the details in <code>git config</code>.</p>
<p>On GitHub, the commit is already indistinguishable from my own. If a user set both <code>user.email</code> and <code>user.name</code> to mine, which they can get from doing <code>git log</code> on any of my commits, then even locally it'd look the same.</p>
<p>This means that anyone can set their <code>user.email</code> to your email address, and it'd look like you made the commit.</p>
<h1 id="heading-why-does-git-do-this">Why Does Git Do This?</h1>
<p>You might wonder why this is possible. You authenticate to your account when you push to the repository after all, shouldn't it use that email? Doesn't this seem a bit flawed?</p>
<p>When you authenticate to push to remote repositories, you're authenticating to do just that– push changes. The commits don't require authentication regardless of who authored or committed them.</p>
<p>If commits required authentication by default, it'd be impossible to migrate or mirror projects to other platforms. The commit history will include former employees, dead users, inactive accounts, or email addresses that aren't on other platforms.</p>
<p>The only solution would be to rewrite the history to remove that they ever worked on the project, which isn't ideal.</p>
<p>Another scenario would be if I forked a project on GitHub, but want to maintain my fork on GitLab. My first push would include all commits from previous committers. For a large project, it's not feasible to authenticate every committer.</p>
<p>The author of a commit signifies attribution for who did the work, not proof of who did the work.</p>
<p>In fact, you can always override the author when committing just for this purpose. Using the <code>--author</code> argument, you can specify a different name and email to your global settings, even details that aren't associated with an account where the repository is hosted.</p>
<p>On public repositories, be mindful when committing on behalf of someone without an account, though. Names and email addresses become public information once pushed, and are accessible to anyone using <code>git log</code>!</p>
<pre><code class="lang-shell">git commit -m "Jen didn't even author this." --author "Jen &lt;jen@example.org&gt;"
git push origin main
</code></pre>
<p>This has different behavior than using another email in <code>git config</code>. This makes the author what we specified in <code>--author</code>, but the committer what we specified in <code>git config</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-2-c.png" alt="GitHub displays that Jen is the author and that I am the committer." width="600" height="400" loading="lazy"></p>
<p>Translation platforms like <a target="_blank" href="https://weblate.org/">Weblate</a> rely on this feature to ensure translators still get attribution, even though an automated user commits and opens the pull requests, not the translator.</p>
<h1 id="heading-how-to-prove-youre-the-committer-in-git">How to Prove You're the Committer in Git</h1>
<p><a target="_blank" href="https://gnupg.org/">GNU Privacy Guard</a> (GnuPG or GPG) allows you to create cryptographic asymmetric key pairs that can be used for the encryption and signing of data. They consist of a public and private key.</p>
<p>You can share the public-key with anyone – you may upload this to your GitHub and GitLab accounts, or put it on the internet for anyone to access.</p>
<p>The private-key, as the name suggests, is private. You should treat this like a password, and under no circumstances should you ever share your private-key with anyone.</p>
<p>We'll be generating a key pair, and then uploading the public key to GitHub and GitLab. Using your private-key, you can sign your commits, and servers with the public key will use it to confirm it was really you.</p>
<h1 id="heading-how-to-sign-commits-in-git">How to Sign Commits in Git</h1>
<p>I'll only cover how to do this in the terminal, since this provides a uniform experience across operating systems. If you're uncomfortable with the terminal, you pretty much just have to copy the commands.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>The only prerequisite, other than Git itself, is to install the GPG command-line utility.</p>
<p>You can verify if it's installed with <code>gpg --version</code>.</p>
<h3 id="heading-windows">Windows</h3>
<h4 id="heading-git-bash">Git BASH</h4>
<p>If you have Git BASH installed (optionally bundled with <a target="_blank" href="https://gitforwindows.org/">Git for Windows</a>), then you already have access to GPG. Just launch an instance of Git BASH, and it'll be available immediately.</p>
<h4 id="heading-gpg4win">Gpg4win</h4>
<p>If you don't have Git BASH, then there's no need to install it. You can install <a target="_blank" href="https://gpg4win.org/download.html">Gpg4win</a>, which will provide GPG globally, so you can just use it from PowerShell.</p>
<p>When installing Gpg4win, you can untick all the additional components, as we won't be needing them since we plan to use the terminal.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-3-1.png" alt="The Choose Components screen on Gpg4win Setup with all additional components unchecked." width="600" height="400" loading="lazy"></p>
<p>If you already had PowerShell open, you'll have to restart it before you can use GPG.</p>
<h3 id="heading-linux">Linux</h3>
<p>Your distribution most likely already includes GPG. If not, then you can install it through your package manager.</p>
<h4 id="heading-apt-debian-ubuntu">apt (Debian / Ubuntu)</h4>
<p><code>sudo apt install gnupg</code></p>
<h4 id="heading-pacman-arch-manjaro">pacman (Arch / Manjaro)</h4>
<p><code>sudo pacman -S gnupg</code></p>
<h2 id="heading-how-to-generate-gpg-keys">How to Generate GPG Keys</h2>
<p>If you already have a GPG key, you can skip this step. It's perfectly fine to reuse GPG keys. Just read below and verify that your key is compatible with Git and GitHub.</p>
<p>You can get a list of your GPG keys with:</p>
<pre><code class="lang-shell">gpg --list-keys
</code></pre>
<p>First we need to generate an RSA key pair. The following will start an interactive script that will ask questions so we can provide the necessary information.</p>
<pre><code class="lang-shell">gpg --full-gen-key
</code></pre>
<ol>
<li><p>For what kind of key you want, input <code>1</code> which is "RSA and RSA".</p>
</li>
<li><p>For key size, input <code>4096</code>. This is the minimum size for GitHub and GitLab, and the maximum size GPG will let us generate.</p>
</li>
<li><p>For how long the key should last, use whatever suits you. The default is <code>0</code>, which means to never expire.</p>
</li>
<li><p>Verify the information is correct by inputting <code>y</code>.</p>
</li>
</ol>
<p>GPG will ask for personal information which is stored in your key.</p>
<ol>
<li><p>Your name, this can be anything at least 5 characters in length.</p>
</li>
<li><p>Your email address, use an email you plan to commit with. You must've verified this email on the remote account you'll push with.</p>
</li>
<li><p>A comment, you can type whatever, or press enter to leave it blank.</p>
</li>
<li><p>Verify the information is correct by inputting <code>o</code>.</p>
</li>
</ol>
<pre><code class="lang-plaintext">root@799d1cc3c99c:/# gpg --full-gen-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      &lt;n&gt;  = key expires in n days
      &lt;n&gt;w = key expires in n weeks
      &lt;n&gt;m = key expires in n months
      &lt;n&gt;y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Seth Falco
Email address: seth@example.org
Comment: 
You selected this USER-ID:
    "Seth Falco &lt;seth@example.org&gt;"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
</code></pre>
<p>GPG will ask for a passphrase to protect the key. You can set this to anything, or leave it blank for no passphrase at all. Of course, it's ideal to use a good passphrase, rely on your password manager if you use one.</p>
<p>The password prompt is environment-dependent, so this step will look different for different users, but what it's asking is effectively the same.</p>
<p>It'll start generating the key, which requires a lot of randomly generated data. Performing actions on your PC will help make it more random, so I'd recommend moving your mouse around while the key is generating.</p>
<h2 id="heading-how-to-export-your-keys">How to Export Your Keys</h2>
<p>Next you need to get the identifier of the newly generated key so we can refer to it when exporting your key and configuring Git.</p>
<p>GPG keys can be referred to in multiple ways. It's a good a habit to use and share the full fingerprint, to minimize the risk of ambiguity when users request it from a key server. Long (64-bit) IDs are fine <em>for now</em>, but short (32-bit) IDs are best avoided, as it's easy to produce a collision. (<a target="_blank" href="https://evil32.com/">More Info</a>)</p>
<p>We'll be using the full GPG fingerprint, which we can get with the command:</p>
<pre><code class="lang-shell">gpg --list-keys
</code></pre>
<p>You'll get output like the following:</p>
<pre><code class="lang-shell">pub   rsa4096 2021-05-23 [SC]
      C6656513A0F9B7B7F4E76389EF39187D04795745
uid           [ultimate] Seth Falco &lt;seth@example.org&gt;
sub   rsa4096 2021-05-23 [E]
</code></pre>
<p>For me, it's <code>C6656513A0F9B7B7F4E76389EF39187D04795745</code>. Make sure to use your fingerprint instead of mine when you do the rest of the commands.</p>
<p>You need to export the public-key so you can upload it to GitHub. We use the <code>--armor</code> argument to indicate that we want to export it in an <a target="_blank" href="https://en.wikipedia.org/wiki/Binary-to-text_encoding">ASCII armored</a> format instead of binary. This writes the public-key to a file named <code>gpg-key.pub</code>.</p>
<pre><code class="lang-shell">gpg --export --armor C6656513A0F9B7B7F4E76389EF39187D04795745 &gt; ./gpg-key.pub
</code></pre>
<h3 id="heading-how-to-back-up-your-keys">How to Back Up Your Keys</h3>
<p>It's worth having a remote backup of your GPG keys because you'll likely use them across services. If you lose it, it'd be a pain to have to update everything.</p>
<p>You can export your private-key in the same way we exported the public-key, this writes the private-key to a file named <code>gpg-key.asc</code>:</p>
<pre><code class="lang-shell">gpg --export-secret-keys --armor C6656513A0F9B7B7F4E76389EF39187D04795745 &gt; ./gpg-key.asc
</code></pre>
<p>You can now back up both your public and private keys, but remember that you should never send the non-encrypted copy of the private-key to the cloud. Always use end-to-end encrypted cloud storage, or a password manager like <a target="_blank" href="https://bitwarden.com/">Bitwarden</a> to back up sensitive data.</p>
<h2 id="heading-how-to-enable-commit-signing">How to Enable Commit Signing</h2>
<p>Then to enable signing all commits, set the <code>commit.gpgsign</code> setting using <code>git config</code>. This will make <code>git commit</code> sign commits by default.</p>
<pre><code class="lang-shell">git config --global commit.gpgsign true
</code></pre>
<p>If you have multiple GPG keys, or just for future reference, you may want to set <code>user.signingkey</code> as well. This will indicate specifically which key Git should use for signing to avoid ambiguity.</p>
<pre><code class="lang-shell">git config --global user.signingkey C6656513A0F9B7B7F4E76389EF39187D04795745
</code></pre>
<h2 id="heading-how-to-use-your-key">How to Use your Key</h2>
<p>Finally, you have to upload your public key. You can use the same GPG key for both GitHub and GitLab, or any other Git provider.</p>
<p>We'll need the exported public-key for the following steps, so open the <code>gpg-key.pub</code> file in any editor like Visual Studio Code, and copy the contents to your clipboard.</p>
<p>On GitHub, you can go to your <a target="_blank" href="https://github.com/settings/profile">settings</a>, under "<a target="_blank" href="https://github.com/settings/keys">SSH and GPG keys</a>", then click "<a target="_blank" href="https://github.com/settings/gpg/new">New GPG key</a>". Paste the contents of <code>gpg-key.pub</code> into the Key field on GitHub, and click "Add GPG key".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-4-c-1.png" alt="Adding a GPG key in the GitHub settings." width="600" height="400" loading="lazy"></p>
<p>On GitLab, the steps are almost identical, just go to your <a target="_blank" href="https://gitlab.com/-/profile/preferences">preferences</a>, then "<a target="_blank" href="https://gitlab.com/-/profile/gpg_keys">GPG Keys</a>". Paste the contents of <code>gpg-key.pub</code> into the Key field on GitLab, and click "Add key".</p>
<p>Now you're able to make signed commits to your repositories! The next commit will prompt for your GPG key password, since it's the first time using it. Subsequent commits will be seamless.</p>
<h1 id="heading-how-to-verify-commits-in-git">How to Verify Commits in Git</h1>
<p>GitHub and GitLab will show a "Verified" badge next to your new commits.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-5-c.png" alt="A signed commit on GitHub, it shows a verified badge on the side." width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-6-c-2.png" alt="A signed commit on GitLab, it shows a verified badge on the side." width="600" height="400" loading="lazy"></p>
<p>The final thing to remember is that commit signing will only verify the committer, not the author. That means when you see a verified commit, the author has nothing to do with the verified status.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-7-c-1.png" alt="A signed commit with the verified badge, but Jen didn't author this commit." width="600" height="400" loading="lazy"></p>
<h2 id="heading-vigilant-mode">Vigilant Mode</h2>
<p>As a bonus, on GitHub specifically there is a setting called <a target="_blank" href="https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits">vigilant mode</a>.</p>
<p>You can optionally enable this if you want all unsigned commits to explicitly say "Unverified". This can be enabled in your <a target="_blank" href="https://github.com/settings/profile">settings</a>, under "<a target="_blank" href="https://github.com/settings/keys">SSH and GPG keys</a>", then tick "Flag unsigned commits as unverified".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-8-c-2.png" alt="The vigilant mode setting on GitHub." width="600" height="400" loading="lazy"></p>
<p>Now the commit that Jen did with my email address shows "Unverified" next to it, to indicate that it wasn't signed with a key associated with my account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/figure-9-c.png" alt="The commit that Jen did with my details earlier, now showing an unverified badge next to it." width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
