<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Ian&#39;s Blog on Ian&#39;s blog</title>
		<link>/</link>
		<description>Recent content in Ian&#39;s Blog on Ian&#39;s blog</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
			<lastBuildDate>Wed, 26 Apr 2023 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Notes on Web Performance</title>
				<link>/blog/15-webperf/</link>
				<pubDate>Wed, 26 Apr 2023 00:00:00 +0000</pubDate>
				<guid>/blog/15-webperf/</guid>
				<description>&lt;p&gt;There are 2 main things that affect the performance of network-based&#xA;applications.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Bandwidth&lt;/li&gt;&#xA;&lt;li&gt;Latency&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;In an ideal world, the latency is low and bandwidth is high.&lt;/p&gt;&#xA;&lt;p&gt;Bandwidth problems become more important when the things being sent over the&#xA;network are large files ie: &amp;gt;1MB. Latency issues become more important when the&#xA;things being sent become smaller/require realtime feedback ie: &amp;lt; 100kb.&lt;/p&gt;&#xA;&lt;p&gt;Reducing page size &amp;amp; The time to first byte can be critical if you want to&#xA;target users on high latency, low bandwidth environments.&lt;/p&gt;</description>
					<content:encoded><![CDATA[<p>There are 2 main things that affect the performance of network-based
applications.</p>
<ol>
<li>Bandwidth</li>
<li>Latency</li>
</ol>
<p>In an ideal world, the latency is low and bandwidth is high.</p>
<p>Bandwidth problems become more important when the things being sent over the
network are large files ie: &gt;1MB. Latency issues become more important when the
things being sent become smaller/require realtime feedback ie: &lt; 100kb.</p>
<p>Reducing page size &amp; The time to first byte can be critical if you want to
target users on high latency, low bandwidth environments.</p>
<h3 id="the-jevons-paradox-faster-sites-report-slower-loads">The Jevons Paradox: Faster sites report slower loads</h3>
<p>Back in 2008, the youtube website was around 1MB. The developers weren&rsquo;t happy
with that and created The
<a href="https://blog.youtube/news-and-events/introducing-feather-lighter-way-to/">Youtube Feather Project</a>
to reduce the page size. The prototype with limited features was made in 3 days
and weighed around 98KB.</p>
<p>They did an A/B test with a few users for 1 week. After collecting and analyzing
the data the developers were confused. The page latency increased under Feather.</p>
<p>The reason? Geography.</p>
<blockquote>
<p>When we plotted the data geographically and compared it to our total numbers
broken out by region, there was a disproportionate increase in traffic from
places like <strong>Southeast Asia</strong>, <strong>South America</strong>, <strong>Africa</strong>, and even remote
regions of <strong>Siberia</strong>. Further investigation revealed that, in these places,
the average page load time under Feather was over <strong>TWO MINUTES</strong>! This meant
that a regular video page, at over a megabyte, was taking more than <strong>TWENTY
MINUTES</strong> to load! This was the penalty incurred before the video stream even
had a chance to show the first frame. Correspondingly, entire populations of
people simply could not use YouTube because it took too long to see anything.
Under Feather, despite it taking over two minutes to get to the first frame of
video, watching a video actually became a real possibility. Over the week,
word of Feather had spread in these areas and our numbers were completely
skewed as a result.</p>
</blockquote>
<p>You can find the full post at
<a href="https://blog.chriszacharias.com/page-weight-matters">Page Weight Matters</a></p>
<p>The irony of making something faster but analytics reports slower loads is very
interesting. The general term for it is
<a href="https://en.wikipedia.org/wiki/Jevons_paradox">the Jevons Paradox</a> and it
applies to many things eg: Website loading speed, electricity consumption <em>etc</em>.</p>
<p>I also found it interesting that Youtube Feather and
<a href="https://en.wikipedia.org/wiki/SPDY">SPDY</a> <em>(the predecessor to http2)</em> were
announced at around the same time.</p>
<p>I guess this is why milisecond improvements in page loads can increase revenue.</p>
<h2 id="reducing-bandwidth">Reducing Bandwidth</h2>
<h3 id="lossless-compression">Lossless compression</h3>
<p>Lossless compression is great for text based content and is the obvious low
hanging fruit when looking at reducing bandwidth.</p>
<p>Here&rsquo;s a chart showing how brotli (a compression format) was used to improve
load speed and save bandwidth.</p>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1639709501556416512_J84nnrJO.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1639709501556416512/J84nnrJO.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1639709501556416512/J84nnrJO.jpg"
    data-zoom-src="/twitter/media/profile-photos/1639709501556416512_J84nnrJO.jpeg"
    data-full_size="/twitter/media/profile-photos/1639709501556416512_J84nnrJO.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/addyosmani">
    <span>Addy Osmani</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@addyosmani</span>
  

  
  <div class="date-compact">· Oct 28 2017</div>


  </div>

  <div class="content">





  







  
  
  









<p class="text"><a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=229237555'>@slightlylate</a> It's been awesome seeing more businesses getting compression wins with Brotli over the last year. Google's Display Ads now uses Brotli too. </p>






  
  
  <div class="gallery gallery-1">
    
      
      
      
      
      
      
      
      
        
        
        

        
          
          
          
        
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/924348105553620994-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/DNPxsz9V4AAzFBQ.jpg"
    loading="lazy"
    alt=""
    width="705"
    height="387"
    data-source_url="https://pbs.twimg.com/media/DNPxsz9V4AAzFBQ.jpg"
    data-zoom-src="/twitter/media/photos/924348105553620994-0.jpeg"
    data-full_size="/twitter/media/photos/924348105553620994-0.jpeg"
    style="aspect-ratio: 705/387"
  />
</picture>

  </div>



















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/addyosmani/status/924348105553620994"
      data-date="1509216736"
      aria-label="Posted on 6:52 PM · Oct 28, 2017"
    >
      6:52 PM · Oct 28, 2017
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=924348105553620994"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














78

    </a>

    
    <a
      class="link"
      href="https://twitter.com/addyosmani/status/924348105553620994"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<p>Notice how the Indian linkedin users get <strong>2%</strong> faster loads out of brotli than
the USA users.</p>
<p>Here&rsquo;s another example with tailwindcss.</p>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1362367807887974401_kuJ1OFT1.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1362367807887974401/kuJ1OFT1.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1362367807887974401/kuJ1OFT1.jpg"
    data-zoom-src="/twitter/media/profile-photos/1362367807887974401_kuJ1OFT1.jpeg"
    data-full_size="/twitter/media/profile-photos/1362367807887974401_kuJ1OFT1.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=716933677">
    <span>Adam Wathan</span>
    
    
  </a>

  
  <span class="scr-name">@adamwathan</span>
  

  
  <div class="date-compact">· Jul 31 2020</div>


  </div>

  <div class="content">





  















<p class="text">Still completely blows my mind how well Tailwind compresses with Brotli. Bravo to those geniuses 👏 </p>






  
  
  <div class="gallery gallery-1">
    
      
      
      
      
      
      
      
      
        
        
        

        
          
          
          
        
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/1288994693498511360-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/EeNt1xWX0AAMbrS.jpg"
    loading="lazy"
    alt=""
    width="1125"
    height="810"
    data-source_url="https://pbs.twimg.com/media/EeNt1xWX0AAMbrS.jpg"
    data-zoom-src="/twitter/media/photos/1288994693498511360-0.jpeg"
    data-full_size="/twitter/media/photos/1288994693498511360-0.jpeg"
    style="aspect-ratio: 1125/810"
  />
</picture>

  </div>



















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/adamwathan/status/1288994693498511360"
      data-date="1596155257"
      aria-label="Posted on 12:27 AM · Jul 31, 2020"
    >
      12:27 AM · Jul 31, 2020
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1288994693498511360"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














352

    </a>

    
    <a
      class="link"
      href="https://twitter.com/adamwathan/status/1288994693498511360"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<h2 id="delta-compression">Delta Compression</h2>
<p>Delta compression is very useful when compressing a lot of similar data. If you
have a one line update to a file, you&rsquo;d only need to download/store the one line
change, regardless of the original file size. This is very useful when doing a
lot of incremental changes.</p>
<p>The most common use of it is probably git. Another great example is the
<a href="https://github.com/elfshaker/manyclangs">manyclangs</a> project which uses
<a href="https://github.com/elfshaker/elfshaker">elfshaker</a> to compress <strong>2,000</strong> clang
builds from <strong>400 GiB</strong> down to <strong>100 MiB</strong> and only takes 4 seconds to load any
build.</p>
<p>Delta compression is also very useful when storing backups. You can use the
<a href="https://github.com/bup/bup">bup</a> tool, if you want to compress lots of simmilar
files eg: excel sheets but don&rsquo;t want to directly use git.</p>
<p>I&rsquo;d love if chromium had something like this so i can run any chrome version I
want.</p>
<h2 id="shared-dictionaries">Shared Dictionaries</h2>
<p>Dictionaries are commonly used to increase compression ratios for specific
loads. A dictionary contains things that appear frequently and take lots of
space.</p>
<p>The web platform will soon add support for compression dictionaries</p>
<ul>
<li><a href="https://github.com/WICG/compression-dictionary-transport">Compression dictionary transport</a></li>
</ul>
<p>Brotli has a feature where you can compress a new file using an old one as a
dictionary and can improve compression ratios dramatically.</p>
<p>I did some tests and they can be really good.</p>
<p>Compressing typescript version <code>5.0.2</code> with version <code>5.1.0-beta</code> as a shared
dictionary</p>
<p>brotli: 642KB brotli+dict: 135KB</p>
<p>This is good news for sites that make constant updates.</p>

<div class="thread-wrapper">
  


  
    


  
    


  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/673140026994126848_kXa69lee.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/673140026994126848/kXa69lee.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/673140026994126848/kXa69lee.jpg"
    data-zoom-src="/twitter/media/profile-photos/673140026994126848_kXa69lee.jpeg"
    data-full_size="/twitter/media/profile-photos/673140026994126848_kXa69lee.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=87775005">
    <span>Patrick Meenan</span>
    
    
  </a>

  
  <span class="scr-name">@patmeenan</span>
  

  
  <div class="date-compact">· Mar 9 2023</div>


  </div>

  <div class="content">



















<p class="text">It's mind-blowing how well brotli shared dictionaries can help with re-delivering "mostly the same" content (both code/CSS bundles and MPA HTML).

A couple of quick spoilers below...</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/patmeenan/status/1633950507776581633" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














4

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950507776581633" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














12

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950507776581633" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














61

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950507776581633" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/673140026994126848_kXa69lee.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/673140026994126848/kXa69lee.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/673140026994126848/kXa69lee.jpg"
    data-zoom-src="/twitter/media/profile-photos/673140026994126848_kXa69lee.jpeg"
    data-full_size="/twitter/media/profile-photos/673140026994126848_kXa69lee.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=87775005">
    <span>Patrick Meenan</span>
    
    
  </a>

  
  <span class="scr-name">@patmeenan</span>
  

  
  <div class="date-compact">· Mar 9 2023</div>


  </div>

  <div class="content">



















<p class="text">Youtube's desktop player bundle (at 10MB uncompressed)

- 1.8 MB using brotli.

- 384 KB upgrading from a 2-month-old version using the old version as a shared dictionary (78% smaller than brotli).</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/patmeenan/status/1633950509206847490" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














2

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950509206847490" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














3

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950509206847490" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














23

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950509206847490" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/673140026994126848_kXa69lee.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/673140026994126848/kXa69lee.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/673140026994126848/kXa69lee.jpg"
    data-zoom-src="/twitter/media/profile-photos/673140026994126848_kXa69lee.jpeg"
    data-full_size="/twitter/media/profile-photos/673140026994126848_kXa69lee.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=87775005">
    <span>Patrick Meenan</span>
    
    
  </a>

  
  <span class="scr-name">@patmeenan</span>
  

  
  <div class="date-compact">· Mar 9 2023</div>


  </div>

  <div class="content">











  
  
  









<p class="text">The HTML for the listing pages for <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=19709040'>@eBay</a> as you go from item to item (600k uncompressed):

- 80 KB using brotli.

- 22 KB using a custom dictionary built off of other listing pages (73% smaller)</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/patmeenan/status/1633950510431477761" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














2

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950510431477761" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














2

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950510431477761" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














11

  </a>
  <a href="https://twitter.com/patmeenan/status/1633950510431477761" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



</div>

<p>You can perform test on your data at
<a href="https://test.patrickmeenan.com/shared-brotli/static/">test.patrickmeenan.com/shared-brotli/static/</a></p>
<p>Check out the
<a href="https://chromestatus.com/feature/5124977788977152">chrome status page</a> &amp;
<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1413922">bug tracker</a> for</p>
<p>implementation status of custom dictionaries.</p>
<p>Here&rsquo;s the script I used</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl">rm ./*.br
</span></span><span class="line"><span class="cl">rm ./*.js
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">dict</span><span class="o">=</span><span class="s2">&#34;cdnjs.cloudflare.com/ajax/libs/typescript/5.0.2/typescript.min.js&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">new</span><span class="o">=</span><span class="s2">&#34;cdnjs.cloudflare.com/ajax/libs/typescript/5.1.0-beta/typescript.min.js&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">dec</span><span class="o">=</span><span class="s2">&#34;smol.s&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Compress using File as dictionary</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;encoding shared br&#34;</span>
</span></span><span class="line"><span class="cl">brotli -q <span class="m">5</span> <span class="nv">$new</span> -o <span class="s2">&#34;</span><span class="nv">$dec</span><span class="s2">.shared.br&#34;</span> -D <span class="nv">$dict</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;encoding basic br&#34;</span>
</span></span><span class="line"><span class="cl">brotli -q <span class="m">5</span> <span class="nv">$new</span> -o <span class="s2">&#34;</span><span class="nv">$dec</span><span class="s2">.basic.br&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># verify</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;decoding basic br&#34;</span>
</span></span><span class="line"><span class="cl">brotli -d <span class="s2">&#34;</span><span class="nv">$dec</span><span class="s2">.basic.br&#34;</span> -o <span class="s2">&#34;basic-decoded.js&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;decoding shared br&#34;</span>
</span></span><span class="line"><span class="cl">brotli -d <span class="s2">&#34;</span><span class="nv">$dec</span><span class="s2">.shared.br&#34;</span> -D <span class="nv">$dict</span> -o <span class="s2">&#34;shared-decoded.js&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;decoding shared br&#34;</span>
</span></span><span class="line"><span class="cl">sha256sum <span class="nv">$new</span> <span class="s2">&#34;shared-decoded.js&#34;</span> <span class="s2">&#34;basic-decoded.js&#34;</span>
</span></span><span class="line"><span class="cl">exa --no-user --no-time --no-permissions -l ./*.br
</span></span></code></pre></div><h2 id="zstandard">Zstandard</h2>
<p>Zstandard (zstd) is a compresion format from facebook that is simmilar to brotli
but requires less cpu for comparable compression ratios to brotli. It&rsquo;s sadly
not implemented in browsers. Here&rsquo;s a chart comparing them</p>

<div class="thread-wrapper">
  


  
    


  
    


  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1518832985599975424_6wr9Nqu_.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1518832985599975424/6wr9Nqu_.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1518832985599975424/6wr9Nqu_.jpg"
    data-zoom-src="/twitter/media/profile-photos/1518832985599975424_6wr9Nqu_.jpeg"
    data-full_size="/twitter/media/profile-photos/1518832985599975424_6wr9Nqu_.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=807786872">
    <span>Jyrki Alakuijala 🇺🇦</span>
    
    
  </a>

  
  <span class="scr-name">@jyzg</span>
  

  
  <div class="date-compact">· Feb 9 2023</div>


  </div>

  <div class="content">





  















<p class="text">brotli/zstd/gzip compression comparison:
benchmarked with silesia corpus files split into 1 MB chunks which are then compressed independently
brotli used to be faster in compression at lower qualities, too, but zstd has caught up and exceeded at qualities below 5 </p>






  
  
  <div class="gallery gallery-1">
    
      
      
      
      
      
      
      
      
        
        
        

        
          
          
          
        
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/1623694815727652864-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/FoiE-O5WcAEKuvR.jpg"
    loading="lazy"
    alt=""
    width="1269"
    height="829"
    data-source_url="https://pbs.twimg.com/media/FoiE-O5WcAEKuvR.jpg"
    data-zoom-src="/twitter/media/photos/1623694815727652864-0.jpeg"
    data-full_size="/twitter/media/photos/1623694815727652864-0.jpeg"
    style="aspect-ratio: 1269/829"
  />
</picture>

  </div>



















    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/jyzg/status/1623694815727652864" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














3

  </a>
  <a href="https://twitter.com/jyzg/status/1623694815727652864" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














4

  </a>
  <a href="https://twitter.com/jyzg/status/1623694815727652864" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














21

  </a>
  <a href="https://twitter.com/jyzg/status/1623694815727652864" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/429283627751317504_xx_ZOL2y.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/429283627751317504/xx_ZOL2y.png"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/429283627751317504/xx_ZOL2y.png"
    data-zoom-src="/twitter/media/profile-photos/429283627751317504_xx_ZOL2y.png"
    data-full_size="/twitter/media/profile-photos/429283627751317504_xx_ZOL2y.png"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=234769926">
    <span>音風景の管理人</span>
    
    
  </a>

  
  <span class="scr-name">@kamedo2</span>
  

  
  <div class="date-compact">· Feb 9 2023</div>


  </div>

  <div class="content">











  
  
  









<p class="text"><a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=807786872'>@jyzg</a> So, brotli has the 'compression-very-slow-but-ultra-compressed' option that zstd doesn't offer, right?
I have a beefy machine to compress, but my clients can be anything, including low-end smartphones and single-board computers, so it helps.</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/kamedo2/status/1623704885182226435" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














1

  </a>
  <a href="https://twitter.com/kamedo2/status/1623704885182226435" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    













  




  </a>
  <a href="https://twitter.com/kamedo2/status/1623704885182226435" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














1

  </a>
  <a href="https://twitter.com/kamedo2/status/1623704885182226435" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1518832985599975424_6wr9Nqu_.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1518832985599975424/6wr9Nqu_.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1518832985599975424/6wr9Nqu_.jpg"
    data-zoom-src="/twitter/media/profile-photos/1518832985599975424_6wr9Nqu_.jpeg"
    data-full_size="/twitter/media/profile-photos/1518832985599975424_6wr9Nqu_.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=807786872">
    <span>Jyrki Alakuijala 🇺🇦</span>
    
    
  </a>

  
  <span class="scr-name">@jyzg</span>
  

  
  <div class="date-compact">· Feb 9 2023</div>


  </div>

  <div class="content">











  
  
  









<p class="text"><a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=234769926'>@kamedo2</a> Brotli as a format is a bit more expressive and can give better density when the heuristics are right or thoroughly explored.
Zstd as a format is easier to decompress.
Brotli hides less data than Zstd -- you can decode byte-to-byte whereas Zstd only when you have a full block.</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/jyzg/status/1623722590366752769" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














1

  </a>
  <a href="https://twitter.com/jyzg/status/1623722590366752769" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    













  




  </a>
  <a href="https://twitter.com/jyzg/status/1623722590366752769" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














3

  </a>
  <a href="https://twitter.com/jyzg/status/1623722590366752769" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



</div>

<h3 id="audio-compression">Audio Compression</h3>
<p>There isn&rsquo;t that much innovation happening in the audio compression but I found
one interesting thing.</p>
<p>Facebook is
<a href="https://ai.facebook.com/blog/ai-powered-audio-compression-technique/">Using AI for lossy audio compression</a>
&amp; acheives a 10x size reduction. ie: great audio quality at smaller sizes</p>
<p>Here&rsquo;s a chart showing the difference.</p>

<img loading='lazy' style='aspect-ratio:16/6;border-radius:0' src='/ai-sota-chart.webp'/>


<p>And Here&rsquo;s a video demonstrating the quality differences</p>

<video preload='metadata' controls poster='/poster-1.webp' style='aspect-ratio:16/9;width:100%;border-radius:8px' src='/311255641_624060969400419_1641488416212193643_n.mp4'></video>


<h3 id="video-compression">Video Compression</h3>
<p>Youtube uses their own custom chips for video compression.
<a href="https://dl.acm.org/doi/abs/10.1145/3445814.3446723">Warehouse-scale video acceleration: co-design and deployment in the wild</a></p>
<p><a href="https://en.wikipedia.org/wiki/Alliance_for_Open_Media">The Alliance for Open Media</a>,
which is behind the <a href="https://en.wikipedia.org/wiki/AV1">av1 video codec</a> &amp; the
<a href="https://en.wikipedia.org/wiki/AVIF">avif image format</a></p>
<ul>
<li><a href="https://www.bbc.co.uk/rd/projects/dynamic-adaptive-streaming-ip-multicast-dasm">IP Multicast</a> -
To reduce server load for broadcast streams eg: Sport Events, National events,
etc</li>
</ul>
<h3 id="image-compression">Image compression</h3>
<p><a href="https://jpegxl.info/">JPEG-XL</a> is a new universal image format that&rsquo;s good at
everything.</p>

<div class="thread-wrapper">
  


  
    


  
    


  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1604572646284447749/RZMthWsp.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1604572646284447749/RZMthWsp.jpg"
    data-zoom-src="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.jpeg"
    data-full_size="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=246290091">
    <span>Jon Sneyers</span>
    
    
  </a>

  
  <span class="scr-name">@jonsneyers</span>
  

  
  <div class="date-compact">· Jan 5 2021</div>


  </div>

  <div class="content">





  













  
    

    
    
    
    
    

    
    
    
    
    
    
    
  

  
    

    
    
    
    
    

    
    
    
    
    
    
    
  



<p class="text">Lossless image compression: besides the very slow experimental compressors LEA and EMMA, <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/hashtag/JPEGXL'>#JPEGXL</a>  beats anything else by a comfortable margin. Well-optimized PNG is 33% to 66% larger than <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/hashtag/JXL'>#JXL</a> . Not so well-optimized PNGs in the wild (not shown here) are ~50% to 100% larger. </p>






  
  
  <div class="gallery gallery-1">
    
      
      
      
      
      
      
      
      
        
        
        

        
          
          
          
        
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/1346389917816008704-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/Eq9TjW1XcAE9R3Q.jpg"
    loading="lazy"
    alt=""
    width="2246"
    height="868"
    data-source_url="https://pbs.twimg.com/media/Eq9TjW1XcAE9R3Q.jpg"
    data-zoom-src="/twitter/media/photos/1346389917816008704-0.jpeg"
    data-full_size="/twitter/media/photos/1346389917816008704-0.jpeg"
    style="aspect-ratio: 2246/868"
  />
</picture>

  </div>



















    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/jonsneyers/status/1346389917816008704" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














9

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346389917816008704" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














41

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346389917816008704" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














146

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346389917816008704" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1604572646284447749/RZMthWsp.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1604572646284447749/RZMthWsp.jpg"
    data-zoom-src="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.jpeg"
    data-full_size="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=246290091">
    <span>Jon Sneyers</span>
    
    
  </a>

  
  <span class="scr-name">@jonsneyers</span>
  

  
  <div class="date-compact">· Jan 5 2021</div>


  </div>

  <div class="content">





  















<p class="text">Also in terms of speed, JXL has a nice range of trade-offs between density and encode time. </p>






  
  
  <div class="gallery gallery-1">
    
      
      
      
      
      
      
      
      
        
        
        

        
          
          
          
        
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/1346579310933663746-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/ErAChU_XUAYdIdv.jpg"
    loading="lazy"
    alt=""
    width="1944"
    height="1188"
    data-source_url="https://pbs.twimg.com/media/ErAChU_XUAYdIdv.jpg"
    data-zoom-src="/twitter/media/photos/1346579310933663746-0.jpeg"
    data-full_size="/twitter/media/photos/1346579310933663746-0.jpeg"
    style="aspect-ratio: 1944/1188"
  />
</picture>

  </div>



















    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/jonsneyers/status/1346579310933663746" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














1

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346579310933663746" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














1

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346579310933663746" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














11

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346579310933663746" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1604572646284447749/RZMthWsp.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1604572646284447749/RZMthWsp.jpg"
    data-zoom-src="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.jpeg"
    data-full_size="/twitter/media/profile-photos/1604572646284447749_RZMthWsp.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=246290091">
    <span>Jon Sneyers</span>
    
    
  </a>

  
  <span class="scr-name">@jonsneyers</span>
  

  
  <div class="date-compact">· Jan 6 2021</div>


  </div>

  <div class="content">








  
  
  

  
  

  

  
  
  

  

  












<p class="text">I didn't do these benchmarks myself, I just summarized the results. The data is coming from <a target='_blank' rel='noopener noreferrer' href='https://docs.google.com/spreadsheets/d/1ju4q1WkaXT7WoxZINmQpf4ElgMD2VMlqeDN2DuZ6yJ8/edit?usp=sharing'>docs.google.com/spreadsheets/d…</a>, which I saw in this forum thread: <a target='_blank' rel='noopener noreferrer' href='https://encode.su/threads/3544-JXL-reference-software-version-0-2-released?p=67989&viewfull=1#post67989'>encode.su/threads/3544-J…</a></p>



  
  
  
    
      
    
  
    
  

  
  
    
    
    
    
    
      
      
      
    


    <section class="card card-small">
      
      
      

      
        
        <picture>
  
  
    
      
      <source
        srcset="/twitter/media/opengraph/1346702130623737862.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic card-thumbnail"
    src="https://pbs.twimg.com/card_img/1646984612172775424/xvGFP0Cr?format=jpg&amp;name=orig"
    loading="lazy"
    alt=""
    width="1200"
    height="630"
    data-source_url="https://pbs.twimg.com/card_img/1646984612172775424/xvGFP0Cr?format=jpg&amp;name=orig"
    data-zoom-src="/twitter/media/opengraph/1346702130623737862.jpeg"
    data-full_size="/twitter/media/opengraph/1346702130623737862.jpeg"
    style="aspect-ratio: 1200/630"
  />
</picture>


      
      <div class="card-content">
        

          
            <div class="vanity-url">docs.google.com</div>
          

          
            <div class="title ">
              <a href="https://docs.google.com/spreadsheets/d/1ju4q1WkaXT7WoxZINmQpf4ElgMD2VMlqeDN2DuZ6yJ8/edit?usp=sharing" target="_blank" rel="noopener noreferrer">
                <span>Lossless Image Formats Comparison (Jpeg XL, AVIF, WebP 2, WebP, FLIF, PNG, ...) v1.27</span>
                <div class="overlay" aria-hidden="true"></div>
              </a>
            </div>
          

          
            <p class="description">Details Summary,Size difference vs. JPEG XL (-e 9 -E 3 -I 1) Type,Image category,WebP,WebP v2,FLIF,AVIF,PNG,Effort 9,Effort 7,Effort 3,BMF (-s),EMMA Digital 2d Art,Art,16.8%,10.2%,5.8%,71.3%,47.7%,...</p>
          

        
      </div>
    </section>
  

  
  

  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/jonsneyers/status/1346702130623737862" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    













  




  </a>
  <a href="https://twitter.com/jonsneyers/status/1346702130623737862" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














1

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346702130623737862" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














4

  </a>
  <a href="https://twitter.com/jonsneyers/status/1346702130623737862" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



</div>

<p><a href="https://encode.su/threads/3544-JXL-reference-software-version-0-2-released?p=67989&amp;viewfull=1#post67989">https://encode.su/threads/3544-JXL-reference-software-version-0-2-released?p=67989&amp;viewfull=1#post67989</a></p>

<img loading='lazy' style='aspect-ratio:;border-radius:0' src='/D63zMYd.png'/>


<p><a href="https://encode.su/threads/3544-JXL-reference-software-version-0-2-released?p=67989&amp;viewfull=1#post67989">Chart is from encode.su</a></p>
<h2 id="latency">Latency</h2>
<p>The other problem to solve when dealing with web performance is latency,
especially network latency. I really like the post titled:
<a href="http://www.stuartcheshire.org/rants/latency.html">It&rsquo;s the Latency, Stupid</a>
which goes over why latency is important and why it&rsquo;s hard to reduce it compared
to increasing bandwidth.</p>
<p>There&rsquo;s several ways to reduce latency as a developer.</p>
<h3 id="do-all-the-processing-locally">Do all the processing locally.</h3>
<p>Eliminating the server and doing everything on the client side is a common way
to tackle performance problems.</p>
<p>A good example is <a href="https://squoosh.app">squoosh.app</a> an image compression web
app. It uses webAssembly which is slower than native but overall much faster
than using an online image compression service for one-off transformations.</p>
<p>Latency is the main reason Single Page Apps are a thing and why client side
routing is always used for long running web applications.</p>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1630207820359700480_a3pHtm6T.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1630207820359700480/a3pHtm6T.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1630207820359700480/a3pHtm6T.jpg"
    data-zoom-src="/twitter/media/profile-photos/1630207820359700480_a3pHtm6T.jpeg"
    data-full_size="/twitter/media/profile-photos/1630207820359700480_a3pHtm6T.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=182821975">
    <span>Evan You</span>
    
    
  </a>

  
  <span class="scr-name">@youyuxi</span>
  

  
  <div class="date-compact">· Apr 12 2022</div>


  </div>

  <div class="content">



















<p class="text">I feel that the current web perf discourse obsesses too much on initial loading perf and largely ignores subsequent navigations. It’s not even quantified in lighthouse scores, but makes a noticeable difference even for static sites.</p>























      


      <article class="tweet quoted" lang="en">
        <div class="profile-pic">
          

  
  
  
  
  
  
  
  

  
  

  

  
  
    
    
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1585965242231709696/cXolOpkB.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1585965242231709696/cXolOpkB.jpg"
    data-zoom-src="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.jpeg"
    data-full_size="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


        </div>
        <div class="user-info">
          


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=728158647122022400">
    <span>Ward Peeters</span>
    
    
  </a>

  
  <span class="scr-name">@wardpeet</span>
  

  
  <div class="date-compact">· Apr 11 2022</div>


        </div>

        <div class="content">



















<p class="text">SPA navigations always feel faster than MPA to me. Even turbo doesn't feel amazing. Anyone has an example to change my mind?</p>




</div>
      </article>
    

    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/youyuxi/status/1513827666406744064"
      data-date="1649759615"
      aria-label="Posted on 10:33 AM · Apr 12, 2022"
    >
      10:33 AM · Apr 12, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1513827666406744064"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














709

    </a>

    
    <a
      class="link"
      href="https://twitter.com/youyuxi/status/1513827666406744064"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<p>There&rsquo;s one issue with client side routing, it&rsquo;s fragile and requires a lot of
tooling and monitoring. Although that&rsquo;s an implementation detail not tied to all
SPAs. There&rsquo;s SPA frameworks like <a href="https://elm-lang.org/">elm</a> with
<a href="https://vitez.me/elm-runtime-error">zero runtime exceptions</a>.</p>
<p>Here&rsquo;s a video from 2016 showing a bug (hopefully fixed?) when using github from
airport wifi. Opening a new tab was faster than the client router.</p>

<video muted controls poster='/gh-screenshot.avif' preload='none' style='aspect-ratio:16/9;width:100%;border-radius:8px' src='/4zG0AZRZD6Q-640x360.webm'></video>


<p><a href="https://www.youtube.com/watch?v=4zG0AZRZD6Q">source: Youtube</a></p>
<p>SPAs need more work to function properly compared to simple MPAs, especially for
document based sites. Doing a lot of things in the client can lead to more
crashes that defeat the whole point of improving user experience.</p>
<h2 id="pre-fetch-things-the-application-will-need">pre-fetch things the application will need</h2>
<p>When visiting some documentation websites like
<a href="https://kit.svelte.dev/docs/web-standards">kit.svelte.dev</a>,
<a href="https://devdocs.io/">devdocs.io/</a> from a desktop device, the page navigation is
much faster than anything a multi page app could ever do.</p>
<p>Pre fetching things is not always good and could have a negative impact on users
on low-end devices.</p>
<h2 id="use-modern-protocols">Use modern protocols</h2>
<p>Specifically, adjust the backend to support batch requests and enable modern
protocols like http2 and http3.</p>
<p>It&rsquo;s pretty easy to setup a http2 server but surprisingly hard to make http2
requests from some languages. The solutions I could find that required little
configuration were the command line tools <a href=""><code>curl</code></a> &amp; <a href=""><code>wget2</code></a> and the
python <a href="https://www.python-httpx.org/http2/">httpx</a> library.</p>
<p>I liked the python one since it allowed me to reuse a client in 3 lines of code
despite me not really writing that much python code</p>
<p>Here&rsquo;s an example</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python3" data-lang="python3"><span class="line"><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">httpx</span><span class="o">.</span><span class="n">AsyncClient</span><span class="p">(</span><span class="n">http2</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="k">await</span> <span class="n">client</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">http_version</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># &#34;HTTP/1.0&#34;, &#34;HTTP/1.1&#34;, or &#34;HTTP/2&#34;.</span>
</span></span></code></pre></div><p>I noticed the benefit of <code>http2</code> when I had to making more than 10,000 http
requests to the twitter api for my archive-browser application. I did some tests
using curl and the difference is big</p>
<p>Move the servers closer to the user for dynamic applications eg: game servers
CDNs</p>
<p>Improve the hardware</p>
<p>Build a own private fiber optic cable network eg:
<a href="https://blog.cloudflare.com/cloudflare-backbone-internet-fast-lane/">Cloudflare Backbone</a>
and directly lower the latency</p>
<h2 id="measurments--analytics">Measurments &amp; analytics</h2>
<p>All these are great strategies but need to be measurably faster espacially if
you have more users. Here&rsquo;s a story about how netflix preloading data lead to
increased crashes &amp; less engagement, which is bad.</p>
<p>
<video controls poster='/destiny-poster.avif' preload='metadata' style='aspect-ratio:16/9;width:100%;border-radius:8px' src='/destiny.webm'></video>

 Source:
<a href="https://www.youtube.com/clip/UgkxnavUDaSW8pEbZAWpDuQDOEmOzHXfXAdE">Clean Code : Horrible Performance</a>
on youtube</p>
<p>The important takeaway here is to measure and test everything and challenge
assumptions. Not that doing things in the client is bad.</p>
<h2 id="you-are-not-google">You are not Google</h2>
<p>All these tips are only important if you have a lot of users on restricted
devices. If you have few users on predictable hardware and your app works,
performance isn&rsquo;t really that important</p>
<h2 id="further-reading">Further reading</h2>
<p>Here&rsquo;s some relevant links</p>
<ul>
<li><a href="https://blog.cloudflare.com/brotli-compression-using-a-reduced-dictionary/">Brotli compression using a reduced dictionary</a></li>
<li><a href="https://blog.cloudflare.com/improving-compression-with-preset-deflate-dictionary/">Improving compression with a preset DEFLATE dictionary</a></li>
<li><a href="https://idlewords.com/talks/website_obesity.htm">The Website Obesity Crisis</a></li>
<li><a href="https://danluu.com/web-bloat/">The modern web on a slow connection</a></li>
<li><a href="https://css-tricks.com/web-really-sucks-slow-connection/">web-really-sucks-slow-connection</a></li>
<li><a href="https://www.wired.co.uk/article/england-vs-croatia-live-stream-bbc-iplayer-itv">How the BBC and ITV are fixing delays on World Cup live streams</a></li>
</ul>
<h2 id="more-topics">More topics</h2>
<p>I haven&rsquo;t covered everything performance related. Here&rsquo;s some of the topics.</p>
<ul>
<li>http2 &amp; http3 multiplexing</li>
<li><a href="https://blog.cloudflare.com/introducing-0-rtt/">TLS 1.3 0 RTT</a></li>
<li>Lighthouse</li>
<li>Profiling websites with v8 profiler</li>
<li>CSS Performance (is it even a thing)</li>
<li>Image codec cpu usage</li>
<li>Geographical Distribution</li>
<li>Zstandard custom dictionaries</li>
<li>Brotli cpu usage benchmarks vs other codecs for compression on the fly</li>
<li>Image compression services</li>
<li>Service Workers</li>
</ul>
]]></content:encoded>
			</item>
			<item>
				<title>How to prevent CLS in Hugo</title>
				<link>/blog/14-cls-hugo/</link>
				<pubDate>Mon, 04 Jul 2022 00:00:00 +0000</pubDate>
				<guid>/blog/14-cls-hugo/</guid>
				<description>Use render hooks to automatically set width &amp; height on Images</description>
					<content:encoded><![CDATA[






  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1587647097670467584_adWRdqQ6.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1587647097670467584/adWRdqQ6.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1587647097670467584/adWRdqQ6.jpg"
    data-zoom-src="/twitter/media/profile-photos/1587647097670467584_adWRdqQ6.jpeg"
    data-full_size="/twitter/media/profile-photos/1587647097670467584_adWRdqQ6.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/leeerob">
    <span>Lee Robinson</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@leeerob</span>
  

  
  <div class="date-compact">· Apr 13 2022</div>


  </div>

  <div class="content">



















<p class="text">"What is Cumulative Layout Shift (CLS) and why does it matter?"

This is probably my favorite example.</p>























      


      <article class="tweet quoted" lang="qme">
        <div class="profile-pic">
          

  
  
  
  
  
  
  
  

  
  

  

  
  
    
    
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1585965242231709696/cXolOpkB.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1585965242231709696/cXolOpkB.jpg"
    data-zoom-src="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.jpeg"
    data-full_size="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


        </div>
        <div class="user-info">
          


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=933857178510921729">
    <span>MidlineShift</span>
    
    
  </a>

  
  <span class="scr-name">@detroit_bound</span>
  

  
  <div class="date-compact">· Mar 27 2022</div>


        </div>

        <div class="content">





  







  
  
  









<p class="text"><a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=1411723858181251074'>@ampol_moment</a> </p>




  

  
    
    
    
      
    

    


    
    
      
    


    <video
      style="aspect-ratio: 83/47; width: 100%; height: auto;"
      width="83"
      height="47"
      src="/remote/video.twimg.com/tweet_video/FO219KiXIAI6iVr.mp4"
      playsinline
      autoplay
      loop
      muted
    ></video>
  

</div>
      </article>
    

    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/leeerob/status/1514079310990254081"
      data-date="1649819612"
      aria-label="Posted on 3:13 AM · Apr 13, 2022"
    >
      3:13 AM · Apr 13, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1514079310990254081"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      





  



  



  






1.1K

    </a>

    
    <a
      class="link"
      href="https://twitter.com/leeerob/status/1514079310990254081"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<p>Preventing CLS requires setting explicit width and height attributes on all
pictures. Here are the steps I took to optimize the images in hugo using the
<a href="https://gohugo.io/templates/render-hooks/">render hooks</a> feature.</p>
<ol>
<li>Get the raw image data from a URL</li>
<li>Decode the image data</li>
<li>If available, set the width &amp; height attributes</li>
<li>Otherwise, fallback to the default template without the attributes</li>
</ol>
<p>Here&rsquo;s the complete code snippet.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go-html-template" data-lang="go-html-template"><span class="line"><span class="cl"><span class="c">&lt;!-- layouts/_default/_markup/render-image.html --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{</span><span class="w"> </span><span class="nx">$alt</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="na">.Text</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{</span><span class="w"> </span><span class="nx">$src</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="na">.Destination</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl"><span class="c">&lt;!-- Load &amp; decode image --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{</span><span class="w"> </span><span class="nx">$img</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">os</span><span class="na">.ReadFile</span><span class="w"> </span><span class="nx">$src</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">resources</span><span class="na">.FromString</span><span class="w"> </span><span class="nx">$src</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">{{/* Set Dimensions on Raster Images */}}</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">ne</span><span class="w"> </span><span class="nx">$img</span><span class="na">.MediaType.SubType</span><span class="w"> </span><span class="s">&#34;svg&#34;</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">img</span>
</span></span><span class="line"><span class="cl">    <span class="na">alt</span><span class="o">=</span><span class="s">&#34;</span><span class="cp">{{</span><span class="w"> </span><span class="nx">$alt</span><span class="w"> </span><span class="cp">}}</span><span class="s">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">src</span><span class="o">=</span><span class="s">&#34;</span><span class="cp">{{</span><span class="w"> </span><span class="nx">$src</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">safeURL</span><span class="w"> </span><span class="cp">}}</span><span class="s">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">width</span><span class="o">=</span><span class="s">&#34;</span><span class="cp">{{</span><span class="w"> </span><span class="nx">$img</span><span class="na">.Width</span><span class="w"> </span><span class="cp">}}</span><span class="s">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="na">height</span><span class="o">=</span><span class="s">&#34;</span><span class="cp">{{</span><span class="w"> </span><span class="nx">$img</span><span class="na">.Height</span><span class="w"> </span><span class="cp">}}</span><span class="s">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">{{/* Svgs &amp; Images that failed to load */}}</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="o">(</span><span class="k">not</span><span class="w"> </span><span class="nx">$img</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="k">eq</span><span class="w"> </span><span class="nx">$img</span><span class="na">.MediaType.SubType</span><span class="w"> </span><span class="s">&#34;svg&#34;</span><span class="o">)</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;</span><span class="cp">{{</span><span class="w"> </span><span class="nx">$src</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">safeURL</span><span class="w"> </span><span class="cp">}}</span><span class="s">&#34;</span> <span class="na">alt</span><span class="o">=</span><span class="s">&#34;</span><span class="cp">{{</span><span class="w"> </span><span class="nx">$alt</span><span class="w"> </span><span class="cp">}}</span><span class="s">&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="cp">}}</span>
</span></span></code></pre></div><p>For this render hook to work, images must be stored in the <code>/img</code> folder
relative to the project root with this configuration file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># config.yaml</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">module</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">mounts</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">static</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">target</span><span class="p">:</span><span class="w"> </span><span class="l">static</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="nt">source</span><span class="p">:</span><span class="w"> </span><span class="l">img</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">target</span><span class="p">:</span><span class="w"> </span><span class="l">static/img</span><span class="w">
</span></span></span></code></pre></div><h2 id="further-development">Further development</h2>
<ul>
<li>Suport Remote Image sources.</li>
<li>Support different local image sources <em>eg: <code>/content</code>, <code>/static</code> or
<code>/assets</code></em>.</li>
<li>Multiple image formats &amp; sizes.</li>
</ul>
]]></content:encoded>
			</item>
			<item>
				<title>Parse JSON with comments in Go</title>
				<link>/blog/13-json-golang/</link>
				<pubDate>Mon, 23 May 2022 00:00:00 +0000</pubDate>
				<guid>/blog/13-json-golang/</guid>
				<description>&lt;p&gt;The Go standard library can&amp;rsquo;t parse json files containing comments or trailing&#xA;commas. Doing so gives you the following error.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;invalid character &amp;#39;/&amp;#39; looking for beginning of object key string&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To prevent this error, you need to sanitize the json using the&#xA;&lt;a href=&#34;https://github.com/tailscale/hujson&#34;&gt;hujson&lt;/a&gt; package from Tailscale.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s an example on how to use it, also available in the&#xA;&lt;a href=&#34;https://go.dev/play/p/ogGACb2KtIE&#34;&gt;Go playground.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 1&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 2&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 3&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 4&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;encoding/json&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 5&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 6&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 7&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;github.com/tailscale/hujson&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 8&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 9&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;`{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;11&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;  // Comment&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;  &amp;#34;foo&amp;#34;: &amp;#34;bar&amp;#34;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;13&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;}`&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;14&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;`json:&amp;#34;foo&amp;#34;`&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;17&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;18&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;19&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;21&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;standardizeJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;22&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Unmarshal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;26&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;27&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;28&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;29&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;31&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;standardizeJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;32&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hujson&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Parse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;33&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;34&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;35&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;36&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Standardize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;37&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Pack&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;ln&#34;&gt;38&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
					<content:encoded><![CDATA[<p>The Go standard library can&rsquo;t parse json files containing comments or trailing
commas. Doing so gives you the following error.</p>
<pre tabindex="0"><code>invalid character &#39;/&#39; looking for beginning of object key string
</code></pre><p>To prevent this error, you need to sanitize the json using the
<a href="https://github.com/tailscale/hujson">hujson</a> package from Tailscale.</p>
<p>Here&rsquo;s an example on how to use it, also available in the
<a href="https://go.dev/play/p/ogGACb2KtIE">Go playground.</a></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">	</span><span class="s">&#34;encoding/json&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">	</span><span class="s">&#34;fmt&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">	</span><span class="s">&#34;github.com/tailscale/hujson&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="kd">const</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">`{
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s">  // Comment
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s">  &#34;foo&#34;: &#34;bar&#34;,
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s">}`</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">	</span><span class="nx">Foo</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="s">`json:&#34;foo&#34;`</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="w">	</span><span class="kd">var</span><span class="w"> </span><span class="nx">t</span><span class="w"> </span><span class="nx">x</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">21</span><span class="cl"><span class="w">	</span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nf">standardizeJSON</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="w">	</span><span class="nx">err</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">t</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">		</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="w">	</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">Foo</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="w">
</span></span></span><span class="line hl"><span class="ln">31</span><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">standardizeJSON</span><span class="p">(</span><span class="nx">b</span><span class="w"> </span><span class="p">[]</span><span class="kt">byte</span><span class="p">)</span><span class="w"> </span><span class="p">([]</span><span class="kt">byte</span><span class="p">,</span><span class="w"> </span><span class="kt">error</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">32</span><span class="cl"><span class="w">	</span><span class="nx">ast</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">hujson</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="nx">b</span><span class="p">)</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">33</span><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">34</span><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="nx">b</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">35</span><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">36</span><span class="cl"><span class="w">	</span><span class="nx">ast</span><span class="p">.</span><span class="nf">Standardize</span><span class="p">()</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">37</span><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="nx">ast</span><span class="p">.</span><span class="nf">Pack</span><span class="p">(),</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line hl"><span class="ln">38</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>]]></content:encoded>
			</item>
			<item>
				<title>Static twitter embed</title>
				<link>/blog/12-tweet-embed/</link>
				<pubDate>Wed, 20 Apr 2022 00:00:00 +0000</pubDate>
				<guid>/blog/12-tweet-embed/</guid>
				<description>Embedding tweets as plain HTML and CSS</description>
					<content:encoded><![CDATA[<p><a href="https://help.twitter.com/en/using-twitter/how-to-embed-a-tweet">The official tweet embed</a>
provides you with a <code>&lt;blockquote&gt;</code> element containing the tweet text and a third
party script to replace it with an <code>&lt;iframe&gt;</code> containing a better UI.</p>
<p>Here&rsquo;s an example of the code twitter provides.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="c">&lt;!-- Markup--&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">blockquote</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;twitter-tweet&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>just setting up my twttr<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  — jack⚡️ (@jack) March 21, 2006
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">blockquote</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="c">&lt;!--Script to enhance markup--&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;https://platform.twitter.com/widgets.js&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="the-problem">The problem</h2>
<p>This method of embedding tweets has some disadvantages:</p>
<ul>
<li>Causes a lot of <a href="https://web.dev/optimize-cls/">layout shifting</a></li>
<li>Difficult to style</li>
<li>Does not preserve deleted tweets</li>
</ul>
<h2 id="the-solution">The solution</h2>
<p>A good solution would be to get the tweet data from the API then use plain HTML
&amp; CSS to display it, which gives you the best lighthouse scores.</p>
<p>I implemented one for this blog. Here&rsquo;s an example.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{<span class="p">&lt;</span><span class="nt">tweet</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;20&#34;</span><span class="p">&gt;</span>}}
</span></span></code></pre></div>






  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1633258359792062465_pa8Hx-C9.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1633258359792062465/pa8Hx-C9.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1633258359792062465/pa8Hx-C9.jpg"
    data-zoom-src="/twitter/media/profile-photos/1633258359792062465_pa8Hx-C9.jpeg"
    data-full_size="/twitter/media/profile-photos/1633258359792062465_pa8Hx-C9.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/jack">
    <span>jack</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@jack</span>
  

  
  <div class="date-compact">· Mar 21 2006</div>


  </div>

  <div class="content">



















<p class="text">just setting up my twttr</p>
























    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/jack/status/20"
      data-date="1142974214"
      aria-label="Posted on 8:50 PM · Mar 21, 2006"
    >
      8:50 PM · Mar 21, 2006
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=20"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      





  



  



  






184.3K

    </a>

    
    <a
      class="link"
      href="https://twitter.com/jack/status/20"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  









  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1988892970125271040/nRrZG8mn.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1988892970125271040/nRrZG8mn.jpg"
    data-zoom-src=""
    data-full_size=""
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=13">
    <span>Biz Stone</span>
    
    
  </a>

  
  <span class="scr-name">@biz</span>
  

  
  <div class="date-compact">· Mar 21 2006</div>


  </div>

  <div class="content">



















<p class="text">wishing I had another sammich</p>
























    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/biz/status/40"
      data-date="1142975764"
      aria-label="Posted on 9:16 PM · Mar 21, 2006"
    >
      9:16 PM · Mar 21, 2006
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=40"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      





  



  



  






3.6K

    </a>

    
    <a
      class="link"
      href="https://twitter.com/biz/status/40"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<p>I had a lot of fun implementing it. I even added some features not available in
the official embed.</p>
<h2 id="features">Features</h2>
<h3 id="quote-tweets">Quote tweets</h3>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1630207820359700480_a3pHtm6T.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1630207820359700480/a3pHtm6T.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1630207820359700480/a3pHtm6T.jpg"
    data-zoom-src="/twitter/media/profile-photos/1630207820359700480_a3pHtm6T.jpeg"
    data-full_size="/twitter/media/profile-photos/1630207820359700480_a3pHtm6T.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=182821975">
    <span>Evan You</span>
    
    
  </a>

  
  <span class="scr-name">@youyuxi</span>
  

  
  <div class="date-compact">· Apr 12 2022</div>


  </div>

  <div class="content">



















<p class="text">I feel that the current web perf discourse obsesses too much on initial loading perf and largely ignores subsequent navigations. It’s not even quantified in lighthouse scores, but makes a noticeable difference even for static sites.</p>























      


      <article class="tweet quoted" lang="en">
        <div class="profile-pic">
          

  
  
  
  
  
  
  
  

  
  

  

  
  
    
    
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1585965242231709696/cXolOpkB.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1585965242231709696/cXolOpkB.jpg"
    data-zoom-src="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.jpeg"
    data-full_size="/twitter/media/profile-photos/1585965242231709696_cXolOpkB.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


        </div>
        <div class="user-info">
          


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=728158647122022400">
    <span>Ward Peeters</span>
    
    
  </a>

  
  <span class="scr-name">@wardpeet</span>
  

  
  <div class="date-compact">· Apr 11 2022</div>


        </div>

        <div class="content">



















<p class="text">SPA navigations always feel faster than MPA to me. Even turbo doesn't feel amazing. Anyone has an example to change my mind?</p>




</div>
      </article>
    

    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/youyuxi/status/1513827666406744064"
      data-date="1649759615"
      aria-label="Posted on 10:33 AM · Apr 12, 2022"
    >
      10:33 AM · Apr 12, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1513827666406744064"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














709

    </a>

    
    <a
      class="link"
      href="https://twitter.com/youyuxi/status/1513827666406744064"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<h3 id="threads">Threads</h3>

<div class="thread-wrapper">
  


  
    


  
    


  
    


  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    data-zoom-src="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    data-full_size="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/TwitterAPI">
    <span>Twitter API</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@TwitterAPI</span>
  

  
  <div class="date-compact">· Apr 29 2022</div>


  </div>

  <div class="content">








  
  
  

  
  

  












<p class="text">Today, we’re deprecating two features of the legacy v1.1 streaming endpoints, which we will retire on Oct 29, 2022:

• The v1.1 statuses/sample endpoint
• Compliance messages on the v1.1 statuses/filter endpoint

Learn more: <a target='_blank' rel='noopener noreferrer' href='https://twittercommunity.com/t/deprecation-announcement-removing-compliance-messages-from-statuses-filter-and-retiring-statuses-sample-from-the-twitter-api-v1-1/170500'>twittercommunity.com/t/deprecation-…</a></p>



  
  
  
    
      
    
  

  
  
    
    
    
    
    
      
      
      
    


    <section class="card card-small">
      
      
      

      
        
        <picture>
  
  
    
      
      <source
        srcset="/twitter/media/opengraph/1520089464487436297.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic card-thumbnail"
    src="https://pbs.twimg.com/card_img/1634855006905192449/aNJvAbXN?format=jpg&amp;name=orig"
    loading="lazy"
    alt=""
    width="1200"
    height="630"
    data-source_url="https://pbs.twimg.com/card_img/1634855006905192449/aNJvAbXN?format=jpg&amp;name=orig"
    data-zoom-src="/twitter/media/opengraph/1520089464487436297.jpeg"
    data-full_size="/twitter/media/opengraph/1520089464487436297.jpeg"
    style="aspect-ratio: 1200/630"
  />
</picture>


      
      <div class="card-content">
        

          
            <div class="vanity-url">twittercommunity.com</div>
          

          
            <div class="title ">
              <a href="https://twittercommunity.com/t/deprecation-announcement-removing-compliance-messages-from-statuses-filter-and-retiring-statuses-sample-from-the-twitter-api-v1-1/170500" target="_blank" rel="noopener noreferrer">
                <span>Deprecation announcement: Removing compliance messages from statuses/filter and retiring statuses...</span>
                <div class="overlay" aria-hidden="true"></div>
              </a>
            </div>
          

          
            <p class="description">Today, we’re deprecating two features on the Twitter API v1.1 streaming endpoints: The v1.1 statuses/sample endpoint Compliance messages on the v1.1 statuses/filter endpoint These features will be...</p>
          

        
      </div>
    </section>
  

  
  

  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/TwitterAPI/status/1520089464487436297" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














7

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089464487436297" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














28

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089464487436297" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














79

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089464487436297" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    data-zoom-src="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    data-full_size="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/TwitterAPI">
    <span>Twitter API</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@TwitterAPI</span>
  

  
  <div class="date-compact">· Apr 29 2022</div>


  </div>

  <div class="content">



















<p class="text">The v2 sampled stream, filtered stream, and batch compliance endpoints are available to all developers as replacements for this v1.1 functionality.</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/TwitterAPI/status/1520089466819461122" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














4

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089466819461122" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














5

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089466819461122" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














12

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089466819461122" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    data-zoom-src="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    data-full_size="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/TwitterAPI">
    <span>Twitter API</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@TwitterAPI</span>
  

  
  <div class="date-compact">· Apr 29 2022</div>


  </div>

  <div class="content">



















<p class="text">Starting today, new client applications will not be able to access v1.1 statuses/sample nor statuses/filter. Client apps created before today will retain access to both endpoints until they are retired. We are not deprecating v1.1 statuses/filter today, only compliance messages.</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/TwitterAPI/status/1520089468765708290" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














3

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089468765708290" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














11

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089468765708290" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














33

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089468765708290" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1445765299974795279/ExVMkDHG.jpg"
    data-zoom-src="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    data-full_size="/twitter/media/profile-photos/1445765299974795279_ExVMkDHG.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/TwitterAPI">
    <span>Twitter API</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@TwitterAPI</span>
  

  
  <div class="date-compact">· Apr 29 2022</div>


  </div>

  <div class="content">



















<p class="text">Deprecating these legacy features enables us to best serve developers on the Twitter API v2. We regain energy to go faster on new features. We’re committed to making migration to v2 equivalents easy and building more new value on v2.

See the forum post for resources 👆</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/TwitterAPI/status/1520089470791557121" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














2

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089470791557121" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














6

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089470791557121" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














33

  </a>
  <a href="https://twitter.com/TwitterAPI/status/1520089470791557121" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



</div>


<div class="thread-wrapper">
  


  
    


  
    


  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1290672565690695681/0G4bie6b.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1290672565690695681/0G4bie6b.jpg"
    data-zoom-src="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.jpeg"
    data-full_size="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=809233214">
    <span>TypeScript</span>
    
    
  </a>

  
  <span class="scr-name">@typescript</span>
  

  
  <div class="date-compact">· Mar 9 2022</div>


  </div>

  <div class="content">








  
  
  

  
  

  












<p class="text">Could we have TypeScript with no build step? Could we have types in JavaScript? Maybe!

We're exploring bringing optional type syntax into the JavaScript language!
<a target='_blank' rel='noopener noreferrer' href='https://devblogs.microsoft.com/typescript/a-proposal-for-type-syntax-in-javascript/'>devblogs.microsoft.com/typescript/a-p…</a></p>



  
  
  
    
      
    
  

  
  
    
    
    
    
    
      
      
      
    


    <section class="card card-small">
      
      
      

      
        
        <div class="card-no-image">
          
<svg
    viewBox="0 0 24 24"
    width="48" height="48"
    aria-hidden="true"
    fill="currentColor"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns="http://www.w3.org/2000/svg"
>
    <g>
        <path d="M14 11.25H6c-.414 0-.75.336-.75.75s.336.75.75.75h8c.414 0 .75-.336.75-.75s-.336-.75-.75-.75zm0-4H6c-.414 0-.75.336-.75.75s.336.75.75.75h8c.414 0 .75-.336.75-.75s-.336-.75-.75-.75zm-3.25 8H6c-.414 0-.75.336-.75.75s.336.75.75.75h4.75c.414 0 .75-.336.75-.75s-.336-.75-.75-.75z"></path>
        <path d="M21.5 11.25h-3.25v-7C18.25 3.01 17.24 2 16 2H4C2.76 2 1.75 3.01 1.75 4.25v15.5C1.75 20.99 2.76 22 4 22h15.5c1.517 0 2.75-1.233 2.75-2.75V12c0-.414-.336-.75-.75-.75zm-18.25 8.5V4.25c0-.413.337-.75.75-.75h12c.413 0 .75.337.75.75v15c0 .452.12.873.315 1.25H4c-.413 0-.75-.337-.75-.75zm16.25.75c-.69 0-1.25-.56-1.25-1.25v-6.5h2.5v6.5c0 .69-.56 1.25-1.25 1.25z"></path>
    </g>
</svg>

        </div>
      

      
      <div class="card-content">
        

          
            <div class="vanity-url">devblogs.microsoft.com</div>
          

          
            <div class="title ">
              <a href="https://devblogs.microsoft.com/typescript/a-proposal-for-type-syntax-in-javascript/" target="_blank" rel="noopener noreferrer">
                <span>A Proposal For Type Syntax in JavaScript - TypeScript</span>
                <div class="overlay" aria-hidden="true"></div>
              </a>
            </div>
          

          
            <p class="description">Today we’re excited to announce our support and collaboration on a new Stage 0 proposal to bring optional and erasable type syntax to JavaScript. Because this new syntax wouldn’t change how surroun...</p>
          

        
      </div>
    </section>
  

  
  

  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/typescript/status/1501634547921801216" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














154

  </a>
  <a href="https://twitter.com/typescript/status/1501634547921801216" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    





  



  



  






1.5K

  </a>
  <a href="https://twitter.com/typescript/status/1501634547921801216" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    





  



  



  






5.6K

  </a>
  <a href="https://twitter.com/typescript/status/1501634547921801216" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1290672565690695681/0G4bie6b.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1290672565690695681/0G4bie6b.jpg"
    data-zoom-src="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.jpeg"
    data-full_size="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=809233214">
    <span>TypeScript</span>
    
    
  </a>

  
  <span class="scr-name">@typescript</span>
  

  
  <div class="date-compact">· Mar 9 2022</div>


  </div>

  <div class="content">



















<p class="text">The Types as Comments proposal means that browsers could run TypeScript-checked code directly, (even though they wouldn't do any type-checking).

That means faster iteration with all the type-checking and editing experience you know and love today.</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/typescript/status/1501634549796593671" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














5

  </a>
  <a href="https://twitter.com/typescript/status/1501634549796593671" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














18

  </a>
  <a href="https://twitter.com/typescript/status/1501634549796593671" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














334

  </a>
  <a href="https://twitter.com/typescript/status/1501634549796593671" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



  

  


<article class="tweet thread" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1290672565690695681/0G4bie6b.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1290672565690695681/0G4bie6b.jpg"
    data-zoom-src="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.jpeg"
    data-full_size="/twitter/media/profile-photos/1290672565690695681_0G4bie6b.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=809233214">
    <span>TypeScript</span>
    
    
  </a>

  
  <span class="scr-name">@typescript</span>
  

  
  <div class="date-compact">· Mar 9 2022</div>


  </div>

  <div class="content">



















<p class="text">We're excited to hear what you think of this idea! We're hoping that this proposal can make coding easier for TypeScript and JavaScript users at every scale.</p>
























    
    
      





  





<div class="tweet-buttons-thread">
  <a href="https://twitter.com/typescript/status/1501634551151411200" class="blue">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><g><path d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"></path></g></svg>

    














17

  </a>
  <a href="https://twitter.com/typescript/status/1501634551151411200" class="green">
    
<svg  width="24" height="24" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true" class="r-4qtqp9 r-yyyyoo r-1xvli5t r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-1hdv0qi"><g><path d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"></path></g></svg>

    














8

  </a>
  <a href="https://twitter.com/typescript/status/1501634551151411200" class="red">
    
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


    














260

  </a>
  <a href="https://twitter.com/typescript/status/1501634551151411200" class="blue">
    
<svg
    viewBox="0 0 24 24"
    aria-hidden="true"
    width="24"
    height="24"
    fill="currentColor"
>
    <g><path d="M17.53 7.47l-5-5c-.293-.293-.768-.293-1.06 0l-5 5c-.294.293-.294.768 0 1.06s.767.294 1.06 0l3.72-3.72V15c0 .414.336.75.75.75s.75-.336.75-.75V4.81l3.72 3.72c.146.147.338.22.53.22s.384-.072.53-.22c.293-.293.293-.767 0-1.06z"></path><path d="M19.708 21.944H4.292C3.028 21.944 2 20.916 2 19.652V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 .437.355.792.792.792h15.416c.437 0 .792-.355.792-.792V14c0-.414.336-.75.75-.75s.75.336.75.75v5.652c0 1.264-1.028 2.292-2.292 2.292z"></path></g></svg>

  </a>
</div>

    
  </div>
</article>



</div>

<h3 id="opengraph-previews">OpenGraph Previews</h3>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/928422963098947584_evsM8DQ4.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/928422963098947584/evsM8DQ4.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/928422963098947584/evsM8DQ4.jpg"
    data-zoom-src="/twitter/media/profile-photos/928422963098947584_evsM8DQ4.jpeg"
    data-full_size="/twitter/media/profile-photos/928422963098947584_evsM8DQ4.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=407274356">
    <span>Andrew Ayer</span>
    
    
  </a>

  
  <span class="scr-name">@__agwa</span>
  

  
  <div class="date-compact">· Nov 12 2021</div>


  </div>

  <div class="content">








  
  
  

  
  

  












<p class="text">New blog post: It's Now Possible To Sign Arbitrary Data With Your SSH Keys <a target='_blank' rel='noopener noreferrer' href='https://www.agwa.name/blog/post/ssh_signatures'>agwa.name/blog/post/ssh_…</a></p>



  
  
  
    
      
    
  

  
  
    
    
    
    
    
      
      
      
    


    <section class="card card-small">
      
      
      

      
        
        <div class="card-no-image">
          
<svg
    viewBox="0 0 24 24"
    width="48" height="48"
    aria-hidden="true"
    fill="currentColor"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns="http://www.w3.org/2000/svg"
>
    <g>
        <path d="M14 11.25H6c-.414 0-.75.336-.75.75s.336.75.75.75h8c.414 0 .75-.336.75-.75s-.336-.75-.75-.75zm0-4H6c-.414 0-.75.336-.75.75s.336.75.75.75h8c.414 0 .75-.336.75-.75s-.336-.75-.75-.75zm-3.25 8H6c-.414 0-.75.336-.75.75s.336.75.75.75h4.75c.414 0 .75-.336.75-.75s-.336-.75-.75-.75z"></path>
        <path d="M21.5 11.25h-3.25v-7C18.25 3.01 17.24 2 16 2H4C2.76 2 1.75 3.01 1.75 4.25v15.5C1.75 20.99 2.76 22 4 22h15.5c1.517 0 2.75-1.233 2.75-2.75V12c0-.414-.336-.75-.75-.75zm-18.25 8.5V4.25c0-.413.337-.75.75-.75h12c.413 0 .75.337.75.75v15c0 .452.12.873.315 1.25H4c-.413 0-.75-.337-.75-.75zm16.25.75c-.69 0-1.25-.56-1.25-1.25v-6.5h2.5v6.5c0 .69-.56 1.25-1.25 1.25z"></path>
    </g>
</svg>

        </div>
      

      
      <div class="card-content">
        

          
            <div class="vanity-url">agwa.name</div>
          

          
            <div class="title ">
              <a href="https://www.agwa.name/blog/post/ssh_signatures" target="_blank" rel="noopener noreferrer">
                <span>It&#39;s Now Possible To Sign Arbitrary Data With Your SSH Keys</span>
                <div class="overlay" aria-hidden="true"></div>
              </a>
            </div>
          

          
            <p class="description">ssh-keygen can sign and verify signatures, and it&#39;s way better than PGP</p>
          

        
      </div>
    </section>
  

  
  

  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/__agwa/status/1459194182459961346"
      data-date="1636733978"
      aria-label="Posted on 4:19 PM · Nov 12, 2021"
    >
      4:19 PM · Nov 12, 2021
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1459194182459961346"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














276

    </a>

    
    <a
      class="link"
      href="https://twitter.com/__agwa/status/1459194182459961346"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  









  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1587830136472313858_Y2UgYOSJ.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1587830136472313858/Y2UgYOSJ.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1587830136472313858/Y2UgYOSJ.jpg"
    data-zoom-src="/twitter/media/profile-photos/1587830136472313858_Y2UgYOSJ.jpeg"
    data-full_size="/twitter/media/profile-photos/1587830136472313858_Y2UgYOSJ.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=59969976">
    <span>Eric Bailey</span>
    
    
  </a>

  
  <span class="scr-name">@ericwbailey</span>
  

  
  <div class="date-compact">· Jan 11 2022</div>


  </div>

  <div class="content">








  
  
  

  
  

  












<p class="text">"The real-life impact of our technical decisions really hit home to me once again: my Mom had trouble volunteering and participating in her local community because somebody shipped the optional chaining operator in their production JavaScript." <a target='_blank' rel='noopener noreferrer' href='https://blog.jim-nielsen.com/2022/a-web-for-all/'>blog.jim-nielsen.com/2022/a-web-for…</a></p>



  
  
  
    
      
    
  

  
  
    
    
    
    
    
      
      
      
    


    <section class="card card-small">
      
      
      

      
        
        <picture>
  
  
    
      
      <source
        srcset="/twitter/media/opengraph/1480948780769976328.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic card-thumbnail"
    src="https://pbs.twimg.com/card_img/1634290400734195712/FawFtzKt?format=png&amp;name=orig"
    loading="lazy"
    alt=""
    width="500"
    height="500"
    data-source_url="https://pbs.twimg.com/card_img/1634290400734195712/FawFtzKt?format=png&amp;name=orig"
    data-zoom-src="/twitter/media/opengraph/1480948780769976328.png"
    data-full_size="/twitter/media/opengraph/1480948780769976328.png"
    style="aspect-ratio: 500/500"
  />
</picture>


      
      <div class="card-content">
        

          
            <div class="vanity-url">blog.jim-nielsen.com</div>
          

          
            <div class="title title-2">
              <a href="https://blog.jim-nielsen.com/2022/a-web-for-all/" target="_blank" rel="noopener noreferrer">
                <span>The Optional Chaining Operator, “Modern” Browsers, and My Mom</span>
                <div class="overlay" aria-hidden="true"></div>
              </a>
            </div>
          

          

        
      </div>
    </section>
  

  
  

  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/ericwbailey/status/1480948780769976328"
      data-date="1641920678"
      aria-label="Posted on 5:04 PM · Jan 11, 2022"
    >
      5:04 PM · Jan 11, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1480948780769976328"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














182

    </a>

    
    <a
      class="link"
      href="https://twitter.com/ericwbailey/status/1480948780769976328"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  









  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1600539069217480704_RzK50Sks.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1600539069217480704/RzK50Sks.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1600539069217480704/RzK50Sks.jpg"
    data-zoom-src="/twitter/media/profile-photos/1600539069217480704_RzK50Sks.jpeg"
    data-full_size="/twitter/media/profile-photos/1600539069217480704_RzK50Sks.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/Cloudflare">
    <span>Cloudflare</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@Cloudflare</span>
  

  
  <div class="date-compact">· Oct 4 2021</div>


  </div>

  <div class="content">








  
  
  

  
  

  












<p class="text">“Facebook can't be down, can it?”, we thought, for a second. Well it can, and here's how.  <a target='_blank' rel='noopener noreferrer' href='https://cfl.re/3l7WBQs'>cfl.re/3l7WBQs</a></p>



  
  
  
    
      
    
  

  
  
    
    
    
    
    
      
      
    


    <section class="card card-large">
      
      
      

      
        
        <picture>
  
  
    
      
      <source
        srcset="/twitter/media/opengraph/1445135742561394692.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic card-thumbnail"
    src="https://pbs.twimg.com/card_img/1633180691771916291/PncAzbH8?format=jpg&amp;name=orig"
    loading="lazy"
    alt=""
    width="1200"
    height="628"
    data-source_url="https://pbs.twimg.com/card_img/1633180691771916291/PncAzbH8?format=jpg&amp;name=orig"
    data-zoom-src="/twitter/media/opengraph/1445135742561394692.jpeg"
    data-full_size="/twitter/media/opengraph/1445135742561394692.jpeg"
    style="aspect-ratio: 1200/628"
  />
</picture>


      
      <div class="card-content">
        

          
            <div class="vanity-url">blog.cloudflare.com</div>
          

          
            <div class="title ">
              <a href="https://cfl.re/3l7WBQs" target="_blank" rel="noopener noreferrer">
                <span>Understanding how Facebook disappeared from the Internet</span>
                <div class="overlay" aria-hidden="true"></div>
              </a>
            </div>
          

          
            <p class="description">Today at 1651 UTC, we opened an internal incident entitled &#34;Facebook DNS lookup returning SERVFAIL&#34; because we were worried that something was wrong with our DNS resolver 1.1.1.1. But as we were...</p>
          

        
      </div>
    </section>
  

  
  

  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/Cloudflare/status/1445135742561394692"
      data-date="1633382185"
      aria-label="Posted on 9:16 PM · Oct 4, 2021"
    >
      9:16 PM · Oct 4, 2021
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1445135742561394692"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      





  



  



  






5.1K

    </a>

    
    <a
      class="link"
      href="https://twitter.com/Cloudflare/status/1445135742561394692"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<h3 id="polls">Polls</h3>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/584963092120899586_TxkxQ7Y5.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/584963092120899586/TxkxQ7Y5.png"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/584963092120899586/TxkxQ7Y5.png"
    data-zoom-src="/twitter/media/profile-photos/584963092120899586_TxkxQ7Y5.png"
    data-full_size="/twitter/media/profile-photos/584963092120899586_TxkxQ7Y5.png"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/LeaVerou">
    <span>Lea Verou</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@LeaVerou</span>
  

  
  <div class="date-compact">· Mar 16 2022</div>


  </div>

  <div class="content">



















<p class="text">Hey, people who write CSS!
Do you use a preprocessor, and if so, which one?</p>



  
  
  

  
  

  
  

  

  

  













  

  
  

  



  
  
    
  
  
  

  
  
  
  

  
  
    
  
  
  

  
  
  
  






  <section class="polls">
    
      
      
      
        
      


      <div class="poll-container ">
        <div class="progress-container-text">
          
          <span> No, I don’t &nbsp; 1532 </span>
          
          <span> 28%</span>
        </div>

        
        <div
          class="progress-bar "
          style="width: 29%;"
          aria-hidden="true"
        ></div>
      </div>
    
      
      
      
        
      


      <div class="poll-container ">
        <div class="progress-container-text">
          
          <span> Yes, PostCSS &nbsp; 924 </span>
          
          <span> 17%</span>
        </div>

        
        <div
          class="progress-bar "
          style="width: 18%;"
          aria-hidden="true"
        ></div>
      </div>
    
      
      
      
        
      


      <div class="poll-container win">
        <div class="progress-container-text">
          
          <span> Yes, Sass &nbsp; 2838 </span>
          
          <span> 51%</span>
        </div>

        
        <div
          class="progress-bar win-bar"
          style="width: 52%;"
          aria-hidden="true"
        ></div>
      </div>
    
      
      
      
        
      


      <div class="poll-container ">
        <div class="progress-container-text">
          
          <span> Yes, other &nbsp; 275 </span>
          
          <span> 5%</span>
        </div>

        
        <div
          class="progress-bar "
          style="width: 6%;"
          aria-hidden="true"
        ></div>
      </div>
    
    
    <div class="total">
      <span>5569 votes</span>
      
        <span>· Final results</span>
      
    </div>
  </section>



    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/LeaVerou/status/1504102594192584705"
      data-date="1647440977"
      aria-label="Posted on 2:29 PM · Mar 16, 2022"
    >
      2:29 PM · Mar 16, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1504102594192584705"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














66

    </a>

    
    <a
      class="link"
      href="https://twitter.com/LeaVerou/status/1504102594192584705"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<h3 id="images">Images</h3>
<p>If supported, profile pictures &amp; images are served as <code>webp</code>, which provides
smaller sizes than jpeg and is supported in
<a href="https://caniuse.com/webp">90% of browsers</a></p>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    data-zoom-src="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    data-full_size="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=944480690">
    <span>API demos</span>
    
    
  </a>

  
  <span class="scr-name">@FloodSocial</span>
  

  
  <div class="date-compact">· Jun 25 2021</div>


  </div>

  <div class="content">





  















<p class="text">Growing more than apples </p>






  
  
  <div class="gallery gallery-2">
    
      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/1408575349286326272-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/E4xDzd7UYAELPMJ.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/E4xDzd7UYAELPMJ.jpg"
    data-zoom-src="/twitter/media/photos/1408575349286326272-0.jpeg"
    data-full_size="/twitter/media/photos/1408575349286326272-0.jpeg"
    style="aspect-ratio: /"
  />
</picture>

      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/1408575349286326272-1.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/E4xDz_sVkAI7suv.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/E4xDz_sVkAI7suv.jpg"
    data-zoom-src="/twitter/media/photos/1408575349286326272-1.jpeg"
    data-full_size="/twitter/media/photos/1408575349286326272-1.jpeg"
    style="aspect-ratio: /"
  />
</picture>

  </div>



















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/FloodSocial/status/1408575349286326272"
      data-date="1624665507"
      aria-label="Posted on 11:58 PM · Jun 25, 2021"
    >
      11:58 PM · Jun 25, 2021
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1408575349286326272"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      













  




    </a>

    
    <a
      class="link"
      href="https://twitter.com/FloodSocial/status/1408575349286326272"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  









  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    data-zoom-src="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    data-full_size="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=944480690">
    <span>API demos</span>
    
    
  </a>

  
  <span class="scr-name">@FloodSocial</span>
  

  
  <div class="date-compact">· May 29 2017</div>


  </div>

  <div class="content">





  















<p class="text">Geo with media </p>






  
  
  <div class="gallery gallery-3">
    
      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/869317433814904832-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/DBBvl9lUQAATWuY.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/DBBvl9lUQAATWuY.jpg"
    data-zoom-src="/twitter/media/photos/869317433814904832-0.jpeg"
    data-full_size="/twitter/media/photos/869317433814904832-0.jpeg"
    style="aspect-ratio: /"
  />
</picture>

      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/869317433814904832-1.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/DBBvl9fUwAI4nnT.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/DBBvl9fUwAI4nnT.jpg"
    data-zoom-src="/twitter/media/photos/869317433814904832-1.jpeg"
    data-full_size="/twitter/media/photos/869317433814904832-1.jpeg"
    style="aspect-ratio: /"
  />
</picture>

      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/869317433814904832-2.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/DBBvl9rVwAAkfee.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/DBBvl9rVwAAkfee.jpg"
    data-zoom-src="/twitter/media/photos/869317433814904832-2.jpeg"
    data-full_size="/twitter/media/photos/869317433814904832-2.jpeg"
    style="aspect-ratio: /"
  />
</picture>

  </div>



















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/FloodSocial/status/869317433814904832"
      data-date="1496096402"
      aria-label="Posted on 10:20 PM · May 29, 2017"
    >
      10:20 PM · May 29, 2017
    </a>

    
    
      <a class="tw-place" href="https://twitter.com/places/07d9e19c7ac81002">
        from
        the pool
      </a>
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=869317433814904832"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














1

    </a>

    
    <a
      class="link"
      href="https://twitter.com/FloodSocial/status/869317433814904832"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  









  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    data-zoom-src="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    data-full_size="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=944480690">
    <span>API demos</span>
    
    
  </a>

  
  <span class="scr-name">@FloodSocial</span>
  

  
  <div class="date-compact">· May 8 2017</div>


  </div>

  <div class="content">





  




  
  
  

  

  




  
  
  




  
  
  




  
    

    
    
    
    
    
      
      
      
        
          
          
        
      
        
          
          
        
      

      
      

    

    
    
    
    
    
    
    
  



<p class="text">Test Tweet with <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=50247739'>@mentionThis</a> <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/search?q=$twtr'>$twtr</a> <a target='_blank' rel='noopener noreferrer' href='http://bit.ly/2pUk4be'>bit.ly/2pUk4be</a> <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/hashtag/hashtag'>#hashtag</a>  </p>






  
  
  <div class="gallery gallery-4">
    
      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/861627479294746624-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/C_UdnvPUwAE3Dnn.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/C_UdnvPUwAE3Dnn.jpg"
    data-zoom-src="/twitter/media/photos/861627479294746624-0.jpeg"
    data-full_size="/twitter/media/photos/861627479294746624-0.jpeg"
    style="aspect-ratio: /"
  />
</picture>

      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/861627479294746624-1.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/C_UdnvPVYAAZbEs.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/C_UdnvPVYAAZbEs.jpg"
    data-zoom-src="/twitter/media/photos/861627479294746624-1.jpeg"
    data-full_size="/twitter/media/photos/861627479294746624-1.jpeg"
    style="aspect-ratio: /"
  />
</picture>

      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/861627479294746624-2.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/C_Udn2UUQAADZIS.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/C_Udn2UUQAADZIS.jpg"
    data-zoom-src="/twitter/media/photos/861627479294746624-2.jpeg"
    data-full_size="/twitter/media/photos/861627479294746624-2.jpeg"
    style="aspect-ratio: /"
  />
</picture>

      
      
      
      
      
      
      
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/861627479294746624-3.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/C_Udn4nUMAAgcIa.jpg"
    loading="lazy"
    alt=""
    width=""
    height=""
    data-source_url="https://pbs.twimg.com/media/C_Udn4nUMAAgcIa.jpg"
    data-zoom-src="/twitter/media/photos/861627479294746624-3.jpeg"
    data-full_size="/twitter/media/photos/861627479294746624-3.jpeg"
    style="aspect-ratio: /"
  />
</picture>

  </div>



















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/FloodSocial/status/861627479294746624"
      data-date="1494262973"
      aria-label="Posted on 5:02 PM · May 8, 2017"
    >
      5:02 PM · May 8, 2017
    </a>

    
    
      <a class="tw-place" href="https://twitter.com/places/2736a5db074e8201">
        from
        Longmont, CO
      </a>
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=861627479294746624"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














8

    </a>

    
    <a
      class="link"
      href="https://twitter.com/FloodSocial/status/861627479294746624"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<h3 id="gifs--videos">Gifs &amp; Videos</h3>







  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1162409582213226497/wHPWq9eI.jpg"
    data-zoom-src="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    data-full_size="/twitter/media/profile-photos/1162409582213226497_wHPWq9eI.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=944480690">
    <span>API demos</span>
    
    
  </a>

  
  <span class="scr-name">@FloodSocial</span>
  

  
  <div class="date-compact">· May 31 2017</div>


  </div>

  <div class="content">





  















<p class="text">Test Tweet with animated GIF </p>







  

  
    
    
    
      
    

    


    
    
      
    


    <video
      style="aspect-ratio: 175/131; width: 100%; height: auto;"
      width="175"
      height="131"
      src="/remote/video.twimg.com/tweet_video/DBMDLy_U0AAqUWP.mp4"
      playsinline
      autoplay
      loop
      muted
    ></video>
  


















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/FloodSocial/status/870042717589340160"
      data-date="1496269323"
      aria-label="Posted on 10:22 PM · May 31, 2017"
    >
      10:22 PM · May 31, 2017
    </a>

    
    
      <a class="tw-place" href="https://twitter.com/places/fd70c22040963ac7">
        from
        Boulder, CO
      </a>
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=870042717589340160"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














3

    </a>

    
    <a
      class="link"
      href="https://twitter.com/FloodSocial/status/870042717589340160"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  









  
  
    


<article class="tweet focus" lang="zxx">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1288228561359237121_f2V_Q8-U.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1288228561359237121/f2V_Q8-U.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1288228561359237121/f2V_Q8-U.jpg"
    data-zoom-src="/twitter/media/profile-photos/1288228561359237121_f2V_Q8-U.jpeg"
    data-full_size="/twitter/media/profile-photos/1288228561359237121_f2V_Q8-U.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=1288226864457084928">
    <span>ladies and gentlemen, the weekend 😌</span>
    
    
  </a>

  
  <span class="scr-name">@CraigWeekend</span>
  

  
  <div class="date-compact">· Apr 1 2022</div>


  </div>

  <div class="content">





  















<p class="text"></p>







  
    
    
    
    


    
    
    

    
      
      
      
    


    
    
      
      
      
      
      
        
      

      
      <video
        src="/remote/video.twimg.com/ext_tw_video/1509951805630803971/pu/vid/1280x720/Usl61jjlNbvinyQB-4dcd12e0.mp4"
        class="tweet-video"
        style="aspect-ratio: 1280/720; width: 100%; height: auto;"
        preload="metadata"
        controls
        poster="/twitter/media/posters/1509951833321578499.jpeg"
      ></video>
    
  

  


















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/CraigWeekend/status/1509951833321578499"
      data-date="1648835545"
      aria-label="Posted on 5:52 PM · Apr 1, 2022"
    >
      5:52 PM · Apr 1, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1509951833321578499"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      





  



  



  






61.6K

    </a>

    
    <a
      class="link"
      href="https://twitter.com/CraigWeekend/status/1509951833321578499"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  









  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1588969125220700160_Wk2tRIyE.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1588969125220700160/Wk2tRIyE.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1588969125220700160/Wk2tRIyE.jpg"
    data-zoom-src="/twitter/media/profile-photos/1588969125220700160_Wk2tRIyE.jpeg"
    data-full_size="/twitter/media/profile-photos/1588969125220700160_Wk2tRIyE.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/MatisseSadko">
    <span>Matisse &amp; Sadko</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@MatisseSadko</span>
  

  
  <div class="date-compact">· Apr 12 2022</div>


  </div>

  <div class="content">





  




  
  
  

  

  




  
  
  









<p class="text">Good morning guys! We’re thrilled to present you a new collab with our brother <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=134234000'>@MartinGarrix</a> 🔥
<a target='_blank' rel='noopener noreferrer' href='http://stmpd.co/vPLaYHI3'>stmpd.co/vPLaYHI3</a> </p>







  
    
    
    
    


    
    
    

    
      
      
      
    


    
    
      
      
      
      
      
        
      

      
      <video
        src="/remote/video.twimg.com/ext_tw_video/1513944612632674314/pu/vid/720x900/Je5t2NFeETLK5BCi-4dcd12e0.mp4"
        class="tweet-video"
        style="aspect-ratio: 720/900; width: 100%; height: auto;"
        preload="metadata"
        controls
        poster="/twitter/media/posters/1513944715703504914.jpeg"
      ></video>
    
  

  


















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/MatisseSadko/status/1513944715703504914"
      data-date="1649787522"
      aria-label="Posted on 6:18 PM · Apr 12, 2022"
    >
      6:18 PM · Apr 12, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1513944715703504914"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














435

    </a>

    
    <a
      class="link"
      href="https://twitter.com/MatisseSadko/status/1513944715703504914"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<h3 id="hashflags">Hashflags</h3>
<p>One of the unreleased features I added were hashflags, the emojis that appear
after a hashtag.</p>
<p>Here&rsquo;s an example using an expired hashflag.</p>







  
  
    


<article class="tweet focus" lang="tl">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1608707742570786816_mhV1fpE2.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1608707742570786816/mhV1fpE2.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1608707742570786816/mhV1fpE2.jpg"
    data-zoom-src="/twitter/media/profile-photos/1608707742570786816_mhV1fpE2.jpeg"
    data-full_size="/twitter/media/profile-photos/1608707742570786816_mhV1fpE2.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/wongmjane">
    <span>Jane Manchun Wong</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@wongmjane</span>
  

  
  <div class="date-compact">· Jun 3 2021</div>


  </div>

  <div class="content">





  













  
    

    
    
    
    
    
      
      
      
        
          
          
        
      
        
          
          
        
      
        
          
          
            
          
        
      

      
      
        
        
          
        
      

    

    
    
    
    
    
    
    
  



<p class="text">Apple’s <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/hashtag/WWDC21'>#WWDC21</a> <picture class='emoji'> <img src='/USEN_THB_TLB_72x72_BAN_WWDC_PREE_NA_NA_NA_NA_NA_14583386657519622016.png' alt=''> </picture> hashflag campaign name is absolutely wild:

USEN_THB_TLB_72x72_BAN_WWDC_PREE_NA_NA_NA_NA_NA

na na na na na </p>






  
  
  <div class="gallery gallery-1">
    
      
      
      
      
      
      
      
      
        
        
        

        
          
          
          
        
      

      <picture>
  
  
    
      
      <source
        srcset="/twitter/media/photos/1400374052087238658-0.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/media/E28gxqZUUAIu6KW.jpg"
    loading="lazy"
    alt=""
    width="1125"
    height="834"
    data-source_url="https://pbs.twimg.com/media/E28gxqZUUAIu6KW.jpg"
    data-zoom-src="/twitter/media/photos/1400374052087238658-0.jpeg"
    data-full_size="/twitter/media/photos/1400374052087238658-0.jpeg"
    style="aspect-ratio: 1125/834"
  />
</picture>

  </div>



















    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/wongmjane/status/1400374052087238658"
      data-date="1622710166"
      aria-label="Posted on 8:49 AM · Jun 3, 2021"
    >
      8:49 AM · Jun 3, 2021
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1400374052087238658"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














415

    </a>

    
    <a
      class="link"
      href="https://twitter.com/wongmjane/status/1400374052087238658"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<p>The code that archives deleted hashflags can be found at
<a href="https://github.com/ianmuchina/HashflagArchive">github.com/ianmuchina/HashflagArchive</a>
repo. It updates itself via github actions and a script.</p>
<h2 id="spaces">Spaces</h2>
<p>I also added a Twitter spaces card. It&rsquo;s simple and only links to the space page
on twitter.</p>







  
  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/618537697670397952_gW9iQsvF.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/618537697670397952/gW9iQsvF.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/618537697670397952/gW9iQsvF.jpg"
    data-zoom-src="/twitter/media/profile-photos/618537697670397952_gW9iQsvF.jpeg"
    data-full_size="/twitter/media/profile-photos/618537697670397952_gW9iQsvF.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=173630577">
    <span>Bryan Cantrill</span>
    
    
  </a>

  
  <span class="scr-name">@bcantrill</span>
  

  
  <div class="date-compact">· Apr 11 2022</div>


  </div>

  <div class="content">








  
  
  

  

  

  
  
  

  
      
    
  

  




  
  
  

  
  
  

  
  
  

  
  
  

  
  
  









<p class="text">No Twitter Space today, but <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=5438882'>@ahl</a> and I will be back next week where we will be joined by <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=2788076549'>@SyntheticGate</a>, <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=1430216716819341312'>@random_enginerd</a>, <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=1387201463173230592'>@AaronHartwig1</a>, <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=47618993'>@arjenroodselaar</a> and crew with more tales from the bringup lab! (The sequel to <a target='_blank' rel='noopener noreferrer' href='https://www.youtube.com/watch?v=lhji-kP3Lhk'>youtube.com/watch?v=lhji-k…</a>.) </p>



  
  
  
    
  
    
      
    
  

  
  

  
  
    











  
  

  
    
    
    
    
    

    
      
    


    <article class="spaces-card">
      <div class="spaces-meta">
        <div>
          <span class="spaces-date">Apr 18</span>
          <span class="spaces-name"
            >Bryan Cantrill</span
          >
          <span class="spaces-length">2:07:57</span>
        </div>
        <div></div>
      </div>
      <h3 class="spaces-title">More tales from the bringup lab</h3>
      <a href="https://twitter.com/i/spaces/1yNGaYVoBoWGj" class="spaces-btn"
        >Open on Twitter</a
      >
    </article>
  



  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/bcantrill/status/1513569873439326209"
      data-date="1649698153"
      aria-label="Posted on 5:29 PM · Apr 11, 2022"
    >
      5:29 PM · Apr 11, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1513569873439326209"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














25

    </a>

    
    <a
      class="link"
      href="https://twitter.com/bcantrill/status/1513569873439326209"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  


<p>After the space expires it will display like this.







  
  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1445764922474827784_W2zEPN7U.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1445764922474827784/W2zEPN7U.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1445764922474827784/W2zEPN7U.jpg"
    data-zoom-src="/twitter/media/profile-photos/1445764922474827784_W2zEPN7U.jpeg"
    data-full_size="/twitter/media/profile-photos/1445764922474827784_W2zEPN7U.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/TwitterDev">
    <span>Twitter Dev</span>
    
    
      <span class="checkmark">
        
<svg class="checkmark" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewbox="0 0 24 24" aria-label="CheckMark Icon" width="24" height="24">
	<g>
		<path d="M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z" fill="currentColor" />
	</g>
</svg>


      </span>
    
  </a>

  
  <span class="scr-name">@TwitterDev</span>
  

  
  <div class="date-compact">· Mar 23 2022</div>


  </div>

  <div class="content">








  
  
  

  
      
    
  

  




  
  
  

  
  
  

  
  
  

  
  
  









<p class="text">Join <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=108209516'>@ashevat</a>, <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=15772978'>@jessicagarson</a>, <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=857699969263964161'>@suhemparack</a> and <a target='_blank' rel='noopener noreferrer' href='https://twitter.com/intent/user?user_id=1324848235714736129'>@alanbenlee</a> Thursday 3/24 at 3:05pm PT for this month’s town hall conversation on the recent updates to the Twitter Developer Platform. 📆

Space Url: </p>



  
  
  
    
      
    
  

  
  

  
  
    











  
  

  
    
    <article class="spaces-card unavailable">
      <div class="spaces-meta">Spaces</div>
      <span class="spaces-title">Details not available</span>
    </article>
  



  

  

  













  

  
  

  



  
  
  
  

  
  
  
  








    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/TwitterDev/status/1506727406609920003"
      data-date="1648066782"
      aria-label="Posted on 8:19 PM · Mar 23, 2022"
    >
      8:19 PM · Mar 23, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1506727406609920003"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      














18

    </a>

    
    <a
      class="link"
      href="https://twitter.com/TwitterDev/status/1506727406609920003"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  

</p>
<p>More tests are available at</p>
<p><a href="https://drafts.blog-byl.pages.dev/tests/tweet/">drafts.blog-byl.pages.dev/tests/tweet/</a></p>
<h3 id="deleted-tweets">Deleted tweets</h3>
<p>Tweets are still shown if they get deleted.







  
  
  
    


<article class="tweet focus" lang="en">
  <div class="profile-pic">
    

  
  
  
  
  
  
  
  

  
  

  

  
  

  <picture>
  
  
    
      
      <source
        srcset="/twitter/media/profile-photos/1459675820537126914_V0xiHJ-W.webp"
        type="image/webp"
      />
    

    
    
  <img
    class="pic "
    src="https://pbs.twimg.com/profile_images/1459675820537126914/V0xiHJ-W.jpg"
    loading="lazy"
    alt=""
    width="45"
    height="45"
    data-source_url="https://pbs.twimg.com/profile_images/1459675820537126914/V0xiHJ-W.jpg"
    data-zoom-src="/twitter/media/profile-photos/1459675820537126914_V0xiHJ-W.jpeg"
    data-full_size="/twitter/media/profile-photos/1459675820537126914_V0xiHJ-W.jpeg"
    style="aspect-ratio: 45/45"
  />
</picture>


  </div>

  <div class="user-info">
    


  
  
  <a class="name" href="https://twitter.com/intent/user?user_id=749646635576197120">
    <span>muchina</span>
    
    
  </a>

  
  <span class="scr-name">@much1na</span>
  

  
  <div class="date-compact">· Apr 29 2022</div>


  </div>

  <div class="content">



















<p class="text">This tweet does not exist</p>
























    
    
      
  
  
  
  
  <span>
    
    <a
      class="tw-date"
      href="https://twitter.com/much1na/status/1520174956310671364"
      data-date="1651272927"
      aria-label="Posted on 10:55 PM · Apr 29, 2022"
    >
      10:55 PM · Apr 29, 2022
    </a>

    
    
  </span>

  <div class="meta">
    <a
      class="likes"
      href="https://twitter.com/intent/like?tweet_id=1520174956310671364"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewbox="0 0 24 24" width="24" height="24" fill="currentColor">
	<g>
		<path d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z" fill="currentColor" />
	</g>
</svg>


      













  




    </a>

    
    <a
      class="link"
      href="https://twitter.com/much1na/status/1520174956310671364"
      target="_blank"
      rel="noopener noreferrer"
    >
      
<svg xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" aria-hidden="true" width="24" fill="currentColor" height="24" viewbox="0 0 24 24">
	<g>
		<path d="M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z" />
		<path d="M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z" fill="currentColor" />
	</g>
</svg>

 Link to Tweet
    </a>
  </div>


    
  </div>
</article>

  

</p>
<h2 id="further-development">Further development</h2>
<ul>
<li>More Test cases</li>
<li>avif file format</li>
<li>Threads</li>
<li>Image zooming</li>
<li>Image placeholders</li>
</ul>
]]></content:encoded>
			</item>
			<item>
				<title>New Look</title>
				<link>/blog/meta-update/</link>
				<pubDate>Mon, 17 May 2021 00:00:00 +0000</pubDate>
				<guid>/blog/meta-update/</guid>
				<description>Meta update on my blog</description>
					<content:encoded><![CDATA[<p>I decided to make a <a href="https://github.com/ianmuchina/purple">new theme</a> from
scratch. This helped me improve my frontend skills a little. The theme isn&rsquo;t
quite yet complete, but it&rsquo;s good enough.</p>
<p>





  <img
    src="/img/meta-update/screenshot.webp"
    width="1920"
    height="1080"
    alt="Screenshot of this site"
  />

</p>
<p>For the static site generator, I chose <code>Hugo</code> because of its speed &amp; simplicity.
The tradeoff is that feature-wise, it&rsquo;s limited. Although it doesn&rsquo;t matter that
much for a blog.</p>
<p>I also transferred my domain from NameCheap to Cloudflare. It made sense since I
was already using Cloudflare for DNS. The costs are crazy. Literally wholesale
pricing. Only on transfers &amp; renewals. You need an existing domain.</p>
<p>





  <img
    src="/img/meta-update/costs.webp"
    width="3828"
    height="1668"
    alt="Image showing costs"
  />

</p>
<ul>
<li><a href="https://www.cloudflare.com/tld-policies/">Cloudflare Supported Tlds</a></li>
<li><a href="https://github.com/judge2020/Actual-Domain-Prices">Wholesale TLD Prices</a></li>
</ul>
]]></content:encoded>
			</item>
			<item>
				<title>Stop chrome from pausing when switching desktops</title>
				<link>/chrome-pauses/</link>
				<pubDate>Sun, 04 Apr 2021 00:00:00 +0000</pubDate>
				<guid>/chrome-pauses/</guid>
				<description>Switch between desktop environments without breaking your browser</description>
					<content:encoded><![CDATA[<p>Sometimes I switch desktop environments because, why not? Every time I switch
between gnome and kde, I face the same issue. Chrome pauses.</p>
<p>When chrome displays the paused sign, it’s an issue with cookies. In this case,
the cookies are encrypted, and chrome can’t decrypt them because it’s looking
for the decryption key in the wrong keyring.</p>
<h2 id="too-many-keyrings">Too many keyrings</h2>
<p>A keyring is a lot like a password manager. The only difference is that keyrings
are meant for programs, and password managers are meant for humans.
<a href="https://chromium.googlesource.com/chromium/src/+/master/docs/security/faq.md#does-the-password-manager-store-my-passwords-encrypted-on-disk">For security</a>,
chrome stores the key used to decrypt cookies in the keyring.</p>
<p>All major operating systems have some sort of keyring implementation. Windows
has one, Mac has one. Linux has several. On Linux, chrome decides the keyring it
will use based on the current desktop environment.</p>
<p>When switching desktop environments, chrome will switch keyrings without
migrating the keys. This makes chrome forget the key needed to decrypt the
cookies.</p>
<h2 id="stick-with-one">Stick with one</h2>
<p>The solution is to hardcode the keyring chrome will use. You can do this with
the &ndash;password-store flag, which has 3 options:</p>
<ul>
<li>gnome (to use GNOME Keyring)</li>
<li>kwallet (to use KDE’s KWallet)</li>
<li>basic (to use the plain text store. No encryption)</li>
</ul>
<p>To set the flag, first install menu-libre.</p>
<pre tabindex="0"><code>sudo apt install menulibre
</code></pre><p>Then using menu-libre, edit chrome’s command.</p>
<pre tabindex="0"><code>/usr/bin/google-chrome-stable --password-store=kwallet5 %U
</code></pre><p>Hopefully, that works, and you can switch desktops without breaking your
browser.</p>
<h2 id="further-reading">Further reading</h2>
<p><a href="https://wiki.gnome.org/Projects/GnomeKeyring/SecurityFAQ">Benefits of keyrings</a></p>
]]></content:encoded>
			</item>
			<item>
				<title>Some youtube-dl aliases</title>
				<link>/blog/08-ytdl/</link>
				<pubDate>Fri, 26 Mar 2021 08:00:00 +0300</pubDate>
				<guid>/blog/08-ytdl/</guid>
				<description>Making youtube-dl easy to use</description>
					<content:encoded><![CDATA[<p>Setup some variables</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Default Command</span>
</span></span><span class="line"><span class="cl"><span class="nv">CMD</span><span class="o">=</span><span class="s2">&#34;youtube-dl&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Use yt-dlp if avaiable</span>
</span></span><span class="line"><span class="cl"><span class="nb">command</span> -v yt-dlp &gt;/dev/null <span class="o">&amp;&amp;</span>
</span></span><span class="line"><span class="cl">  <span class="nv">CMD</span><span class="o">=</span><span class="s2">&#34;yt-dlp&#34;</span> <span class="nv">ARGS</span><span class="o">=</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Quality Options</span>
</span></span><span class="line"><span class="cl"><span class="nv">Q_HD</span><span class="o">=</span><span class="s2">&#34;720&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">Q_FHD</span><span class="o">=</span><span class="s2">&#34;1080&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">Q_DEFAULT</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$Q_HD</span><span class="s2">&#34;</span>
</span></span></code></pre></div><h3 id="default-command">Default command</h3>
<p>Saves video to <code>~/Videos/Channel/video.mp4</code> without video Id.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="c1"># Video</span>
</span></span><span class="line"><span class="cl">ydl<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;</span><span class="nv">$CMD</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$ARGS</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --no-playlist <span class="se">\
</span></span></span><span class="line"><span class="cl">    --embed-subs <span class="se">\
</span></span></span><span class="line"><span class="cl">    --format <span class="s2">&#34;[height&lt;=</span><span class="nv">$Q_DEFAULT</span><span class="s2">]&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output <span class="s2">&#34;</span><span class="nv">$HOME</span><span class="s2">/Videos/%(uploader)s/%(title)s.%(ext)s&#34;</span> <span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></div><h2 id="720p-video">720p Video</h2>
<ul>
<li>Single video</li>
<li>No playlist</li>
<li>Saves to <code>~/Videos/Uploader/Title.mp4</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Video (720p)</span>
</span></span><span class="line"><span class="cl">yhd<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;</span><span class="nv">$CMD</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$ARGS</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --no-playlist <span class="se">\
</span></span></span><span class="line"><span class="cl">    --embed-subs <span class="se">\
</span></span></span><span class="line"><span class="cl">    --format <span class="s2">&#34;[height&lt;=</span><span class="nv">$Q_HD</span><span class="s2">]&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output <span class="s2">&#34;</span><span class="nv">$HOME</span><span class="s2">/Videos/%(uploader)s/%(title)s.%(ext)s&#34;</span> <span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></div><h2 id="720p-video-playlist">720p video playlist</h2>
<ul>
<li>Download entire playlist</li>
<li>Saves to <code>~/Videos/Uploader/Playlist/Title.mp4</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ypl<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;</span><span class="nv">$CMD</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$ARGS</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --yes-playlist <span class="se">\
</span></span></span><span class="line"><span class="cl">    --format <span class="s2">&#34;[height&lt;=</span><span class="nv">$Q_DEFAULT</span><span class="s2">]&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output <span class="s2">&#34;</span><span class="nv">$HOME</span><span class="s2">/Videos/%(uploader)s/%(playlist)s/%(title)s.%(ext)s&#34;</span> <span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></div><h2 id="audio">Audio</h2>
<ul>
<li>Outputs to mp3</li>
<li>Does not download entire playlist</li>
<li>Saves to <code>~/Music/Uploader/Title.mp3</code></li>
<li>Embeds Video thumbnail as cover art</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Audio</span>
</span></span><span class="line"><span class="cl">ymp3<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;</span><span class="nv">$CMD</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$ARGS</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --extract-audio <span class="se">\
</span></span></span><span class="line"><span class="cl">    --audio-format mp3 <span class="se">\
</span></span></span><span class="line"><span class="cl">    --no-playlist <span class="se">\
</span></span></span><span class="line"><span class="cl">    --embed-thumbnail <span class="se">\
</span></span></span><span class="line"><span class="cl">    --format <span class="s2">&#34;bestaudio&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output <span class="s2">&#34;</span><span class="nv">$HOME</span><span class="s2">/Music/%(uploader)s/%(title)s.%(ext)s&#34;</span> <span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></div><h2 id="audio-playlist">Audio Playlist</h2>
<ul>
<li>Saves to <code>~/Videos/Uploader/Playlist/Title.mp3</code></li>
<li>Adds thumbnail as cover art</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Audio Playlist</span>
</span></span><span class="line"><span class="cl">ypl3<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;</span><span class="nv">$CMD</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$ARGS</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --extract-audio <span class="se">\
</span></span></span><span class="line"><span class="cl">    --audio-format mp3 <span class="se">\
</span></span></span><span class="line"><span class="cl">    --yes-playlist <span class="se">\
</span></span></span><span class="line"><span class="cl">    --embed-thumbnail <span class="se">\
</span></span></span><span class="line"><span class="cl">    --format <span class="s2">&#34;bestaudio&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output <span class="s2">&#34;</span><span class="nv">$HOME</span><span class="s2">/Music/%(uploader)s/%(playlist)s/%(title)s.%(ext)s&#34;</span> <span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span></code></pre></div>]]></content:encoded>
			</item>
			<item>
				<title>Reproducible Builds</title>
				<link>/blog/reproducible-builds/</link>
				<pubDate>Wed, 13 Jan 2021 11:30:00 +0300</pubDate>
				<guid>/blog/reproducible-builds/</guid>
				<description>Why are reproducible buids are so important</description>
					<content:encoded><![CDATA[<p>A reproducible build is one that produces the same byte for byte output when
given the same input. These builds aren&rsquo;t common. Mostly because of compiler
defaults.</p>
<p>The things that can make a build non-reproducible are:</p>
<ul>
<li>Timestamps</li>
<li>Unique IDs</li>
<li>Build paths</li>
<li><em>etc</em></li>
</ul>
<h2 id="why-they-matter">Why they matter</h2>
<p>Reproducible builds have inherent security. They allow us to verify the source
code a binary comes from. This makes detecting changes or tampering
straightforward.</p>
<ol>
<li>Compile the program on at least two different systems</li>
<li>Compare the checksums.</li>
<li>If they match, that&rsquo;s good. If they don&rsquo;t match, something is wrong.</li>
</ol>
<p>The builds have more integrity, which benefits everyone. For security-minded
people, it means a straightforward way of detecting backdoors in the build
process. For open source enthusiasts, it means a clear way of detecting GPL
violations. For everyone else, we get safer software.</p>
<p>You can find out how to acheive reproducible builds at
<a href="https://reproducible-builds.org">reproducible-builds.org/docs</a>.</p>
<h2 id="attacks-on-build-systems">Attacks on build systems</h2>
<p>Back-doors introduced in the build process are not easy to detect. Most of the
detection happens too late when the damage is already done. The attacks can have
a high impact in a short period, so early detection is important.</p>
<p>There have been many attacks like this in the past. Some of them are:</p>
<ul>
<li><a href="https://www.crowdstrike.com/blog/sunspot-malware-technical-analysis/">SUNSPOT</a>,
An attack on SolarWinds that affected
<a href="https://businessinsider.com/tech-insider/heres-a-list-of-the-us-agencies-and-companies-that-were-reportedly-hacked-in-the/n58jz32">lots of important people</a></li>
<li><a href="https://en.wikipedia.org/wiki/XcodeGhost">XcodeGhost</a> - Attack on an IDE for
Mac. Lots of iOS apps were affected. Including Angry Birds</li>
</ul>
<h2 id="defending-against-them">Defending against them</h2>
<p>Reproducible builds are the best way to defend against these kinds of attacks.
Attackers lose their incentive bacause they are detected quickly and need to
compromise more systems.</p>
<h2 id="the-disadvantages">The disadvantages</h2>
<p>Like everything there are downsides. Some of them are:</p>
<ul>
<li>Need to use a specific compiler version</li>
<li>No
<a href="https://en.wikipedia.org/wiki/Profile-guided_optimization">Profile-guided optimization</a></li>
</ul>
<h2 id="what-they-dont-protect-us-from">What they don&rsquo;t protect us from</h2>
<p>Reproducible builds don&rsquo;t protect us from malicious developers. A developer
could knowingly write vulnerable code that looks like a mistake when discovered.
This called underhanded code.</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Underhanded_C_Contest">Underhanded C Contest</a></li>
<li><a href="https://underhandedcrypto.com/">Underhanded Crypto Contest</a></li>
</ul>
<p>In the paper titled
<a href="https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_ReflectionsonTrustingTrust.pdf">Trusting Trust</a>
Ken Thompson asks us:</p>
<blockquote>
<p>To what extent should one trust a statement that a program is free of Trojan
horses? Perhaps it is more important to trust the people who wrote the
software.</p>
</blockquote>
<h2 id="who-does-reproducible-builds">Who does reproducible builds?</h2>
<p>Many open-source projects have reproducible builds to assure users of their
integrity. Some of them include:</p>
<ol>
<li><a href="https://daniel-lima.github.io/bitcoin-devenv/vagrant/how-to/deterministically-build-bitcoin-core.html">Bitcoin</a></li>
<li><a href="https://blog.torproject.org/deterministic-builds-part-two-technical-details">Tor Browser</a></li>
<li><a href="https://f-droid.org/docs/Reproducible_Builds/?title=Deterministic,_Reproducible_Builds">F-Droid</a></li>
<li><a href="https://signal.org/blog/reproducible-android/.">Signal</a></li>
<li><a href="https://core.telegram.org/reproducible-builds">Telegram</a></li>
</ol>
<p>You can find more at
<a href="https://reproducible-builds.org/projects/">reproducible-builds</a></p>
<h3 id="linux-distros">Linux distros</h3>
<p>Around 80%-90% of the packages in Linux distributions <em>( Arch, Debian, OpenSUSE,
NixOS, Guix)</em> are already reproducible. You can find the exact numbers at
<a href="https://reproducible-builds.org/citests/">reproducible-builds.org</a>.</p>
<h2 id="digital-signatures">Digital signatures</h2>
<p>Digital signatures still have their place. They are useful when verifying who a
document or message comes from. They aren&rsquo;t useful when verifying the source
code a binary comes from. Some forms of digital signatures can get in the way of
reproducible builds, as explained by telegram developers in
<a href="https://core.telegram.org/reproducible-builds">this article</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I&rsquo;ll conclude by quoting Mike Perry of the Tor project. He
<a href="https://mailman.stanford.edu/pipermail/liberationtech/2013-June/009257.html#:~:text=believe">described</a>
the importance of reproducible-builds as follows:</p>
<blockquote>
<p>I don&rsquo;t believe that software development models based on trusting a single
party can be secure against serious adversaries anymore, given the current
trends in computer security.</p>
</blockquote>
<p>This statement is true to this day.</p>
<hr>
<h2 id="further-reading">Further reading</h2>
<p>Many people have written about reproducible builds and have gone into more
detail than I have in this post. Here are some of them.</p>
<h3 id="reproducible-buildsorg"><a href="https://reproducible-builds.org">reproducible-builds.org</a></h3>
<p>A website with technical information on reproducible builds. It also has status
updates on Linux distributions.</p>
<h3 id="reflections-on-trusting-trust"><a href="https://www.win.tue.nl/~aeb/linux/hh/thompson/trust.html">Reflections on Trusting Trust</a></h3>
<p>A paper by Ken Thompson. He asks us what if compilers had backdoors. Would it
possible to even detect &amp; prevent such an attack?</p>
<h3 id="countering-compiler-backdoors"><a href="https://dwheeler.com/trusting-trust/">Countering Compiler backdoors </a></h3>
<p>David A. Wheeler answers the above question. He proposes a method called Diverse
Double-Compiling.</p>
<h3 id="the-octopus-scanner-malware"><a href="https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain">The Octopus Scanner Malware</a></h3>
<p>Writeup on the discovery of a supply chain attack that targeted developer&rsquo;s
machines.</p>
<h3 id="verifying-the-source-code-for-binaries"><a href="https://lwn.net/Articles/555761/">Verifying the source code for binaries</a></h3>
<p>An Lwn article on reproducible builds</p>
]]></content:encoded>
			</item>
			<item>
				<title>Automating updates on Debian</title>
				<link>/blog/debian-updates/</link>
				<pubDate>Wed, 13 Jan 2021 00:00:00 +0000</pubDate>
				<guid>/blog/debian-updates/</guid>
				<description>How to improve security by enabling automatic security updates on debian</description>
					<content:encoded><![CDATA[<p>Debian is a good operating system. Forming the basis for Ubuntu, Kali Linux and
many others it is one of the most stable operating systems out there.</p>
<p>





  <img
    src="/img/deb-updates/debian.png"
    width="720"
    height="360"
    alt="Image of the Debian Logo"
  />

</p>
<p>In this post, I will go over how to configure automatic security updates on
Debian, which are not enabled by default.</p>
<h2 id="introduction">Introduction</h2>
<p>Debian uses the <code>apt</code> package manager. A system update is done with the
following commands:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> apt update
</span></span><span class="line"><span class="cl"><span class="gp">$</span> apt upgrade
</span></span></code></pre></div><h2 id="the-importance-of-security-updates">The importance of security updates</h2>
<p>Security updates contain fixes for security vulnerabilities. They are an
overlooked protection measure against many attacks.</p>
<p>In 2017 there was a ransomware attack named
<a href="https://www.kaspersky.com/resource-center/threats/ransomware-wannacry">Wannacry</a>.
All the infected computers had one thing in common. They weren&rsquo;t updated.</p>
<p>Updating a system regularly can prevent lots of attacks.</p>
<p>





  <img
    src="/img/deb-updates/hacker.webp"
    width="2000"
    height="2000"
    alt="Ilustration of a Hacker"
  />

</p>
<h2 id="why-automate">Why Automate?</h2>
<p>Performing manual updates is repetitive and can be a huge burden to system
administrators.</p>
<h2 id="setting-up-automatic-updates">Setting up automatic updates</h2>
<p>First update the package list.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> apt update
</span></span></code></pre></div><p>Install these 2 packages</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> apt install unattended-upgrades apt-listchanges
</span></span></code></pre></div><p>Perform a quick configuration</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo dpkg-reconfigure -plow unattended-upgrades
</span></span></code></pre></div><p>At this point, automatic upgrades have been configured and will run every 24
hours.</p>
<h2 id="automatic-reboots">Automatic reboots</h2>
<p>The next thing is to set up automatic reboots. Some updates such as those to the
Linux kernel require a reboot.</p>
<p> 1. With a text editor open the <code>unattended-upgrades</code> configuration file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> vim /etc/apt/apt.conf.d/50unattended-upgrades
</span></span></code></pre></div><p> 2. Uncomment the line with <code>Automatic-Reboot</code> and set it to True.</p>
<pre tabindex="0"><code class="language-config" data-lang="config">Unattended-Upgrade::Automatic-Reboot &#34;true&#34;;
</code></pre><p> 3. This step is not neccesary but makes updates predictable.</p>
<pre tabindex="0"><code class="language-config" data-lang="config">Unattended-Upgrade::Automatic-Reboot-Time &#34;23:00&#34;;
</code></pre><p><em>Commented lines are those that start with two slashes <code>//</code> , remove the slashes
to uncomment the lines.</em></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// This line is commented
</span></span></span><span class="line"><span class="cl"><span class="n">This</span> <span class="n">line</span> <span class="n">is</span> <span class="n">not</span> <span class="n">commented</span>
</span></span></code></pre></div><h2 id="live-patching">Live Patching</h2>
<p>If server uptime is important to you, a good solution is
<a href="https://ubuntu.com/livepatch">Livepatch</a> by Cannonical, the company behind
Ubuntu. It is free for up to 3 devices.</p>
<blockquote>
<p><strong>Livepatch</strong> allows you to install some critical kernel security updates
without rebooting your system, by directly patching the running kernel. &hellip;
It&rsquo;s mainly intended for servers which are supposed to have months and years
of continuous uptime without reboots</p>
</blockquote>
<p><a href="https://mkyong.com/linux/an-introduction-to-kernel-live-patching-on-linux/">More info on kernel live patching</a>.</p>
<h2 id="alerts-on-update-failure">Alerts on update failure</h2>
<p>Debian is a very stable OS, however, updates can fail when using software that
is not in the official repos. When that happens you will want to receive an
alert.</p>
<p>I will be setting up email alerts in case of update failure.</p>
<h2 id="configuring-unattended-upgrades-to-send-email">Configuring <code>unattended-upgrades</code> to send email</h2>
<ol>
<li>With a text editor modify the following lines in the <code>unattended-upgrades</code>
configuration file</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ vim /etc/apt/apt.conf.d/50unattended-upgrades
</span></span></code></pre></div><ol start="2">
<li>Uncomment and modify these lines.</li>
</ol>
<pre tabindex="0"><code>Unattended-Upgrade::Mail &#34;your@email.address&#34;;
Unattended-Upgrade::MailOnlyOnError &#34;true&#34;;
</code></pre><h2 id="setting-up-postfix-to-send-email">Setting up postfix to send email</h2>
<p>To send the email alerts you need a working email setup. For this, I will be
using postfix to send email from a Gmail account</p>
<h3 id="create-an-app-password">Create an app password</h3>
<p>If you use Gmail, a good way to control access is by using app passwords. I use
this method because I can revoke app passwords in case of compromise.</p>
<blockquote>
<p>An App Password is a 16-digit passcode that gives a non-Google app or device
permission to access your Google Account</p>
</blockquote>
<ol>
<li>To create an app password, go to the Google account
<a href="https://myaccount.google.com/security">security page</a> while signed in.</li>
<li>Under <em>Signing into Google</em> , Select App Passwords</li>
<li>Generate a custom App password, name it to something relevant like <em>server-x
email alerts</em> and copy it. We&rsquo;ll need it later.</li>
</ol>
<p>





  <img
    src="/img/deb-updates/app-passwords.webp"
    width="1007"
    height="689"
    alt=""
  />

</p>
<h3 id="install-and-configure-postfix">Install and Configure Postfix</h3>
<p>The next thing is to install Postfix and other required packages. They are
required to send emails using the app passwords we just created.</p>
<ol>
<li>Install <code>postfix</code>, <code>libsasl</code> and <code>bsd-mailx</code></li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> apt install postfix libsasl2-modules bsd-mailx
</span></span></code></pre></div><p>When prompted, select Internet site.</p>
<p>





  <img
    src="/img/deb-updates/postfix.webp"
    width="720"
    height="405"
    alt=""
  />

</p>
<h3 id="configure-postfix">Configure postfix</h3>
<p>The first step is to configure postfix. Follow these steps.</p>
<ol>
<li>Open the postfix configuration file.</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> vim /etc/postfix/main.cf
</span></span></code></pre></div><ol start="2">
<li>Find the line with <code>relayhost</code> and add this.</li>
</ol>
<pre tabindex="0"><code class="language-config" data-lang="config">relayhost = [smtp.gmail.com]:587
</code></pre><h4 id="set-up-tls">Set up TLS</h4>
<p>The next step is to configure TLS. It stands for Transport Layer Security This
ensures the email contents and credentials are encrypted in transit.</p>
<ol>
<li>Open the postfix configuration file.</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> vim /etc/postfix/main.cf
</span></span></code></pre></div><ol start="2">
<li>Append the following lines to the end of the file</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Enable SASL authentication</span>
</span></span><span class="line"><span class="cl"><span class="nv">smtp_sasl_auth_enable</span> <span class="o">=</span> yes
</span></span><span class="line"><span class="cl"><span class="c1"># Disallow methods that allow anonymous authentication</span>
</span></span><span class="line"><span class="cl"><span class="nv">smtp_sasl_security_options</span> <span class="o">=</span> noanonymous
</span></span><span class="line"><span class="cl"><span class="c1"># Location of sasl_passwd</span>
</span></span><span class="line"><span class="cl"><span class="nv">smtp_sasl_password_maps</span> <span class="o">=</span> hash:/etc/postfix/sasl/sasl_passwd
</span></span><span class="line"><span class="cl"><span class="c1"># Enable STARTTLS encryption</span>
</span></span><span class="line"><span class="cl"><span class="nv">smtp_tls_security_level</span> <span class="o">=</span> encrypt
</span></span><span class="line"><span class="cl"><span class="c1"># Location of CA certificates</span>
</span></span><span class="line"><span class="cl"><span class="nv">smtp_tls_CAfile</span> <span class="o">=</span> /etc/ssl/certs/ca-certificates.crt
</span></span></code></pre></div><h4 id="set-up-the-credentials">Set up the credentials</h4>
<p>The next step is to configure postfix to use the Gmail app passwords we have
created.</p>
<ol>
<li>Open <code>/etc/postfix/sasl/sasl_passwd</code></li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> vim /etc/postfix/sasl/sasl_passwd
</span></span></code></pre></div><ol start="2">
<li>Add the following contents</li>
</ol>
<pre tabindex="0"><code class="language-config" data-lang="config">[smtp.gmail.com]:587 yourusername@gmail.com:password
</code></pre><ol start="3">
<li>Generate the password database</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> postmap /etc/postfix/sasl/sasl_passwd
</span></span></code></pre></div><h4 id="secure-the-credentials">Secure the credentials</h4>
<p>By default, the files containing the email credentials are readable by everyone.
We can change this.</p>
<ol>
<li>Modify the permissions so that the root user owns them with <code>chown</code></li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ sudo chown root:root /etc/postfix/sasl/sasl_passwd <span class="se">\
</span></span></span><span class="line"><span class="cl">   /etc/postfix/sasl/sasl_passwd.db
</span></span></code></pre></div><ol start="2">
<li>With <code>chmod</code>, change the permissions so that only root can the file.</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo chmod <span class="m">0600</span> /etc/postfix/sasl/sasl_passwd <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="go">    /etc/postfix/sasl/sasl_passwd.db
</span></span></span></code></pre></div><ol start="3">
<li>Restart Postfix</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> systemctl restart postfix
</span></span></code></pre></div><h4 id="test-the-email-setup">Test the email setup</h4>
<ol>
<li>Send yourself a test email from the terminal</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> <span class="nb">echo</span> <span class="s2">&#34;Test completed&#34;</span> <span class="p">|</span> mail -s “Test From server” your_email@gmail.com
</span></span></code></pre></div><p>If the email is received, then congratulations. The email setup is comlete. You
now have:</p>
<ul>
<li>Automatic daily updates</li>
<li>Automatic reboots</li>
<li>A feedback system incase updates fail</li>
</ul>
<h2 id="image-credits">Image Credits</h2>
<p>Illustrations from <a href="https://stories.freepik.com">Stories by Freepik</a></p>
]]></content:encoded>
			</item>
			<item>
				<title>Building a Pentest lab with Docker</title>
				<link>/docker-lab/</link>
				<pubDate>Sat, 13 Jun 2020 14:30:00 +0300</pubDate>
				<guid>/docker-lab/</guid>
				<description>Lightweight lab entirely in Docker without Vmware or VirtualBox</description>
					<content:encoded><![CDATA[<h2 id="what-is-docker">What is Docker?</h2>
<p>





  <img src="/img/docker-lab/docker.svg" alt="Docker Logo" />

</p>
<p>Docker is a container platform that is similar to a Hypervisor like Virtualbox.
Containers use less storage and RAM and are portable.</p>
<p>Docker can run on:</p>
<ul>
<li>Linux</li>
<li>Windows</li>
<li>Mac OS</li>
</ul>
<p>In this article I will go over how to set up a penetration testing lab entirely
in docker</p>
<p>It will consist of two types of containers.</p>
<ol>
<li>Attacker Machine</li>
<li>Target Machines</li>
</ol>
<h2 id="installation-on-linux">Installation on Linux</h2>
<p>The Docker engine is in the official repositories of most Linux distributions.</p>
<h3 id="ubuntudebian">Ubuntu/Debian</h3>
<p>





  <img src="/img/docker-lab/ubuntu.svg" alt="" />

</p>
<p>Anything that uses <code>apt</code> to install software is Debian based.</p>
<p>To install docker:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo apt install docker.io
</span></span></code></pre></div><h3 id="fedora">Fedora</h3>
<p>To install on fedora:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo dnf install docker
</span></span></code></pre></div><p>Start the Docker service</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo systemctl start docker
</span></span></code></pre></div><h3 id="archmanjaro">Arch/Manjaro</h3>
<p>To install Arch based distros:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo pacman -Syu
</span></span></code></pre></div><p>Enable the loop kernel module</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo tee /etc/modules-load.d/loop.conf <span class="o">&lt;&lt;&lt;</span> <span class="s2">&#34;loop&#34;</span>
</span></span><span class="line"><span class="cl"><span class="gp">$</span> modprobe loop
</span></span></code></pre></div><p>Install Docker</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo pacman -S docker
</span></span></code></pre></div><p>Start and enable the service</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo systemctl start docker.service
</span></span><span class="line"><span class="cl"><span class="gp">$</span> sudo systemctl <span class="nb">enable</span> docker.service
</span></span></code></pre></div><h2 id="hello-world">Hello World</h2>
<p>After you have installed docker, run this command as a test</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker run hello-world
</span></span></code></pre></div><p>If it completes successfully, you can follow along</p>
<p>![](img/docker-lab/Server status-pana.svg)</p>
<h2 id="the-network">The Network</h2>
<p>The network will be called <code>vulnerable</code>. It will have a 10.0.0/24 subnet</p>
<p>Create it with this command</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker network create vulnerable --attachable --subnet 10.0.0.0/24
</span></span></code></pre></div><h2 id="attacker-container">Attacker Container</h2>
<p>For this, I will use Parrot OS. It&rsquo;s docker images are better Kali Linux Images.</p>
<p>





  <img src="/img/docker-lab/cyberr.svg" alt="" />

</p>
<p>First download the Parrot OS Docker image. This command will take a while
depending on your internet connection.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> docker pull parrotsec/security:latest
</span></span></code></pre></div><p>Create and run the container .</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo docker run <span class="se">\
</span></span></span><span class="line"><span class="cl">    --name parrot <span class="se">\
</span></span></span><span class="line"><span class="cl">    -it <span class="se">\
</span></span></span><span class="line"><span class="cl">    --hostname parrot <span class="se">\
</span></span></span><span class="line"><span class="cl">    --network vulnerable <span class="se">\
</span></span></span><span class="line"><span class="cl">    --ip<span class="o">=</span><span class="s2">&#34;10.0.0.2&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --env <span class="nv">DISPLAY</span><span class="o">=</span><span class="nv">$DISPLAY</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    -v /dev/shm:/dev/shm <span class="se">\
</span></span></span><span class="line"><span class="cl">    --device /dev/snd <span class="se">\
</span></span></span><span class="line"><span class="cl">    --device /dev/dri <span class="se">\
</span></span></span><span class="line"><span class="cl">    --mount <span class="nv">type</span><span class="o">=</span>bind,src<span class="o">=</span>/tmp/.X11-unix,dst<span class="o">=</span>/tmp/.X11-unix <span class="se">\
</span></span></span><span class="line"><span class="cl">    parrotsec/security:latest <span class="se">\
</span></span></span><span class="line"><span class="cl">    /bin/bash
</span></span></code></pre></div><p>All tools available in Parrot OS are now an <code>apt-get</code> away.</p>
<p>Use this command to restart the parrot OS container after a reboot.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker start -a parrot
</span></span></code></pre></div><h2 id="target-containermetasploitable2">Target container:Metasploitable2</h2>
<p>





  <img src="/img/docker-lab/Target-pana.svg" alt="" />

</p>
<p>This is a very vulnerable test machine. It is what I recommend for anyone
starting out.</p>
<p>Open another terminal and pull the metasploitable image. The image is around
500MB.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> docker pull tleemcjr/metasploitable2
</span></span></code></pre></div><p>To run a metasploitable container:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run <span class="se">\
</span></span></span><span class="line"><span class="cl">    -it <span class="se">\
</span></span></span><span class="line"><span class="cl">    --network vulnerable <span class="se">\
</span></span></span><span class="line"><span class="cl">    --ip<span class="o">=</span><span class="s2">&#34;10.0.0.3&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    --name metasploitable <span class="se">\
</span></span></span><span class="line"><span class="cl">    --hostname metasploitable2 <span class="se">\
</span></span></span><span class="line"><span class="cl">    tleemcjr/metasploitable2 <span class="se">\
</span></span></span><span class="line"><span class="cl">    bash
</span></span></code></pre></div><p>You should see a terminal prompt like this</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">root@metasploitable2:/#
</span></span></span></code></pre></div><p>Start the vulnerable services</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">root@metasploitable2:/# services.sh
</span></span></span></code></pre></div><p>You can now access metasploitable from <a href="http://10.0.0.3">10.0.0.3</a></p>
<p>If you want to stop the container, close the terminal with <code>CTRL + D</code></p>
<p>Run this command to start metasploitable again</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker start -a parrot
</span></span></code></pre></div><p>Then start the vulnerable services.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">root@metasploitable2:/# services.sh
</span></span></span></code></pre></div><h2 id="guides--tutorials">Guides &amp; Tutorials</h2>
<p>There are tons of free guides out there on metasploitable.</p>
<p>





  <img src="/img/docker-lab/read.svg" alt="" />

</p>
<ol>
<li><a href="https://www.exploit-db.com/docs/english/44040-the-easiest-metasploit-guide-you%E2%80%99ll-ever-read.pdf">The Easiest Metasploit Guide You’ll Ever Read</a></li>
<li><a href="https://www.offensive-security.com/metasploit-unleashed/">Metasploit Unleashed</a></li>
<li><a href="https://metasploit.help.rapid7.com/docs/metasploitable-2-exploitability-guide">Metasploitable 2 Exploitability Guide</a></li>
<li><a href="https://www.youtube.com/results?search_query=metasploitable">Youtube Tutorials</a></li>
</ol>
<p>If you don&rsquo;t know what guide to use, I recommend
<a href="https://metasploit.help.rapid7.com/docs/metasploitable-2-exploitability-guide">this one</a>.</p>
<h2 id="more-vulnerable-containers-">More vulnerable containers 🧑‍💻</h2>
<p>





  <img src="/img/docker-lab/hacker.svg" alt="" />

</p>
<p>You can extend the lab with any of these containers depending on your learning
goal.</p>
<h3 id="owasp-juiceshop">OWASP Juiceshop</h3>
<p>This container focusses on web application security.</p>
<p>





  <img src="/img/docker-lab/juiceshop.svg" alt="" />

</p>
<p>To create and start the juiceshop container for the first time</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run -d <span class="se">\
</span></span></span><span class="line"><span class="cl">    --name juiceshop <span class="se">\
</span></span></span><span class="line"><span class="cl">    --network vulnerable <span class="se">\
</span></span></span><span class="line"><span class="cl">    --ip<span class="o">=</span><span class="s2">&#34;10.0.0.6&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    bkimminich/juice-shop
</span></span></code></pre></div><p>Check if it is running</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> docker ps
</span></span></code></pre></div><p>Access the web interface from this URL</p>
<p><a href="http://10.0.0.6:3000/">http://10.0.0.6:3000/</a></p>
<p>Stop the container when you&rsquo;re done</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">docker stop juiceshop
</span></span></span></code></pre></div><p>Start the container again</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">docker start juiceshop
</span></span></span></code></pre></div><h2 id="juiceshop-guides">Juiceshop Guides</h2>
<ul>
<li><a href="https://pwning.owasp-juice.shop/">Pwning Juiceshop</a></li>
<li><a href="https://www.youtube.com/results?search_query=owasp+juiceshop">Youtube Videos</a></li>
</ul>
<h2 id="owasp-webgoat-">OWASP Webgoat 🐐</h2>
<p><a href="(https://owasp.org/www-project-webgoat/)">Webgoat</a> is a ctf-style vulnerable
container focused on web application security.</p>
<p>





  <img src="/img/docker-lab/goat.svg" alt="" />

</p>
<p>Create and run the container for the first time</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run  -d <span class="se">\
</span></span></span><span class="line"><span class="cl">    --name webgoat <span class="se">\
</span></span></span><span class="line"><span class="cl">    --network vulnerable <span class="se">\
</span></span></span><span class="line"><span class="cl">    --ip<span class="o">=</span><span class="s2">&#34;10.0.0.4&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    -e <span class="nv">TZ</span><span class="o">=</span><span class="k">$(</span>cat /etc/timezone<span class="k">)</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    webgoat/goatandwolf
</span></span></code></pre></div><p>Access Webgoat and Webwolf from these URLs</p>
<p><a href="http://10.0.0.4:8080/WebGoat">10.0.0.4:8080/WebGoat</a></p>
<p><a href="http://10.0.0.4:9090/WebWolf">10.0.0.4:9090/WebWolf</a></p>
<p>To stop the container</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">docker stop webgoat
</span></span></span></code></pre></div><p>To Start the container again.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">docker start webgoat
</span></span></span></code></pre></div><p>If you can&rsquo;t access the url, check if it is running.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> docker ps -a
</span></span></code></pre></div><h2 id="why-i-use-docker-for-a-pentest-lab">Why I use docker for a pentest lab</h2>
<p>Two Operating systems make my computer painfully slow. Containers aren&rsquo;t
resource-intensive and perform well. This fits my use case.</p>
<p>





  <img src="/img/docker-lab/lab.svg" alt="" />

</p>
<p>If you have RAM to spare then it&rsquo;s really not that much of a difference.</p>
<h2 id="when-not-to-use-docker">When not to use Docker</h2>
<p>If you want to run Windows containers on a Linux host. You can run linux
containers on WIndows though</p>
<h2 id="common-docker-commands">Common Docker Commands</h2>
<p>Stop a container:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker stop containerName
</span></span></code></pre></div><p>Start a container</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker start containerName
</span></span></code></pre></div><p>List running and stopped containers</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker ps -a
</span></span></code></pre></div><p>Spawn a bash shell in a running container</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> sudo docker <span class="nb">exec</span> -it containerName bash
</span></span></code></pre></div><p>Docker has tab completion for each of these commands.</p>
<h2 id="graphical-apps-inside-docker">Graphical apps inside docker</h2>
<p>Sometimes you may want to run a GUI tool like firefox or burpsuite.</p>
<p>The Parrot OS commands above are already set for running graphical apps. You
only need to install these packages</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> apt install hicolor-icon-theme <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="go">    libcanberra-gtk* libgl1-mesa-dri \
</span></span></span><span class="line"><span class="cl"><span class="go">    libgl1-mesa-glx libpangox-1.0-0 \
</span></span></span><span class="line"><span class="cl"><span class="go">    libpulse0 libv4l-0 fonts-symbola \
</span></span></span></code></pre></div><p>You can run a few commands to avoid some errors encountered when running GUI
apps</p>
<h3 id="burpsuite">Burpsuite</h3>
<p>Burp Suite is a web app pentesting tool for monitoring http requests and
responses.</p>
<p>





  <img src="/img/docker-lab/burp.svg" alt="" />

</p>
<p>To install and run burpsuite inside the parrot os container.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> sudo apt update
</span></span><span class="line"><span class="cl"><span class="gp">#</span> sudo apt install burpsuite
</span></span><span class="line"><span class="cl"><span class="gp">#</span> java -jar -Xmx2G /usr/bin/burpsuite
</span></span></code></pre></div><p>You can then point your browser to use <code>10.0.0.2:8080</code> as the proxy and burp
will intercept everything</p>
<h3 id="firefox">Firefox</h3>
<p>Firefox, is a free and open-source web browser.</p>
<p>





  <img src="/img/docker-lab/firefox.svg" alt="" />

</p>
<p>To install and run firefox:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> apt install firefox ca-certificates
</span></span></code></pre></div><h2 id="credits">Credits</h2>
<p>Illustrations from <a href="https://stories.freepik.com/">Freepik</a></p>
<h2 id="further-readingresearch">Further reading/research</h2>
<p>Jess Frazelle has written an awesome
<a href="https://blog.jessfraz.com/post/docker-containers-on-the-desktop/">blog post</a>
with details on running graphical apps inside Docker containers. She&rsquo;s also
given this awesome <a href="https://youtu.be/cYsVvV1aVss">Talk/Demo</a> on running various
applications and retro games inside docker containers.</p>
]]></content:encoded>
			</item>
			<item>
				<title>Running my website on $1 monthly</title>
				<link>/blog/site-cost/</link>
				<pubDate>Tue, 19 May 2020 14:30:00 +0300</pubDate>
				<guid>/blog/site-cost/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://ianmuchina.com/blog/meta-update/&#34;&gt;Updated version&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This website costs me almost nothing to run. I take advantage of a few free&#xA;services. This site is&#xA;&lt;a href=&#34;https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fianmuchina.com%2F&#34;&gt;fast&lt;/a&gt;&#xA;and looks okay. Here&amp;rsquo;s what I use.&lt;/p&gt;&#xA;&lt;h2 id=&#34;1-dns--cloudflare&#34;&gt;1. DNS : Cloudflare&lt;/h2&gt;&#xA;&lt;p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;  &lt;img src=&#34;./img/site-cost/cloudflare.svg&#34; alt=&#34;cloudflare logo&#34; /&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;DNS is what enables the translation of website names to IP addresses. I use&#xA;Cloudflare to manage the DNS of my domain at &lt;code&gt;ianmuchina.com&lt;/code&gt;. I can have&#xA;unlimited subdomains.&lt;/p&gt;&#xA;&lt;h2 id=&#34;2-cdn-cloudflare&#34;&gt;2. CDN: Cloudflare&lt;/h2&gt;&#xA;&lt;p&gt;Cloudflare have over 200 datacenters worldwide meant for just this purpose.&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;  &lt;img&#xA;    src=&#34;./img/site-cost/cloudflare-network.webp&#34;&#xA;    width=&#34;900&#34;&#xA;    height=&#34;578&#34;&#xA;    alt=&#34;cloudflare nodes map&#34;&#xA;  /&gt;&#xA;&#xA;&lt;/p&gt;</description>
					<content:encoded><![CDATA[<blockquote>
<p><a href="https://ianmuchina.com/blog/meta-update/">Updated version</a></p>
</blockquote>
<p>This website costs me almost nothing to run. I take advantage of a few free
services. This site is
<a href="https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fianmuchina.com%2F">fast</a>
and looks okay. Here&rsquo;s what I use.</p>
<h2 id="1-dns--cloudflare">1. DNS : Cloudflare</h2>
<p>





  <img src="/img/site-cost/cloudflare.svg" alt="cloudflare logo" />

</p>
<p>DNS is what enables the translation of website names to IP addresses. I use
Cloudflare to manage the DNS of my domain at <code>ianmuchina.com</code>. I can have
unlimited subdomains.</p>
<h2 id="2-cdn-cloudflare">2. CDN: Cloudflare</h2>
<p>Cloudflare have over 200 datacenters worldwide meant for just this purpose.






  <img
    src="/img/site-cost/cloudflare-network.webp"
    width="900"
    height="578"
    alt="cloudflare nodes map"
  />

</p>
<p>When using Cloudflare&rsquo;s Content Delivery Network, someone in Nairobi gets the
site assets from a datacenter in Mombasa instead of somewhere further like
France or USA.</p>
<p>A content delivery network greatly improves speed.</p>
<h2 id="4-framework--jekyll">4. Framework : Jekyll</h2>
<p>





  <img src="/img/site-cost/jekyll.svg" alt="Jekyll logo" />

</p>
<p>I use Jekyll to generate the static files of my website. Jekyll has some awesome
free themes. However it can take a bit of time to configure for those not
familiar with it.</p>
<h2 id="5-hosting-netlify--github">5. Hosting: Netlify + GitHub</h2>
<p>





  <img src="/img/site-cost/Netlify_logo.svg" alt="Netlify and github logo" />

</p>
<p>Netlify is what builds my site from the configuration files of my site. I use
netlify with github. The static content is regenerated anytime I modify the
config files</p>
<h2 id="6-domain-registrar---cloudflare">6. Domain Registrar - Cloudflare</h2>
<p>





  <img src="/img/site-cost/Namecheap-Logo.svg" alt="cloudflare logo" />

</p>
<p>One gets a domain from a domain registrar. You can get a free one from
<a href="https://www.freenom.com">Freenom</a>. I have a freenom domain that I dont use at
muchina.gq, but I abandoned it in favor of ianmuchina.com. Most .com domains are
not that expensive and cost around $12 per year.</p>
<h2 id="7-ssl-cloudflare">7. SSL: Cloudflare</h2>
<p>





  <img src="/img/site-cost/ssl.svg" alt="picture showing SSL in action in the browser" />

</p>
<p>A site with SSL correctly configured has a padlock alongside the domain name.
When using the cloudflare CDN, your site automatically gets free SSL</p>
<h2 id="tldr">TLDR</h2>
<p>Take advantage of Cloudflare &amp; Github Pages and just pay for the domain._</p>
]]></content:encoded>
			</item>
			<item>
				<title>Why SSH certificates are awesome</title>
				<link>/blog/ssh-certificates/</link>
				<pubDate>Fri, 15 May 2020 11:30:00 +0300</pubDate>
				<guid>/blog/ssh-certificates/</guid>
				<description>How Certificates are used by big tech companies to secure thousands of servers</description>
					<content:encoded><![CDATA[<p>Big Tech companies such as Facebook, Google, Netflix, Uber with thousands of
users and servers use SSH Certificates to manage access. This post will go over
why that&rsquo;s the case</p>
<h2 id="what-is-ssh">What is SSH?</h2>
<p>SSH is a protocol used by system administrators and developers to communicate
securely with a server. Authentication can be done with SSH keys or passwords.</p>
<h2 id="passwords-and-why-theyre-not-recommended">Passwords and why they’re not recommended</h2>
<p>We all know passwords and have used them at some point. Those secret string of
characters you have to remember to prove your identity.</p>
<p>





  <img
    src="/img/ssh_certs/2fYbsnl.png.webp"
    width="2000"
    height="2000"
    alt="How many times have you forgotten your password?"
  />

</p>
<p>Passwords are good and better than nothing, but securing a server with just a
password is not recommended especially on critical systems.</p>
<ol>
<li>Weak passwords can be brute-forced</li>
<li>Sometimes passwords have to be shared for group accounts.</li>
<li>Only one compromised server is enough to phish all user credentials.</li>
<li>Revocation of compromised user passwords is not easy or convenient</li>
<li>Without a second factor, they are a single point of failure</li>
</ol>
<p>You can improve the security by using tools like fail2ban to block IP addresses
that have multiple failed login attempts.</p>
<h2 id="why-use-keys">Why use keys?</h2>
<p>Keys are the default authentication method on most cloud providers eg: Digital
Ocean. There is a good reason for this. Keys are more secure than passwords</p>
<blockquote>
<p>SSH keys are a matching set of cryptographic keys which can be used for
authentication.</p>
</blockquote>
<p>





  <img
    src="/img/ssh_certs/jC5HqKn.png.webp"
    width="1143"
    height="1143"
    alt="Keys are awesome"
  />

</p>
<blockquote>
<p>Each set contains a public and a private key. The public key can be shared
freely without concern, while the private key must be vigilantly guarded and
never exposed to anyone. source</p>
</blockquote>
<h2 id="why-ssh-keys-are-more-secure">Why SSH Keys are more secure</h2>
<ul>
<li>One user account can have multiple keys. This makes auditing easier</li>
<li>Keys can be password protected. Note the password is just for unlocking the
key and never sent to the server</li>
<li>Keys can be combined with passwords</li>
<li>Keys can be revoked</li>
</ul>
<p>Keys are created with the <code>ssh-keygen</code> command.</p>
<p>When creating keys, it is a good idea to encrypt them with a password. So that
even if the key is leaked, the password will add another layer of security.</p>
<h2 id="managing-ssh-keys">Managing SSH keys</h2>
<p>To connect to a server using keys, a user’s public key has to be in the
authorized_keys file on every server they want to connect to.</p>
<p>This method of managing keys is the most common and works okay for small teams
but it can be a burden for large organizations with many users.






  <img
    src="/img/ssh_certs/RHoK5W9.png.webp"
    width="1286"
    height="857"
    alt="Managing keys is a pain"
  />

</p>
<blockquote>
<p>But growth creeps upon you, and before you know it you are securing
significant assets with sub-standard methods</p>
</blockquote>
<p>Key management issues</p>
<ul>
<li>The <code>authorized_keys file</code> on all servers has to be maintained regularly</li>
<li>Issuing a new key is a long process</li>
<li>Losing a key locks you out</li>
</ul>
<p>The task of updating the <code>authorized_keys</code> file can and should be automated for
large companies. This method &ldquo;works&rdquo; but there is a much better alternative</p>
<h2 id="ssh-certificates">SSH Certificates</h2>
<p>This is where public keys are signed by a Certificate Authority(CA). This method
scales very well across thousands of machines. It can be used for both user and
host verification. This method eliminates the Trust on first use requirement.






  <img
    src="/img/ssh_certs/KnaoAHm.png.webp"
    width="2000"
    height="2000"
    alt="Certificates are never talked about that much"
  />

</p>
<h3 id="advantages-of-certificates">Advantages of certificates</h3>
<p>SSH certificates are underrated and awesome in my opinion. They have some good
features:</p>
<ul>
<li>Server configuration is done only once</li>
<li>Updating the <code>authorized_keys</code> file on every server is not needed.</li>
<li>Audits are easier since every key is unique</li>
<li>Works perfectly for giving users access to offline/air-gapped servers</li>
<li>Keys can expire</li>
</ul>
<h2 id="available-metadata">Available Metadata</h2>
<p>The signed key can contain the following useful information</p>
<h3 id="1-key-expiry-date--time">1. Key Expiry date &amp; time</h3>
<p>This is how long a key is valid. The value can range from minutes to years.
Netflix set their certificates to expire after two minutes. That&rsquo;s enough time
for a developer to login into a server and start an ssh session. Note that the
session does not terminate when a certificate expires, only when a user logs out</p>
<h4 id="2-principals">2. Principals</h4>
<p>Principals control which user accounts and hosts a user has access to. For
example, there can be a <code>root_staging</code> principal which allows users to login as
root on a staging server</p>
<p>You can Parse this data offline with <code>ssh-keygen -Lf /Path/To/Signed_Cert</code></p>
<p>You can also use
<a href="https://gravitational.com/resources/ssh-certificate-parser/">this site</a></p>
<h2 id="open-source-implementations">Open Source Implementations</h2>
<p>There are many solutions to giving users SSH access. All these are available on
GitHub. Note that documentation is not that good for some tools though






  <img
    src="/img/ssh_certs/uphOO5p.png.webp"
    width="2000"
    height="2000"
    alt=""
  />

</p>
<h3 id="1-keybase-certificate-authority-bot">1. <a href="https://keybase.io/blog/keybase-ssh-ca">Keybase Certificate Authority bot</a></h3>
<p>This is a keybase chatbot that signs public keys. it is cli based. The bot
doesn&rsquo;t need any ports open.</p>
<ul>
<li>Used internaly @ Keybase</li>
<li>Only supports keybase Authentication</li>
<li>Good <a href="https://keybase-ssh-ca-bot.readthedocs.io/en/latest/">Documentation</a></li>
</ul>
<p><a href="https://keybase.io/blog/keybase-ssh-ca">Blog post</a> on keybase SSH</p>
<h4 id="2-cashier">2. <a href="https://github.com/nsheridan/cashier">Cashier </a></h4>
<ul>
<li>Controlled via a web interface</li>
<li>Integrates well with LDAP or Active Directory</li>
<li>Google, Github or Gitlab login available</li>
<li>Key revocation page</li>
</ul>
<p><a href="https://youtu.be/NCEQj27A3XA">Video</a> on The Tool</p>
<h4 id="3-bless---by-netflix">3. <a href="https://github.com/Netflix/bless">BLESS - By Netflix</a></h4>
<ul>
<li>Used internally @ Netflix,</li>
<li>Runs on AWS Lambda</li>
<li><a href="https://youtu.be/JwLGsWYVjqU">Video</a> on the tool</li>
</ul>
<h4 id="4-sshrimp---by-stoggi">4. <a href="https://github.com/stoggi/sshrimp">SSHrimp - by Stoggi</a></h4>
<ul>
<li>Runs on AWS Lambda</li>
<li>Authenticate with OpenID connect</li>
<li>Still in Beta</li>
</ul>
<h3 id="5-keymaster---symantec">5. <a href="https://github.com/Cloud-Foundations/keymaster">Keymaster - Symantec</a></h3>
<ul>
<li>Supportts Oauth2 login</li>
<li>Integrates well with LDAP/Active Directory</li>
<li>Made by Symantec</li>
<li><a href="https://github.com/Cloud-Foundations/keymaster/blob/master/docs/Keymaster-DesignDoc.md">Documentation</a></li>
</ul>
<p><em>More Tools</em></p>
<ul>
<li><a href="https://github.com/smallstep/certificates">Smallstep CA</a></li>
<li><a href="https://github.com/uber/pam-ussh">Uber&rsquo;s PAM module</a></li>
</ul>
<h3 id="video-resources">Video Resources</h3>
<p>For those that prefer videos to blog posts</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=GSIDS_lvRv4">Public key Cryptography Explained</a></li>
<li><a href="https://www.youtube.com/watch?v=vsXMMT2CqqE">The Key Exchange Problem</a></li>
<li><a href="https://www.youtube.com/playlist?list=PLYiD9Y1aw76Y0NlUeFDl_YWfkZmdRcYpj">Conference Talks on SSH Certificates</a></li>
</ul>
<h2 id="further-reading">Further Reading</h2>
<p>I&rsquo;m not the first one to write about this topic, so here&rsquo;s related content
covering it</p>
<h3 id="blog-posts">Blog Posts</h3>
<ul>
<li><a href="https://engineering.fb.com/production-engineering/scalable-and-secure-access-with-ssh/"> How SSH is secured At Facebook</a></li>
<li><a href="https://medium.com/@dmuth/ssh-at-scale-cas-and-principals-b27edca3a5d"> SSH at scale - CAs and Principals</a></li>
<li><a href="https://gravitational.com/blog/how-to-ssh-properly/"> How to SSH Properly</a></li>
<li><a href="https://smallstep.com/blog/use-ssh-certificates/">If you’re not using SSH certificates you’re doing SSH wrong</a></li>
</ul>
<p>





  <img
    src="/img/ssh_certs/YqKOBwg.png.webp"
    width="2000"
    height="2000"
    alt=""
  />

</p>
<h3 id="whitepapers-and-manuals">Whitepapers and Manuals</h3>
<ul>
<li><a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/openssh-sssd">Redhat Deployment Guide</a></li>
<li><a href="https://nvlpubs.nist.gov/nistpubs/ir/2015/NIST.IR.7966.pdf">NIST whitepaper on SSH automation</a></li>
<li><a href="https://tools.ietf.org/html/draft-ylonen-sshkeybcp-01">IETF Memo on recomended practice</a></li>
<li><a href="https://blog.habets.se/2011/07/OpenSSH-certificates.html">ssh-keygen manual</a></li>
</ul>
<h2 id="image-credits">Image Credits</h2>
<p>Illustrations from <a href="https://stories.freepik.com">Stories by Freepik</a></p>
]]></content:encoded>
			</item>
			<item>
				<title>Isolating vocals from songs using Spleeter</title>
				<link>/blog/Spleeter/</link>
				<pubDate>Sun, 08 Mar 2020 10:00:00 +0300</pubDate>
				<guid>/blog/Spleeter/</guid>
				<description>Use AI to isolate vocals and instrumentals from songs</description>
					<content:encoded><![CDATA[<p>Isolating vocals from a song in the past has had a high barrier to entry. It is
now an easy thing to do . In this article, I will go over the various methods.</p>
<h2 id="1-the-browser-method">1. The browser method</h2>
<p>This is done entirely online. Open a browser, go to a upload a song and get
vocal and instrumental stems. This is a simple method which relies on third
party websites to process the music.</p>
<h2 id="steps">Steps</h2>
<p>The only requirement is a browser.</p>
<ol>
<li>Go to <a href="https://moises.ai/">moises.ai</a></li>
<li>Create an account</li>
<li>Upload a song</li>
<li>Wait for the isolation to be done</li>
<li>Enjoy !!</li>
</ol>
<h2 id="advantages">Advantages</h2>
<ul>
<li>Can be done from any device with a browser even a mobile phone</li>
<li>Requires no special knowledge</li>
<li>Easy user interface</li>
</ul>
<h2 id="disadvantages">Disadvantages</h2>
<ul>
<li>Only 5 uploads per month</li>
<li>There&rsquo;s a queue that may affect your waiting time</li>
</ul>
<p>You can use <a href="ezstems.com">https://ezstems.com</a> as an alternative for more upload
options and it works in a simmilar way.</p>
<h2 id="2-the-app-method">2. The App Method</h2>
<p>This second method is simmilar to the first, but only uses the computer&rsquo;s
resources. 





  <img
    src="/img/spleeter/uJrx7GI.jpg"
    width="953"
    height="598"
    alt="Screenshot of image"
  />

</p>
<h3 id="steps-1">Steps</h3>
<p>This method only works on windows</p>
<ol>
<li>Download and install the latest version of
<a href="https://www.python.org/downloads/">Python</a></li>
<li>During the installation make sure add to path checkbox is selected.</li>
<li>Download <a href="https://github.com/lazydevyo/SpleetGUI/releases">SpleetGUI</a></li>
<li>Extract the zip file</li>
<li>Install SpleetGUI</li>
</ol>
<p>*I have no idea if it is safe to use</p>
<h2 id="3-command-line-method">3. Command line Method</h2>
<p>This last is done entirely from the command line and is great for those familiar
with the command line. For this method, you will require git and
<a href="https://docs.conda.io/projects/conda/en/latest/user-guide/install/">conda</a>.</p>
<p>After they are both installed, type the following commands to install spleeter.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> git clone https://github.com/Deezer/spleeter
</span></span><span class="line"><span class="cl"><span class="gp">$</span> conda install -c conda-forge spleeter
</span></span></code></pre></div><p>To run spleeter:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> python3 -m spleeter -i your_song.mp3 -p spleeter:2stems -o output
</span></span></code></pre></div><h2 id="how-does-it-work">How Does it Work?</h2>
<p>





  <img
    src="/img/spleeter/machine-learning.webp"
    width="371"
    height="439"
    alt="xkcd comic"
  />

</p>
<p>Machine learning is artificial intelligence that can automatically learn from
past data. You give it enough data and it can literally learn like humans,
through practice</p>
<p>For more detailed information, check out the
<a href="https://github.com/deezer/spleeter/wiki/2.-Getting-started">spleeter documentation</a></p>
<h2 id="conclusion">Conclusion</h2>
<p>This is a great tool that can be used to get clean vocals from almost any song.
It also works well to de-noise a track.</p>
]]></content:encoded>
			</item>
			<item>
				<title>Tracking documents with Canarytokens</title>
				<link>/blog/canarytokens/</link>
				<pubDate>Sat, 15 Feb 2020 11:30:00 +0300</pubDate>
				<guid>/blog/canarytokens/</guid>
				<description>This post goes over how you can create a document that sends an email alert every time it is opened</description>
					<content:encoded><![CDATA[<p>The ability to track Documents might come in handy in some situations. To do
this we use Canarytokens. These are files and links that trigger email alerts
anytime anyone accesses them.</p>
<p>In this article, I will go over how to create and deploy these tokens.</p>
<h2 id="requirements">Requirements</h2>
<ul>
<li>Email Address</li>
<li>Target With An Internet Connection</li>
</ul>
<h2 id="steps">Steps</h2>
<h3 id="1-creating-the-file">1. Creating the file</h3>
<ul>
<li>Go to <a href="https://canarytokens.org">canarytokens.org</a></li>
<li>Choose either a Word Document or an Adobe PDF token</li>
<li>Enter an email address where alerts will be sent</li>
<li>Choose an appropriate reminder eg: &ldquo;Opened&rdquo;</li>
<li>Click on <em>&ldquo;Create My Canary Token&rdquo;</em></li>
<li>Download the token</li>
</ul>
<h3 id="2-setting-up-the-file">2. Setting up the file</h3>
<p>After Downloading the file you should:</p>
<ul>
<li>Rename the file</li>
<li>Edit the content of the file</li>
<li>Send the file to someone</li>
<li>Wait for an alert</li>
</ul>
<h3 id="3-receiving-alerts">3. Receiving Alerts</h3>
<p>The alerts contain:</p>
<ul>
<li>The IP address the file was opened from</li>
<li>A Reminder if you wrote one</li>
<li>The time and date when the file was opened</li>
</ul>
<p>If someone with internet access opens the document, you will be alerted. Usualy
within seconds.</p>
<h2 id="further-reading">Further Reading</h2>
<p><a href="https://docs.canarytokens.org/guide/">Official Documentation</a></p>
]]></content:encoded>
			</item>
	</channel>
</rss>
