<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <link href="https://koddsson.com/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://koddsson.com/" rel="alternate" type="text/html"/>
  <id>https://koddsson.com/</id>
  
  <updated>2018-03-18T00:00:00Z</updated>
  <author>
    <name>Kristján Oddsson</name>
    <uri>https://koddsson.com/</uri>
  </author>
  
  
  <entry>
    <title>Emojis as favicons</title>
    <link href="https://koddsson.com/posts/emoji-as-favicons/" rel="alternate" type="text/html"/>
    <id>https://koddsson.com/posts/emoji-as-favicons/</id>
    <updated>2018-03-18T00:00:00Z</updated>
    <published>2018-03-18T00:00:00Z</published>
    <summary>A blog post describing how to use JavaScript to quickly set a websites favicon to a emoji</summary>
    <content type="html">&lt;p&gt;So I was working on &lt;a href=&#34;https://jsonresume.io&#34;&gt;jsonresume.io&lt;/a&gt; this weekend and really wanted a favicon for the page. I don&#39;t know about you but I kind of dislike having to add a favicon. I don&#39;t really know how to make a icon and so I keep reaching more and more into the ever expanding unicode emoji sets.&lt;/p&gt;
&lt;p&gt;I really wanted just to drop a 📝 into a &lt;code&gt;&amp;lt;link /&amp;gt;&lt;/code&gt; tag and call it a day. As far as I knew this wasn&#39;t possible, prompting this tweet:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Which technical committee do I need to submit a proposal to in order to get emojis as favicons?  &lt;a href=&#34;https://twitter.com/WHATWG?ref_src=twsrc%5Etfw&#34;&gt;@WHATWG&lt;/a&gt; ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To make a long story short, I made my way to &lt;a href=&#34;https://whatwg.org/&#34;&gt;whatwg.org&lt;/a&gt; to figure out how to make a proposal. That lead me to this issue &lt;a href=&#34;https://github.com/whatwg/html/issues/661&#34;&gt;#661&lt;/a&gt;. That mentions that you can set the favicon dynamically with a data uri.&lt;/p&gt;
&lt;p&gt;Turns out I don&#39;t need to do a proposal at all! Even though it&#39;s not as easy as &lt;code&gt;&amp;lt;link rel=&amp;quot;icon&amp;quot; value=&amp;quot;🍕&amp;quot; /&amp;gt;&lt;/code&gt; it&#39;s still pretty straightforward if you can write some JavaScript. Here&#39;s the code I wrote to set the favicon of this post:&lt;/p&gt;
&lt;pre class=&#34;language-js&#34;&gt;&lt;code class=&#34;language-js&#34;&gt;&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; canvas &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; document&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;createElement&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#39;canvas&#39;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;
canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;height &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;64&lt;/span&gt;
canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;width &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;64&lt;/span&gt;

&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; ctx &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;getContext&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#39;2d&#39;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;
ctx&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;font &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#39;64px serif&#39;&lt;/span&gt;
ctx&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;fillText&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#39;🛰&#39;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;
console&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;toDataURL&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; favicon &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; document&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;querySelector&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#39;link[rel=icon]&#39;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;
favicon&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;href &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;toDataURL&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could even wrap this in a function and dynamically set the favicon.&lt;/p&gt;
&lt;p&gt;Let me know if you enjoyed this post on &lt;a href=&#34;https://twitter.com/koddsson&#34;&gt;twitter&lt;/a&gt; 🙌.&lt;/p&gt;
&lt;h2&gt;&lt;time datetime=&#34;2018-03-24T22:00&#34;&gt;March 24th 2018&lt;/time&gt; update.&lt;/h2&gt;
&lt;p&gt;I refined the script a bit and it ends up looking like this:&lt;/p&gt;
&lt;pre class=&#34;language-js&#34;&gt;&lt;code class=&#34;language-js&#34;&gt;&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; favicon &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; document&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;querySelector&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;link[rel=icon]&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;token keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;favicon&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; emoji &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; favicon&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;getAttribute&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;data-emoji&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

  &lt;span class=&#34;token keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;emoji&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; canvas &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; document&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;createElement&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;canvas&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
    canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;height &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
    canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;width &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; ctx &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;getContext&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;2d&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
    ctx&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;font &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;64px serif&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
    ctx&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;fillText&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;emoji&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

    favicon&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;href &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; canvas&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;toDataURL&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This change means that I only need to include this script and set the emoji I want as a favicon like so:&lt;/p&gt;
&lt;pre class=&#34;language-html&#34;&gt;&lt;code class=&#34;language-html&#34;&gt;&lt;span class=&#34;token tag&#34;&gt;&lt;span class=&#34;token tag&#34;&gt;&lt;span class=&#34;token punctuation&#34;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&#34;token attr-name&#34;&gt;rel&lt;/span&gt;&lt;span class=&#34;token attr-value&#34;&gt;&lt;span class=&#34;token punctuation attr-equals&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;&#34;&lt;/span&gt;icon&lt;span class=&#34;token punctuation&#34;&gt;&#34;&lt;/span&gt;&lt;/span&gt; &lt;span class=&#34;token attr-name&#34;&gt;data-emoji&lt;/span&gt;&lt;span class=&#34;token attr-value&#34;&gt;&lt;span class=&#34;token punctuation attr-equals&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;&#34;&lt;/span&gt;🛰&lt;span class=&#34;token punctuation&#34;&gt;&#34;&lt;/span&gt;&lt;/span&gt; &lt;span class=&#34;token attr-name&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;token attr-value&#34;&gt;&lt;span class=&#34;token punctuation attr-equals&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;&#34;&lt;/span&gt;image/png&lt;span class=&#34;token punctuation&#34;&gt;&#34;&lt;/span&gt;&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exactly what I wanted orginally! 🤙&lt;/p&gt;
&lt;!-- Include `OpenHeartElement` --&gt;
&lt;script src=&#34;https://unpkg.com/open-heart-element&#34; type=&#34;module&#34; defer&gt;&lt;/script&gt;
&lt;!-- Render `&lt;open-heart&gt;` --&gt;
&lt;p&gt;&lt;open-heart href=&#34;https://open-heart-endpoint.koddsson.workers.dev/?id=&#34; emoji=&#34;❤️&#34;&gt;♥&lt;/open-heart&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Stop trying to make things perfect</title>
    <link href="https://koddsson.com/posts/stop-trying-to-make-things-perfect/" rel="alternate" type="text/html"/>
    <id>https://koddsson.com/posts/stop-trying-to-make-things-perfect/</id>
    <updated>2022-12-13T00:00:00Z</updated>
    <published>2022-12-13T00:00:00Z</published>
    <summary>A blog post with some thoughts on perfectionism</summary>
    <content type="html">&lt;p&gt;I recently discovered the work of Tom Sachs, a contemporary artist known for his sculptural installations that often incorporate everyday objects and materials. After watching a number of his videos and reading about his creative process, I was struck by his philosophy of &amp;quot;just make the thing.&amp;quot; In other words, don&#39;t try to overthink or perfect your work before you&#39;ve even started - just get started and see where it takes you.&lt;/p&gt;
&lt;p&gt;This philosophy resonated with me, as I often struggle with perfectionism in my own creative pursuits. For example, I have been thinking about creating a physical cookbook for some time now, but I have been stuck in the planning phase, trying to figure out the perfect layout and design before I even start writing any recipes. However, after learning about Tom Sachs&#39; approach, I realized that I should just start writing down my recipes and worry about the design later. As Tom puts it, &amp;quot;Creativity is the enemy&amp;quot; - by trying to make everything perfect before we start, we risk stifling our own creativity and productivity.&lt;/p&gt;
&lt;p&gt;To illustrate this point, consider the example of my mom&#39;s old cookbook. She used to collect newspaper clippings with recipes and handwritten notes, and would mark the good ones with &amp;quot;Great!&amp;quot; and add notes to the margins. This was not a fancy or professionally-designed cookbook, but it was functional and effective for her needs. It also allowed for flexibility and growth - she could easily add new recipes or make changes to existing ones by adding pages or making notes in the margins. This is the kind of cookbook I want to create for myself - one that is functional, flexible, and easy to use in the kitchen.&lt;/p&gt;
&lt;p&gt;In conclusion, I think it&#39;s important to remember that perfectionism is often the enemy of creativity and productivity. Instead of trying to make everything perfect before we start, we should just get started and see where it takes us. By embracing the philosophy of &amp;quot;just make the thing,&amp;quot; we can open ourselves up to new possibilities and creative growth.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Implementing View Transitions on koddsson.com</title>
    <link href="https://koddsson.com/posts/implementing-view-transitions-on-koddsson.com/" rel="alternate" type="text/html"/>
    <id>https://koddsson.com/posts/implementing-view-transitions-on-koddsson.com/</id>
    <updated>2023-05-31T00:00:00Z</updated>
    <published>2023-05-31T00:00:00Z</published>
    <summary>How I implemented MPA View Transitions on koddsson.com</summary>
    <content type="html">&lt;p&gt;Welcome to a development journey post for my personal website, &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt;. Today, we&#39;ll explore how I implemented view transitions to enhance the user interface and provide a more engaging browsing experience. The changes were made in a &lt;a href=&#34;https://github.com/koddsson/koddsson.com/pull/53&#34;&gt;Pull Request titled &amp;quot;Implement View Transitions!&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;View transitions are a key part of modern web design, adding visual continuity and smoothness when moving between different views or pages on a website. They can greatly improve the user experience by reducing visual abruptness and providing a sense of spatial awareness. Inspired by this, I decided it was time to introduce this feature to my own website, &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The process of implementing view transitions involved changes in &lt;a href=&#34;https://github.com/koddsson/koddsson.com/pull/53/commits/4faeb48632e1494751add39e80a1a380db938a0b&#34;&gt;two main files&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;_layouts/default.html&lt;/code&gt;: Here, I introduced a meta tag &lt;code&gt;&amp;lt;meta name=&amp;quot;view-transition&amp;quot; content=&amp;quot;same-origin&amp;quot;&amp;gt;&lt;/code&gt; to set the view transition property. This tag indicates that we want to enable transitions for navigations to and from this page.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;css/index.css&lt;/code&gt;: This file saw a more substantial change. I added a CSS &lt;code&gt;@supports&lt;/code&gt; rule that checks if the browser supports the property &lt;code&gt;view-transition-name&lt;/code&gt;. If it does, two new properties are set: &lt;code&gt;view-transition-name: header;&lt;/code&gt; under the &lt;code&gt;header&lt;/code&gt; section and &lt;code&gt;view-transition-name: main;&lt;/code&gt; under the &lt;code&gt;main&lt;/code&gt; section. These properties enable the transitions for the &lt;code&gt;header&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt; views.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Creating this Pull Request was a process of research, trial-and-error, and testing. I started by researching how view transitions could be implemented and found the &lt;a href=&#34;https://github.com/WICG/view-transitions/blob/main/explainer.md&#34;&gt;explainer document&lt;/a&gt; to be extremely helpful. After writing the code, I thoroughly tested it to ensure it worked as expected. The Pull Request passed all six checks before being merged, confirming the changes didn&#39;t regress the performance or accessibility of the page in any way that &lt;a href=&#34;https://github.com/GoogleChrome/lighthouse-ci&#34;&gt;Lighthouse CI&lt;/a&gt; can detect.&lt;/p&gt;
&lt;img src=&#34;/imgs/github-lighthouse-checks-screenshot.png&#34; alt=&#34;Screenshot of github.com pull request checks showing 6 lighthouse checks that are all passing.&#34;&gt;
&lt;p&gt;The view transitions have significantly improved the visual experience of browsing &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt;. The transitions between different views are now smooth and engaging. And according to &lt;a href=&#34;https://github.com/WICG/view-transitions/blob/main/explainer.md&#34;&gt;the View Transitions explainer&lt;/a&gt; these transitions also: &amp;quot;[...] lower the cognitive load by helping users &lt;a href=&#34;https://www.smashingmagazine.com/2013/10/smart-transitions-in-user-experience-design/&#34;&gt;stay in context&lt;/a&gt; as they navigate from Page-A to Page-B, and &lt;a href=&#34;https://wp-rocket.me/blog/perceived-performance-need-optimize/#:~:text=1.%20Use%20activity%20and%20progress%20indicators&#34;&gt;reduce the perceived latency&lt;/a&gt; of loading.&amp;quot; I encourage you to visit the website and experience these transitions firsthand.&lt;/p&gt;
&lt;div class=&#34;info&#34;&gt;
You need to browse the website using Chrome and have these two experimental flags enable to be able to view these transitions:
&lt;pre&gt;&lt;code&gt;chrome://flags#view-transition
chrome://flags#view-transition-on-navigation
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Looking ahead, I plan to continue refining these transitions and exploring other ways to enhance the site&#39;s user interface.&lt;/p&gt;
&lt;p&gt;In this post, we&#39;ve delved into the process of implementing view transitions on &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt;. I hope this glimpse into my development process has been informative and interesting. As always, I welcome your feedback and questions. Happy browsing!&lt;/p&gt;
&lt;div style=&#34;font-size: var(--size-fluid-3);&#34;&gt;Changelog&lt;/div&gt;
&lt;ol style=&#34;margin: 0; padding: 0; list-style: none; font-size: var(--font-size-1);&#34;&gt;
    &lt;li style=&#34;display: flex;max-inline-size: unset; padding-inline-start: unset;&#34;&gt;
        &lt;span style=&#34;font-family: var(--font-mono); margin-right: var(--size-3);&#34;&gt;May 30, 2023&lt;/span&gt;
        &lt;span style=&#34;flex: 1;&#34;&gt;Add instruction on how to enable View Transitions.&lt;/span&gt;
    &lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  
  <entry>
    <title>Web Performance — From the Lab to the Field</title>
    <link href="https://koddsson.com/posts/web-performance-from-the-lab-to-the-field/" rel="alternate" type="text/html"/>
    <id>https://koddsson.com/posts/web-performance-from-the-lab-to-the-field/</id>
    <updated>2023-08-13T00:00:00Z</updated>
    <published>2023-08-13T00:00:00Z</published>
    <summary>In this post, I delve into the world of web performance and its profound influence on user experience. I share my experiences of optimizing my website, koddsson.com, by using real user monitoring and tools like Lighthouse CI.</summary>
    <content type="html">&lt;p&gt;The advent of the internet and the rise of digital technologies have transformed the way we live, work, and play. As we find ourselves increasingly reliant on web applications, the importance of Web Performance has never been more evident. In this post, we&#39;ll go over some basics of Web Performance, why Web Performance matters, and look at some real production data, how to collect it, and analyse it.&lt;/p&gt;
&lt;h2&gt;Understanding Web Performance and the need for speed&lt;/h2&gt;
&lt;p&gt;Web Performance is the amalgamation of objective measurements and the perceived user experience of load and run time. It encapsulates how long a site takes to load, become interactive and responsive, and how smooth the content is during user interactions. It is crucial to minimise the loading and response times, making the experience as available and interactive as possible, as soon as possi​ble. &lt;sup class=&#34;footnote-ref&#34;&gt;&lt;a href=&#34;#fn1&#34; id=&#34;fnref1&#34;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Improving the loading performance of a web page is often one of the highest value performance optimisations that can be made. Users prefer web experiences that are fast to load and smooth to interact with. Good user experience includes ensuring your page loads quickly. The longer it takes for a site to respond, the more users will abandon the page for better user experiences.&lt;/p&gt;
&lt;p&gt;To ensure optimal Web Performance, it&#39;s essential to test and analyse in a controlled lab environments, such as your own development machine, &lt;em&gt;and&lt;/em&gt; in real-world field conditions.&lt;/p&gt;
&lt;h3&gt;Testing in the Lab&lt;/h3&gt;
&lt;p&gt;In the lab, controlled experiments can be conducted to measure Web Performance under specific conditions. This involves using various tools and techniques to simulate user interactions, network conditions, and device capabilities. By conducting tests in the lab, developers can gain valuable insights into the performance bottlenecks of their web pages and identify areas for improvement.&lt;/p&gt;
&lt;p&gt;Lab testing often involves the use of performance testing tools, such as &lt;a href=&#34;https://developer.chrome.com/docs/lighthouse/overview/&#34;&gt;Lighthouse&lt;/a&gt;, &lt;a href=&#34;https://www.webpagetest.org/&#34;&gt;WebPagetest&lt;/a&gt;, or browser developer tools. These tools provide detailed metrics and diagnostics related to page load times, network requests, rendering, and other performance-related aspects. They allow developers to analyse critical performance indicators, such as &lt;a href=&#34;https://web.dev/ttfb/&#34;&gt;Time to First Byte (TTFB)&lt;/a&gt;, &lt;a href=&#34;https://web.dev/fcp/&#34;&gt;First Contentful Paint (FCP)&lt;/a&gt;, and &lt;a href=&#34;https://web.dev/tti/&#34;&gt;Time to Interactive (TTI)&lt;/a&gt;, to assess and optimise Web Performance.&lt;/p&gt;
&lt;p&gt;Testing in the Lab has the benefit of repeatable results on a predetermined software and hardware which is very useful for debugging specific performance issues that your web page might have.&lt;/p&gt;
&lt;h3&gt;Testing in the Field&lt;/h3&gt;
&lt;p&gt;While lab testing provides valuable insights, it is equally important to understand how web pages perform in real-world scenarios. Real user monitoring (RUM) allows for comprehensive performance analysis by collecting data from actual users&#39; interactions with the website.&lt;/p&gt;
&lt;p&gt;RUM involves embedding lightweight tracking scripts in web pages to capture real-time performance data, including page load times, rendering speed, network latency, and user interactions. This data is then aggregated and analysed to understand the actual performance experienced by users in different geographical locations, on different devices, and across various network conditions.&lt;/p&gt;
&lt;p&gt;By monitoring Web Performance in the field, developers can gain insights into long-term trends, identify performance issues that may be specific to certain user segments or geographic regions, and make data-driven decisions to optimise performance.&lt;/p&gt;
&lt;h2&gt;Embracing Web Performance in Practice&lt;/h2&gt;
&lt;p&gt;Let&#39;s take a look at how we implemented these principles on my website, &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt;. I started by implementing &amp;quot;in the lab&amp;quot; tests on each pull request created on the sites repository.&lt;/p&gt;
&lt;h3&gt;Testing in the Lab&lt;/h3&gt;
&lt;p&gt;For the pull request checks I used Lighthouse CI running in GitHub Actions. Lighthouse CI runs the same Lighthouse audits as you might have already run in your Chrome DevTools so they might look familiar. These audits provide detailed metrics and diagnostics related to page load times, network requests, rendering, and other performance-related aspects. These checks are then reported back to the Pull Request so I can make sure that I haven&#39;t regressed on any of the performance metrics.&lt;/p&gt;
&lt;img src=&#34;/imgs/web-perf1.png&#34; alt=&#34;&#34;&gt;
&lt;img src=&#34;/imgs/web-perf2.png&#34; alt=&#34;&#34;&gt;
&lt;img src=&#34;/imgs/web-perf3.png&#34; alt=&#34;&#34;&gt;
&lt;p&gt;By running Lighthouse audits in the lab, I&#39;m able to identify performance bottlenecks and areas for improvement. The critical performance indicators, such as Time to First Byte (TTFB), First Contentful Paint (FCP), and Time to Interactive (TTI), allowed us to assess and optimise Web Performance. This iterative process of testing, analysing, and optimising in the lab helped me improve the site&#39;s speed and responsiveness.&lt;/p&gt;
&lt;h3&gt;Testing in the Field&lt;/h3&gt;
&lt;p&gt;While lab testing provides valuable insights, it&#39;s equally important to understand how web pages perform in real-world scenarios. Real user monitoring (RUM) enables us to collect data from actual users&#39; interactions with the website and gain insights into their experiences.&lt;/p&gt;
&lt;p&gt;For &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt;, I implemented real user monitoring by embedding lightweight tracking scripts in web pages. These scripts capture Core Web Vitals metrics during the users visit using the &lt;a href=&#34;https://www.npmjs.com/package/web-vitals&#34;&gt;&lt;code&gt;web-vitals&lt;/code&gt;&lt;/a&gt; npm package which is provided by Google.&lt;/p&gt;
&lt;p&gt;Apart from the &lt;code&gt;web-vitals&lt;/code&gt; library, the code to send the data to a backend system for processing is pretty minimal thanks to the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon&#34;&gt;&lt;code&gt;sendBeacon&lt;/code&gt; API&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;language-javascript&#34;&gt;&lt;code class=&#34;language-javascript&#34;&gt;&lt;span class=&#34;token keyword&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;onLCP&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; onFID&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; onCLS&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; onINP&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; onFCP&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; onTTFB&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#39;web-vitals&#39;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; endpoint &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#39;https://vitals.koddsson.workers.dev/&#39;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;token keyword&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;token function&#34;&gt;sendToAnalytics&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token parameter&#34;&gt;metric&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; body &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token constant&#34;&gt;JSON&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;stringify&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;metric&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

	&lt;span class=&#34;token comment&#34;&gt;// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.&lt;/span&gt;
	&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;navigator&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;sendBeacon &lt;span class=&#34;token operator&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; navigator&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;sendBeacon&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;endpoint&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; body&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token operator&#34;&gt;||&lt;/span&gt;
		&lt;span class=&#34;token function&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;endpoint&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;body&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token literal-property property&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#39;POST&#39;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token literal-property property&#34;&gt;keepalive&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token boolean&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;token function&#34;&gt;onCLS&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;sendToAnalytics&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token function&#34;&gt;onFID&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;sendToAnalytics&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token function&#34;&gt;onLCP&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;sendToAnalytics&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token function&#34;&gt;onINP&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;sendToAnalytics&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token function&#34;&gt;onFCP&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;sendToAnalytics&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token function&#34;&gt;onTTFB&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;sendToAnalytics&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you have your browser network monitor open while visiting &lt;a href=&#34;http://koddsson.com&#34;&gt;http://koddsson.com&lt;/a&gt; you should see the data being sent:&lt;/p&gt;
&lt;img src=&#34;/imgs/web-perf4.png&#34; alt=&#34;&#34;&gt;
&lt;p&gt;The data gets sent to a &lt;a href=&#34;https://workers.cloudflare.com/&#34;&gt;Cloudflare Worker®&lt;/a&gt; which saves the values sent to a database. I won&#39;t put the whole worker in this post but here&#39;s the bit that accepts a POST request:&lt;/p&gt;
&lt;pre class=&#34;language-javascript&#34;&gt;&lt;code class=&#34;language-javascript&#34;&gt;&lt;span class=&#34;token keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;request&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;method &lt;span class=&#34;token operator&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;POST&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; payload &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;await&lt;/span&gt; request&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
	&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt; name&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; id&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; value&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; rating&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; delta&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; navigationType &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; payload&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
	&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; timestamp &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; Date&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

	&lt;span class=&#34;token keyword&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;token keyword&#34;&gt;await&lt;/span&gt; env&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token constant&#34;&gt;DB&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;
			&lt;span class=&#34;token template-string&#34;&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;INSERT INTO recordings (id, name, value, rating, delta, navitationType, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)
		&lt;/span&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;id&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; name&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; value&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; rating&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; delta&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; navigationType&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; timestamp&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
	&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;error&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
		console&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;error&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
	&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;token keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;token class-name&#34;&gt;Response&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;token literal-property property&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;token number&#34;&gt;201&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This data is then analyzed to understand the actual performance experienced by users in different geographical locations, on various devices, and across diverse network conditions.&lt;/p&gt;
&lt;p&gt;By monitoring Web Performance in the field, I&#39;m able to identify long-term trends and uncover performance issues specific to certain user segments or geographic regions. These insights allows me to make data-driven decisions and further optimize the performance of &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt; in the future.&lt;/p&gt;
&lt;h2&gt;Visualising and Charting the Data&lt;/h2&gt;
&lt;p&gt;To gain a deeper understanding of the collected Web Performance data, visualising and charting the data can be immensely helpful. By visualising the data, patterns, trends, and anomalies can become more apparent, aiding in the identification of areas that require attention and optimisation.&lt;/p&gt;
&lt;p&gt;At this point though the data is all just dumped into a database which makes it hard to gleam insights about Web Performance about it.&lt;/p&gt;
&lt;img src=&#34;/imgs/web-perf5.png&#34; alt=&#34;&#34;&gt;
&lt;p&gt;It would be really good if I could explore and graph this data for insights and overview. First we need to export the data in some easy way in a portable format. JSON seems like a logical choice so I added a endpoint the fetches all the data and some convenience filtering by the metric type.&lt;/p&gt;
&lt;pre class=&#34;language-javascript&#34;&gt;&lt;code class=&#34;language-javascript&#34;&gt;&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; type &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; url&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;searchParams&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;type&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;token keyword&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;token keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;!&lt;/span&gt;type&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
	    &lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt; results &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;await&lt;/span&gt; env&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token constant&#34;&gt;DB&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token template-string&#34;&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;SELECT * FROM recordings&lt;/span&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
		&lt;span class=&#34;token keyword&#34;&gt;return&lt;/span&gt; Response&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;results&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
	&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;LCP&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;CLS&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;FID&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;INP&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;TTFB&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;includes&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;type&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt; results &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;await&lt;/span&gt; env&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token constant&#34;&gt;DB&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token template-string&#34;&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;SELECT * FROM recordings WHERE name = ?&lt;/span&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;type&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
		&lt;span class=&#34;token keyword&#34;&gt;return&lt;/span&gt; Response&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;results&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
	&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;error&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
	console&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;error&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then tried to load the data into various data visualisation applications and using different kind of charting libraries. These all either didn&#39;t work properly or didn&#39;t give me the results I wanted. I might have been spoilt with my previous experience with DataDog. I really wish I could load the data into a service and then easily explore it and present it in different ways. I ended up just wanting &lt;em&gt;something&lt;/em&gt; simple and easy to manage and I actually ended up using Google Sheets with the charting function! One problem though; there doesn&#39;t seem to be a easy way to import a JSON file or endpoint. No worries, lets just add functionality to our worker to return CSV as well:&lt;/p&gt;
&lt;pre class=&#34;language-javascript&#34;&gt;&lt;code class=&#34;language-javascript&#34;&gt;&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; type &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; url&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;searchParams&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;type&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; csv &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; request&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;headers&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;Accept&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;?.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;includes&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;text/csv&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; formatResults &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; csv &lt;span class=&#34;token operator&#34;&gt;?&lt;/span&gt; ResponseCSV &lt;span class=&#34;token operator&#34;&gt;:&lt;/span&gt; Response&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;json&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;token keyword&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;token keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token operator&#34;&gt;!&lt;/span&gt;type&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt; results &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;await&lt;/span&gt; env&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token constant&#34;&gt;DB&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token template-string&#34;&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;SELECT * FROM recordings&lt;/span&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;token keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;token function&#34;&gt;formatResults&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;results&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;&#34;LCP&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;CLS&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;FID&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;INP&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;token string&#34;&gt;&#34;TTFB&#34;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;includes&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;type&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;token keyword&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt; results &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token operator&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;await&lt;/span&gt; env&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token constant&#34;&gt;DB&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token template-string&#34;&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;token string&#34;&gt;SELECT * FROM recordings WHERE name = ?&lt;/span&gt;&lt;span class=&#34;token template-punctuation string&#34;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;type&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;token keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;token function&#34;&gt;formatResults&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;results&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;token keyword&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;error&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;token punctuation&#34;&gt;{&lt;/span&gt;
  console&lt;span class=&#34;token punctuation&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;token function&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;(&lt;/span&gt;error&lt;span class=&#34;token punctuation&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;token punctuation&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;token punctuation&#34;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now I can import the CSV files into Google Sheets and start creating charts that help me (and other potential stakeholders) to visualise and better understand the data.&lt;/p&gt;
&lt;img src=&#34;/imgs/Count of rating.svg&#34; alt=&#34;&#34;&gt;
&lt;img src=&#34;/imgs/Histogram of datetime.svg&#34; alt=&#34;&#34;&gt;
&lt;p&gt;These are pretty minimal charts but they are currently working for my use cases. I&#39;m planning on finding a even better solution but at least now I can actually view the data with charts.&lt;/p&gt;
&lt;img src=&#34;/imgs/LCP ratings.svg&#34; alt=&#34;&#34;&gt;
&lt;img src=&#34;/imgs/INP ratings.svg&#34; alt=&#34;&#34;&gt;
&lt;img src=&#34;/imgs/CLS ratings.svg&#34; alt=&#34;&#34;&gt;
&lt;h2&gt;Looking Forward&lt;/h2&gt;
&lt;p&gt;Web performance is a continuous journey, not a destination. Looking ahead, I plan to continue explore other ways to enhance the site&#39;s user interface. Web Performance is a vital area that needs constant attention and optimisation, but the results are definitely wo​rth looking into.&lt;/p&gt;
&lt;p&gt;You should note that I did all this without spending any money. I&#39;ll concede that I don&#39;t have huge site to manage, there&#39;s not a lot of traffic right now so there isn&#39;t a lot of data to crunch but I&#39;m also not buying some system wholesale and letting them deal with it for me. DataDog and Sentry cost some amount of money (that I don&#39;t want to pay for on such a small site like &lt;a href=&#34;http://koddsson.com&#34;&gt;koddsson.com&lt;/a&gt; and which doesn&#39;t make me any money). I had to do &lt;em&gt;some&lt;/em&gt; work but it&#39;s just installing some &lt;code&gt;npm&lt;/code&gt; packages, writing a little JS snippet and a worker to save the metrics to a database. The hardest part so far has been graphing the data up in meaningful way.&lt;/p&gt;
&lt;p&gt;In conclusion, Web Performance is an essential aspect of providing a smooth, user-friendly online experience. As developers, we should strive to create web pages that are not only functional but also performant. Before knowing how to make your website faster you&#39;ll need to know what things can be improved and that starts by measuring. As the Dutch say: &amp;quot;Meten is weten!&amp;quot; (To measure is to know).&lt;/p&gt;
&lt;hr class=&#34;footnotes-sep&#34;&gt;
&lt;section class=&#34;footnotes&#34;&gt;
&lt;ol class=&#34;footnotes-list&#34;&gt;
&lt;li id=&#34;fn1&#34; class=&#34;footnote-item&#34;&gt;&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/Performance&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/Performance&lt;/a&gt; &lt;a href=&#34;#fnref1&#34; class=&#34;footnote-backref&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
  
</feed>
