<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title></title>
    <link rel="self" type="application/atom+xml" href="https://hugodaniel.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://hugodaniel.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-17T00:00:00+00:00</updated>
    <id>https://hugodaniel.com/atom.xml</id>
    <entry xml:lang="en">
        <title>The LLM experience of boreDOM</title>
        <published>2026-02-17T00:00:00+00:00</published>
        <updated>2026-02-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/redesigning-boredom-for-lx/"/>
        <id>https://hugodaniel.com/posts/redesigning-boredom-for-lx/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/redesigning-boredom-for-lx/">&lt;p&gt;&lt;strong&gt;TL;DR&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I talk about the changes made to bring &lt;a href=&quot;&#x2F;posts&#x2F;why-llms-keep-editing-the-wrong-file&#x2F;&quot;&gt;LLM Experience design&lt;&#x2F;a&gt; to &lt;code&gt;boreDOM&lt;&#x2F;code&gt;, my testbed zero-build JS runtime that collapses HTML, CSS, JS and state into a single HTML file so models can locate the source of an effect in place.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;machines_of_code.png&quot; alt=&quot;I&amp;#39;m a machine and so are you&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-a-codebase-look-like-if-its-primary-author-is-a-machine&quot;&gt;What does a codebase look like if its primary author is a machine?&lt;&#x2F;h2&gt;
&lt;p&gt;If a codebase is mostly written by a machine, do our usual frontend instincts still hold? What do we need to change to make that workflow reliable? And how much can we min-max an LLM’s strengths if we stop designing exclusively for human cognition?&lt;&#x2F;p&gt;
&lt;p&gt;I walked this path, looking for answers, adapting and changing &lt;a href=&quot;&#x2F;pages&#x2F;boreDOM&#x2F;&quot;&gt;&lt;code&gt;boreDOM&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; a minimal JS framework (with no bundler or package manager) I keep evolving as I learn where LLM workflows actually break.&lt;&#x2F;p&gt;
&lt;p&gt;With little JS &lt;code&gt;boreDOM&lt;&#x2F;code&gt; tries to make components reusable and allow them to be layed out in triplets:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; data-component&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;my-thing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;!&lt;&#x2F;span&gt;&lt;span&gt;-- regular CSS here --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; data-component&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;my-thing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;!-- regular &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;HTML&lt;&#x2F;span&gt;&lt;span&gt; here --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt; type=&amp;quot;text&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;boredom&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;data-component&lt;&#x2F;span&gt;&lt;span&gt;=&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;my-thing&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;!-- Component JS here --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HTML is HTML, style is CSS, and code is JS. These units of triplets can then be placed in a single file index.html or in multiple files through some existing bundler (I use vite when I am hand-rolling them).&lt;&#x2F;p&gt;
&lt;p&gt;Working with LLMs pushed me to over-emphasize a single source of truth. The goal started moving slowly from &quot;syntactic clarity for humans&quot; and more into &quot;operational clarity&quot; by making it cheap to discover where an effect originates, and safe to change it coherently.&lt;&#x2F;p&gt;
&lt;p&gt;The rest of this post is about that shift from human-readable structure to machine-editable traceability in &lt;code&gt;boreDOM&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;boredom&quot;&gt;boreDOM&lt;&#x2F;h3&gt;
&lt;p&gt;For boredom the &lt;a href=&quot;&#x2F;posts&#x2F;why-llms-keep-editing-the-wrong-file&#x2F;&quot;&gt;previous LX (LLM-Experience) guides&lt;&#x2F;a&gt; translated into the following design principles:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Single place of truth: UI structure + style + behavior live together.&lt;&#x2F;li&gt;
&lt;li&gt;Instrumented runtime, everything is machine parseable.&lt;&#x2F;li&gt;
&lt;li&gt;Constrained surface area, fewer ways to do the same thing and a limited number of composable things.&lt;&#x2F;li&gt;
&lt;li&gt;No build-time indirection, what the model edits is what the browser runs.&lt;&#x2F;li&gt;
&lt;li&gt;The whole framework is included in the single file of the app, as if the LLM made it, unmaintainable for humans, but a bit better for deep agentic loops, so long we don&#x27;t hit their other problems (lost in the middle, etc...).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;From here on I&#x27;ll describe the specific ergonomics I added to boreDOM to make that LX workflow real.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ergonomics-for-llms&quot;&gt;Ergonomics for LLMs&lt;&#x2F;h2&gt;
&lt;p&gt;To enforce these principles, &lt;code&gt;boreDOM&lt;&#x2F;code&gt; relies on specific mechanics designed for autonomous agentic loops. This is a more technical part, but maybe it can also be applied while vibecoding too.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ergonomics.png&quot; alt=&quot;Pencil ergonomics for my weird hands&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-let-llms-self-correct-without-humans-in-the-loop&quot;&gt;A. Let LLMs self-correct without humans in the loop&lt;&#x2F;h3&gt;
&lt;p&gt;I want to give the LLM parseable and deterministic feedback so that it can self-heal in a loop.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;CLI Validator&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;boreDOM&lt;&#x2F;code&gt; includes a custom CLI linter validator. Actually I don&#x27;t see it as a linter and more like a context injection engine made specifically to signal the LLM the best practices and idiomatic approaches it needs. It guardrails the semantic boreDOM approaches as well as tries to prevent introducing things that could impair reusability of components and offline usage (introducing Google Fonts, hallucinating directive names, going around components logic and update loop with &lt;code&gt;innerHTML&lt;&#x2F;code&gt; and others, etc...).&lt;&#x2F;p&gt;
&lt;p&gt;The CLI tool validator outputs structured actionable errors that forms a lint-fix loop (validate -&amp;gt; fix -&amp;gt; validate again).&lt;&#x2F;p&gt;
&lt;p&gt;It can produce warnings for &lt;code&gt;boreDOM&lt;&#x2F;code&gt; specific things, such as when LLMs should be using &lt;code&gt;data-dispatch&lt;&#x2F;code&gt; but instead go and write &lt;code&gt;data-action&lt;&#x2F;code&gt;. Or errors for generic things like when a &lt;code&gt;setInterval&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;addEventListener&lt;&#x2F;code&gt; is used but not cleaned up.&lt;&#x2F;p&gt;
&lt;p&gt;Every warning&#x2F;error includes a suggestion string, a plain English fix instruction, and sometimes an example of corrected code.&lt;&#x2F;p&gt;
&lt;p&gt;The validator tries to re-prompt LLMs with suggestions in its output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; W001: Found data-action=&amp;quot;submit&amp;quot; (boreDOM uses data-dispatch) (line 42:7) Suggestion: Rename to data-dispatch=&amp;quot;...&amp;quot; (click) or data-dispatch-&amp;lt;event&amp;gt; for other events.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Example: data-dispatch=&amp;quot;submit&amp;quot;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Having a custom made linter validator improved at lot the success rate of single prompts with boreDOM.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Import Debug via #sourceURL&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When &lt;code&gt;boreDOM&lt;&#x2F;code&gt; encounters a &lt;code&gt;&amp;lt;script data-component=&quot;some-component&quot;&amp;gt;&lt;&#x2F;code&gt; it will extract the script text from it and dynamically import it with &lt;code&gt;import(url)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;url&lt;&#x2F;code&gt; is a temporary URL object from a Blob that has &lt;code&gt;&#x2F;&#x2F;# sourceURL=...&lt;&#x2F;code&gt; appended to it. The object URL is revoked immediately after the import resolves.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.chrome.com&#x2F;docs&#x2F;devtools&#x2F;javascript&#x2F;source-maps#sourceurl&quot;&gt;&lt;code&gt;#sourceURL&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; allows LLMs to pin point lines for each component script. It produces relative line numbers and points the dev tools to a fictitious URL &lt;code&gt;boredom:&#x2F;&#x2F;default&#x2F;some-component.js&lt;&#x2F;code&gt;, which is something that LLMs can easily disambiguate.&lt;&#x2F;p&gt;
&lt;p&gt;Each component&#x27;s script is a lazily-evaluated ES module that only gets imported once and can produce a parseable correction signal when an LLM generates a boreDOM component that breaks.&lt;&#x2F;p&gt;
&lt;p&gt;This way when the model breaks a component, the console points to &lt;code&gt;boredom:&#x2F;&#x2F;...:linenumber&lt;&#x2F;code&gt;, so it can patch the right script block without guessing offsets.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Structured Logs for regex&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Every &lt;code&gt;console.error&lt;&#x2F;code&gt; and &lt;code&gt;console.warn&lt;&#x2F;code&gt; in &lt;code&gt;boreDOM&lt;&#x2F;code&gt; follows the exact same shape:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;[BOREDOM:ERROR]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; JSON&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  component&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;component-name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  message&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; err&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;message&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  stack&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; err&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stack&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  code&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SCRIPT_LOAD_FAILED&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  loc&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;boredom:&#x2F;&#x2F;default&#x2F;some-component.js:12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  context&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; source&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;script_load&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; or &amp;quot;state_parse&amp;quot;, &amp;quot;_update&amp;quot;, etc...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The idea here is that errors come out in a structured JSON that an LLM can regex out of a log dump.&lt;&#x2F;p&gt;
&lt;p&gt;An LLM reading console output can grep for &lt;code&gt;&quot;[BOREDOM:ERROR]&quot;&lt;&#x2F;code&gt;, parse the JSON, and immediately know which component, what failed, and where in the lifecycle.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;b-make-the-default-behavior-match-llm-expectations&quot;&gt;B. Make the default behavior match LLM expectations&lt;&#x2F;h3&gt;
&lt;p&gt;Making the runtime transient and fluid towards what LLMs are trying to output is a good way to avoid fighting the weights or going against their training and instead try to leverage their thinking skills. I ended up gifting &lt;code&gt;boreDOM&lt;&#x2F;code&gt; with the following things.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Declarative bindings&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;LLMs trained on React&#x2F;Vue&#x2F;Svelte default to thinking of bindings as two-way. When they see &lt;code&gt;data-value=&quot;local.name&quot;&lt;&#x2F;code&gt; on an &lt;code&gt;&amp;lt;input&amp;gt;&lt;&#x2F;code&gt;, they assume typing in the input automatically updates &lt;code&gt;local.name&lt;&#x2F;code&gt;, unfortunately that&#x27;s not how it works in vanilla DOM, &lt;code&gt;data-value&lt;&#x2F;code&gt; is just an attribute the runtime reads to push state down and without an explicit event listener typing in the &lt;code&gt;&amp;lt;inpute&amp;gt;&lt;&#x2F;code&gt; does nothing to state.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;boreDOM&lt;&#x2F;code&gt; these values are compiled with &lt;code&gt;new Function&lt;&#x2F;code&gt;s, in a set of constraints that make it safe-ish for the &lt;code&gt;boreDOM&lt;&#x2F;code&gt; strict conditions that it uses it. This way it allow LLMs to write:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;input data-value=&amp;quot;local.name&amp;quot; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;p data-text=&amp;quot;local.name&amp;quot;&amp;gt;&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And it just works, state flows down.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Pre-registered event delegation&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Instead of requiring per-element addEventListener calls, &lt;code&gt;boreDOM&lt;&#x2F;code&gt; pre-registers all 16 supported events (yep, only 16 events are supported) on each component host on setup.&lt;&#x2F;p&gt;
&lt;p&gt;Most UI apps use ~16 events, explicitly naming them and limiting prevents hallucinated event types and lifecycle leaks.&lt;&#x2F;p&gt;
&lt;p&gt;These can be extended in CONSTANTS.Events if needed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;CONSTANTS&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Events&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;forEach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;addEventListener&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;event&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    dispatchComponentEvent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; actionType&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span&gt; capture&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; useCapture&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The LLM just writes &lt;code&gt;data-dispatch=&quot;doThing&quot;&lt;&#x2F;code&gt; in the HTML and &lt;code&gt;on(&quot;doThing&quot;, ...)&lt;&#x2F;code&gt; in the script. No need to keep track of what &lt;code&gt;addEventListeners&lt;&#x2F;code&gt; need to be cleared.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Automatic re-rendering via proxies&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Both state (global) and local (component) are wrapped in a &lt;code&gt;Proxy&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; proxy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Proxy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;target&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;obj&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; prop&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Object&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;is&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;oldValue&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    obj&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;prop&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    scheduleUpdate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;obj&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; prop&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Deep wraps, so state.projects[0].name = &amp;quot;x&amp;quot; triggers a re-render too:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; createReactiveState&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;obj&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;prop&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; callback&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; cache&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;LLMs just write &lt;code&gt;local.count += 1&lt;&#x2F;code&gt; and the UI updates. There is a &lt;code&gt;WeakMap&lt;&#x2F;code&gt; cache to prevent infinite proxy wrapping.&lt;&#x2F;p&gt;
&lt;p&gt;boreDOM deliberately uses deep proxies and constrained event delegation to reduce syntactic friction for LLMs. I want re-renders to happen automatically, remove them from being explicit in the syntax and into runtime behavior. Again this is the shift from designing for operation instead of for syntax. Think of it as removing hooks from React and instead focusing on the way a LLM will be writing the intentions.&lt;&#x2F;p&gt;
&lt;p&gt;This does introduce risks such as recursive mutations that can trigger render loops, or unsupported DOM events that won&#x27;t fire.&lt;&#x2F;p&gt;
&lt;p&gt;These are intentional constraints designed to reduce surface area for generation and prevent common lifecycle errors, at the cost of flexibility.&lt;&#x2F;p&gt;
&lt;p&gt;With LLMs I tend to see syntax as a solved problem, so my natural approach is to shift explicitness from boilerplate in authored code to consistency behaviours in runtime that LLMs can inspect and produce at will.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;c-flatten-the-abstractions&quot;&gt;C. Flatten the abstractions&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Flat destructurable API&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The component init function receives everything in one flat object:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; createInitContext&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;component&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fn&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; registerAction&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  onMount&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; registerHook&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  onUpdate&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; registerHook&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  onCleanup&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; registerHook&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  self&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; component&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createComponentContext&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;component&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; { state, local, refs }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This way LLMs can destructure exactly what they need: &lt;code&gt;({ state, local, on, onMount }) =&amp;gt; { ... }&lt;&#x2F;code&gt; without having to keep extra context about class inheritances or import paths. The entire API surface is flat 7 names: on, onMount, onUpdate, onCleanup, state, local and refs (and the ref for the component itself).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Components triplets in a single place&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As I&#x27;ve shown at the start, the architectural format itself is an LLM ergonomy thing, where HTML, CSS and JS are defined per component in the same place with the same tags. In the end everything lives in one file, but this is just an optional final flattening (things can be in split files if it gets too big).&lt;&#x2F;p&gt;
&lt;p&gt;LLMs love this when there are semantic anchors across the domain concepts. In boredom this is achieve with the &lt;code&gt;data-component&lt;&#x2F;code&gt; in style, template, and script tags.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tradeoffs&quot;&gt;The tradeoffs&lt;&#x2F;h2&gt;
&lt;p&gt;My idea is to optimize for a single author + LLM collaborator model. I mean a very specific single author: me. All of this seems terrible for human teams of many engineers trying to tackle complex products.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;tumbling_cog.png&quot; alt=&quot;Code is made of words&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Systems become unmaintainable without modular boundaries and clear APIs. With &lt;code&gt;boreDOM&lt;&#x2F;code&gt; you lose strict cross-file type checking, fault isolation, refactoring safety, dependency management, and all of the bundler advantages (tree shaking, code splitting, asset hashing, preloading, etc...).&lt;&#x2F;p&gt;
&lt;p&gt;This isn&#x27;t an attempt to replace React, Vue, Svelte, or even trying to overhaul existing frontend architectures.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I tried exploring a different category, runtimes designed for environments where code is frequently written, read and refactored by LLMs.&lt;&#x2F;p&gt;
&lt;p&gt;In these contexts, I am flipping common knowledge by betting that immediacy, traceability, and low causal distance matter more for AI-driven iteration than strict modular boundaries and build optimizations .&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;boreDOM&lt;&#x2F;code&gt; isn&#x27;t meant to be a maintainable codebase for big engineering teams. It&#x27;s an architecture for high-velocity, AI-assisted prototyping and it treats code as &quot;disposable&quot; or &quot;constantly mutable&quot; rather than a permanent monument.&lt;&#x2F;p&gt;
&lt;p&gt;Current LLMs are still &#x27;DX-native&#x27;, they are trained on the very spaghetti of indirection I&#x27;m trying to solve. This inconsistency isn&#x27;t a failure of the rearchitecture I am proponing but more like a symptom of the existing training gap.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe in the future they will have that capability of determinism and provide for greater experiments.&lt;&#x2F;p&gt;
&lt;p&gt;For now, this is exploratory work. The architectural patterns are strong enough to justify continued experimentation.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that in the future we will be spending more time designing the environment where the code writes itself, as a sort of protocol of intuition between us and our partner that has a 256k context window and zero intuition.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to experiment with this architecture yourself, or just want to see how an LLM handles a zero-build framework, you can check out the &lt;a href=&quot;&#x2F;pages&#x2F;boreDOM&#x2F;&quot;&gt;boreDOM landing page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;npx @mr_hugo&#x2F;boredom init&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Feed it to Claude or Cursor, and let me know if it fails awesomely or brilliantly.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>R.I.P. Rest In Prompt</title>
        <published>2026-02-16T00:00:00+00:00</published>
        <updated>2026-02-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/rip-rest-in-prompt/"/>
        <id>https://hugodaniel.com/posts/rip-rest-in-prompt/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/rip-rest-in-prompt/">&lt;p&gt;&lt;strong&gt;TL;DR&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;LLMs tend to mislocalize when there are multiple sources of truth, so they can fail even while generating &quot;correct&quot; code. This post explores what frontend architecture looks like when the primary collaborator is an LLM. I call this LLM Experience (LX): optimizing for discoverability, traceability, and machine-readable runtime feedback over human-centric modularity.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;rip_prompt.png&quot; alt=&quot;Rest In Prompt&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;make-the-button-more-blue&quot;&gt;&quot;Make the button more blue&quot;&lt;&#x2F;h3&gt;
&lt;p&gt;Think about it, changing a button color in a modern framework such as React, can be a task that spans component code, provider tree traversals, theme tokens, CSS vars, and build-time layers.&lt;&#x2F;p&gt;
&lt;p&gt;This is mostly a lookup problem and not so much a &quot;thinking&quot; problem because in this scenario to change a color we would have to trace through the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Where is the value defined?&lt;&#x2F;li&gt;
&lt;li&gt;What layer owns it?&lt;&#x2F;li&gt;
&lt;li&gt;What overrides it?&lt;&#x2F;li&gt;
&lt;li&gt;What runtime state mutates it?&lt;&#x2F;li&gt;
&lt;li&gt;What token maps to it?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We humans solve this lookup problem using the Dev tools inspector, jumping definitions and class names, toggling states and modifying live styles with a bit of intuition and experience.&lt;&#x2F;p&gt;
&lt;p&gt;For an LLM it&#x27;s also a lookup problem, but with the failure caveat that it can pick the wrong thing and still produce a plausible looking patch.&lt;&#x2F;p&gt;
&lt;p&gt;Humans debug this by inspecting computed styles and jumping definitions. LLMs don&#x27;t have that interactive loop, so they often edit Button.tsx, see no effect, then &quot;fix it&quot; by adding inline styles or duplicate tokens... and now the codebase has two competing truths.&lt;&#x2F;p&gt;
&lt;p&gt;An LLM will give us a fast answer and make it look effortless by confidently editing &lt;code&gt;Button.tsx&lt;&#x2F;code&gt;. But its retrieval might have caught the wrong files, maybe the real color is coming from the theme provider, and produce a slightly off result because even a 1M-token model will fail if you include the wrong stuff.&lt;&#x2F;p&gt;
&lt;p&gt;Things made for humans that humans struggle with are amplified now. Stuff we consider midly annoying can be a reliability killer for models.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-prompts-go-to-die&quot;&gt;Where prompts go to die&lt;&#x2F;h2&gt;
&lt;p&gt;I keep on inventing small things, functions, frameworks, tools, widgets. Things for fun.&lt;&#x2F;p&gt;
&lt;p&gt;There is a massive blocker nowadays in all of these, that is if you try to invent a new language, or library, or framework, then LLMs will have to look at it from their existing training.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;btn_more_blue.jpg&quot; alt=&quot;It is already blue!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You need to be prepared for LLMs to make moves that only make sense inside ecosystems they&#x27;ve seen billions of times. If its a new JS frontend framework, then LLMs would do things like randomly inject tailwind classes, setup a bundler and package manager, or assume the occasional React pattern of &lt;code&gt;useEffect&lt;&#x2F;code&gt; where dependencies are laied in an array and cleanup function is the one being returned.&lt;&#x2F;p&gt;
&lt;p&gt;This is a hard situation we are now at. Anything slightly offset from the mainstream will be fighting the weights of LLMs.&lt;&#x2F;p&gt;
&lt;p&gt;My attempts at prompt-engineering around these didn&#x27;t help and only made it clear that the problem would need another angle besides prompts.&lt;&#x2F;p&gt;
&lt;p&gt;I then shifted towards re-architecturing things for discoverability.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;our-clean-code-is-a-context-tax&quot;&gt;Our clean code is a context tax&lt;&#x2F;h3&gt;
&lt;p&gt;These machines are only deterministic in a very broad and abstract statistical way. If the codebase doesn&#x27;t make it easy to locate the source of behavior, I find that models will confidently edit the wrong place or rewrite parts of the system into something they recognize.&lt;&#x2F;p&gt;
&lt;p&gt;I was forcing these machines to use my new tool the way they use mainstream stacks (Webpack, file splitting, npm, Tailwind, Redux, etc.). But my tool still lived inside the same broad architectural assumptions, only without the cultural momentum those ecosystems have.&lt;&#x2F;p&gt;
&lt;p&gt;So I stopped trying to out-prompt the model, and started reshaping the architecture around how LLMs actually approach code.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clean_tax.png&quot; alt=&quot;The price is different for LLMs and for Humans&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;developer-experience-dx-vs-llm-experience-lx&quot;&gt;Developer Experience (DX) vs LLM Experience (LX)&lt;&#x2F;h2&gt;
&lt;p&gt;My way into the LLM-experience experience was to avoid the common tactic of making use of the context window to artificially cram awareness into it through prompts.&lt;&#x2F;p&gt;
&lt;p&gt;There is some psychology game here. What is implicit for humans in a codebase, but needs to be explicit for machines?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dx&quot;&gt;DX&lt;&#x2F;h3&gt;
&lt;p&gt;Developer Experience (DX) is the set of design choices we&#x27;ve converged on to help human teams build and maintain software over time. It assumes humans have limited short-term memory and need strong boundaries to keep complexity tame.&lt;&#x2F;p&gt;
&lt;p&gt;It assumes syntax is hard to manage, that code layout and configuration needs to be extremely versatile and layered through to cater for many possible scenarios so that it does not become too &quot;opinionated&quot; or too strict (which can be good things too).&lt;&#x2F;p&gt;
&lt;p&gt;We humans like to have our logic split in small sections, divide and conquer, remove the noise around, avoid goto, premature-optimization is the root of all evil, do one thing and do it well, and uni-uni-uni-uni-unix problems to infinity.&lt;&#x2F;p&gt;
&lt;p&gt;Be it files, components, objects, functions, blocks of { code }, if&#x27;s for&#x27;s, relationships, life choices, whatever.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lx&quot;&gt;LX&lt;&#x2F;h3&gt;
&lt;p&gt;LLM Experience (LX) is a different target, it comprises the set of choices that make a codebase easier for an LLM to read, locate the cause of an effect, modify safely, and validate via feedback.
It assumes that syntax is super easy and that the hard part is finding the correct source of truth and changing it without breaking invariants.&lt;&#x2F;p&gt;
&lt;p&gt;Humans navigate complexity using amazing implicit knowledge and spatial awareness, we go through folders, naming conventions, import strategies, design patterns, source-to-source compilation, like it was easy and benefitial.&lt;&#x2F;p&gt;
&lt;p&gt;LLMs however are more into navigating complexity using contiguous text and local coherence. We both can do both things, but some are better at some.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;I have updated index.ts, index.ts and index.ts. If you want I can also patch index.ts and index.ts next.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Their sense of place has been improving and will hopefully make a lot of this obsolete soon.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;LX in one sentence:&lt;&#x2F;strong&gt; reduce ambiguity about where truth lives, and make runtime feedback point back to the exact edit location.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;design-for-lx&quot;&gt;Design for LX&lt;&#x2F;h2&gt;
&lt;p&gt;There is an apparent tension between DX and LX, where DX adds indirection to make systems scalable the LX removes indirection to make edits reliable.&lt;&#x2F;p&gt;
&lt;p&gt;In the end of the day both LX and DX are trying to reach the same outcome and goal. Both are trying managing the reliability of changes, just through different layers of abstraction.&lt;&#x2F;p&gt;
&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;Feature&lt;&#x2F;th&gt;
            &lt;th&gt;Developer Experience (DX)&lt;&#x2F;th&gt;
            &lt;th&gt;LLM Experience (LX)&lt;&#x2F;th&gt;
        &lt;&#x2F;tr&gt;
    &lt;&#x2F;thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Primary Goal&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
            &lt;td&gt;Minimize cognitive load for humans.&lt;&#x2F;td&gt;
            &lt;td&gt;Maximize context density&#x2F;traceability for AI.&lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Structure&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
            &lt;td&gt;Modular, split files, deep hierarchies.&lt;&#x2F;td&gt;
            &lt;td&gt;Co-located sources of truth, shallow hops (often single-file artifacts).&lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Logic&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
            &lt;td&gt;Abstractions (Hooks, Providers, HOCs).&lt;&#x2F;td&gt;
            &lt;td&gt;Explicit, linear, and &quot;in-place&quot; logic.&lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Feedback&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
            &lt;td&gt;Human-readable error messages.&lt;&#x2F;td&gt;
            &lt;td&gt;Machine-parseable JSON logs&#x2F;signals.&lt;&#x2F;td&gt;
        &lt;&#x2F;tr&gt;
    &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;In LLM Experience, you collide and reduce the sources of truth, so that it is easier to find the places a behavior could be hiding.&lt;&#x2F;p&gt;
&lt;p&gt;This means bringing structure, style, state, and behavior close together, to try to reduce the casual distance of moving parts, while producing fewer valid ways to do the same thing, to try to constraint the surface area.&lt;&#x2F;p&gt;
&lt;p&gt;Errors and traces are structured to try to instrument runtime feedback for machines.&lt;&#x2F;p&gt;
&lt;p&gt;Essentially LX is an attempt to make it hard to edit the wrong thing in the wrong way, by architecturing to provide a predictable runtime behavior and deterministic logs and feedback above code semiotics.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a shift from syntactic explicitness to operational explicitness.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;devx_llmx.png&quot; alt=&quot;LLLLLLLLLLLLLMMMMMMMMXXXXXXXX&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;you-might-already-be-lxing&quot;&gt;You might already be LXing&lt;&#x2F;h3&gt;
&lt;p&gt;Take a look at your current source code, and try to answer these:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Can I locate any UI effect in &amp;lt;= 2 hops?&lt;&#x2F;li&gt;
&lt;li&gt;Is there a single authoritative source for tokens?&lt;&#x2F;li&gt;
&lt;li&gt;Do runtime logs point to an exact edit location?&lt;&#x2F;li&gt;
&lt;li&gt;Can an LLM run validate -&amp;gt; fix without guessing line offsets?&lt;&#x2F;li&gt;
&lt;li&gt;If an agent deletes this component and regenerates it from scratch, will it break the rest of the app?&lt;&#x2F;li&gt;
&lt;li&gt;Can this logic be validated without a complex mocking setup?&lt;&#x2F;li&gt;
&lt;li&gt;Can I find every occurrence of a feature using a single regex, or is the logic smeared across layers?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Anyway you get the idea, LX is about information density, trying to provide the highest ratio of reasoning per token possible, so that the model doesn&#x27;t drift away easily.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lx-patterns-you-can-use&quot;&gt;LX patterns you can use&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;One authoritative place for tokens&#x2F;theme&#x2F;state mutations&lt;&#x2F;li&gt;
&lt;li&gt;Shallow hops: an on-screen effect should be reachable in ≤2 jumps&lt;&#x2F;li&gt;
&lt;li&gt;Stable identifiers that show up in markup and logs&lt;&#x2F;li&gt;
&lt;li&gt;Machine-parseable errors (JSON envelopes with code, component, loc)&lt;&#x2F;li&gt;
&lt;li&gt;Constrained surface area: fewer sanctioned ways to wire events&#x2F;state&lt;&#x2F;li&gt;
&lt;li&gt;A validator loop (validate -&amp;gt; fix -&amp;gt; validate) that doesn&#x27;t require human intuition&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;LLMs strive with less ambiguity. When a UI effect has many plausible owners, models can confidently patch the wrong one and then compensate by duplicating logic. LX is my attempt to design against that failure mode by collapsing sources of truth, reduce indirection, and make runtime feedback machine-readable and location-specific.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;a href=&quot;&#x2F;posts&#x2F;redesigning-boredom-for-lx&#x2F;&quot;&gt;next post&lt;&#x2F;a&gt; I&#x27;ll show the concrete mechanics I used to make this real in my testbed JS framework &lt;a href=&quot;&#x2F;pages&#x2F;boreDOM&#x2F;&quot;&gt;&lt;code&gt;boreDOM&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Where I introduced a CLI validator that drives validate-&amp;gt;fix loops, &lt;code&gt;#sourceURL&lt;&#x2F;code&gt; mapping so console errors point to the exact block to edit, structured JSON logs, and a constrained event&#x2F;state surface that reduces generation drift.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>I was banned from Claude for scaffolding a CLAUDE.md file</title>
        <published>2026-01-22T00:00:00+00:00</published>
        <updated>2026-01-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/claude-code-banned-me/"/>
        <id>https://hugodaniel.com/posts/claude-code-banned-me/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/claude-code-banned-me/">&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;API Error: 400 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;error&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;type&amp;quot;: &amp;quot;invalid_request_error&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;message&amp;quot;:&amp;quot;This organization has been disabled.&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One minute I&#x27;m a €220&#x2F;month &quot;Max 20x&quot; AI &lt;em&gt;&quot;power user&quot;&lt;&#x2F;em&gt; (is this even a thing?).
The next, I am a disabled non-person &quot;organization&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Like a lot of my peers I was using claude code CLI regularly and trying to understand how far I could go with it on my personal projects. Going wild, with ideas and approaches to code I can now try and validate at a very fast pace. Run it inside &lt;code&gt;tmux&lt;&#x2F;code&gt; and let it do the work while I went on to do something else.&lt;&#x2F;p&gt;
&lt;p&gt;Until in one of these sessions I got presented with that response.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;claude_ban.jpg&quot; alt=&quot;&amp;quot;Ban hammer was fast!&amp;quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;organizations-of-late-capitalism-unite&quot;&gt;Organizations of late capitalism, unite!&lt;&#x2F;h2&gt;
&lt;p&gt;My account was banned! no warning and no feedback, just that message saying that my request was invalid because I am a disabled organization.&lt;&#x2F;p&gt;
&lt;p&gt;I wasn&#x27;t even doing anything groundbreaking, in fact, I was asking it to tune a tool I use to do project scaffolding.&lt;&#x2F;p&gt;
&lt;p&gt;Yes you read that right: project scaffolding! Probably one of the most boring things you can think of doing!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-quine-is-the-quine&quot;&gt;The quine is the quine&lt;&#x2F;h2&gt;
&lt;p&gt;So I asked claude to update my scaffolding tool so that it would include a CLAUDE.md file in there with baked instructions for a particular homemade framework (&lt;em&gt;cof&lt;&#x2F;em&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;boredom-another-js-framework&#x2F;&quot;&gt;boreDOM&lt;&#x2F;a&gt; &lt;em&gt;cof&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;I was playing like a &quot;human-in-the-loop&quot; middleware for these LLM tools. Like watching one instance of Claude try to &quot;boss around&quot; another instance of itself, and the platform&#x27;s security guards mistook it for a riot.&lt;&#x2F;p&gt;
&lt;p&gt;To help understand this, there are three main characters in this story:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Claude A&lt;&#x2F;li&gt;
&lt;li&gt;Claude B&lt;&#x2F;li&gt;
&lt;li&gt;A disabled organization (me)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The loop was like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The disabled organization asked Claude A to update the scaffold tool with a cool CLAUDE.md&lt;&#x2F;li&gt;
&lt;li&gt;The disabled organization went on and started a new project with the tool, opened a claude in there (Claude B) and asked for a complex task to be done&lt;&#x2F;li&gt;
&lt;li&gt;Whenever Claude B made a mistake, the disabled organization would go to Claude A, paste the error, and say something like &quot;hey, Claude B made this error&quot;&lt;&#x2F;li&gt;
&lt;li&gt;goto I&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The loop repeated until the disabled organization was told it was a disabled organization.&lt;&#x2F;p&gt;
&lt;p&gt;Banned!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stop-you-are-wrong&quot;&gt;STOP! YOU ARE WRONG&lt;&#x2F;h2&gt;
&lt;p&gt;I just wanted a standard context file for new projects.&lt;&#x2F;p&gt;
&lt;p&gt;At one point Claude A got somewhat annoyed with Claude B, and started shoutting! writting in en-US instead of en-GB, that is: ALL CAPS.&lt;&#x2F;p&gt;
&lt;p&gt;I went on to check the file, and it was getting littered with these kind of instructions to make Claude B do something instead of what it would try to do.&lt;&#x2F;p&gt;
&lt;p&gt;My guess is that this likely tripped the &quot;Prompt Injection&quot; heuristics that the non-disabled organization has.&lt;&#x2F;p&gt;
&lt;p&gt;I would love to see the face of that AI when it saw its own &quot;system prompt&quot; language being echoed back to it.&lt;&#x2F;p&gt;
&lt;p&gt;Or I don&#x27;t know. This is all just a guess from me.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;claude_code_logo.png&quot; alt=&quot;&amp;quot;That hole is red. That hole is me.&amp;quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;it-s-not-just-bad-support-it-s-automated-exclusion&quot;&gt;&quot;It’s not just bad support; it’s automated exclusion.&quot;&lt;&#x2F;h2&gt;
&lt;p&gt;So I went running to read their docs. What was going on here?&lt;&#x2F;p&gt;
&lt;p&gt;Made an appeal, which was a link to a google docs form, with a textbox where I tried to convince some Claude C in the multi-trillion-quadrillion dollar non-disabled organization that I was not only a human but also a well-intended one.&lt;&#x2F;p&gt;
&lt;p&gt;I got no reply. Not even an automatic response. 0 comms.&lt;&#x2F;p&gt;
&lt;p&gt;So I wrote to their support, this time I wrote the text with the help of an LLM from another non-disabled organization.&lt;&#x2F;p&gt;
&lt;p&gt;I got no reply. Not even an automatic response.&lt;&#x2F;p&gt;
&lt;p&gt;And to wonder that people complain about civil servants, eh, wait until you have to deal with one of these expensive machines!&lt;&#x2F;p&gt;
&lt;p&gt;After a couple of days I got an e-mail:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;credit-note-from-anthropic-pbc-for-invoice&quot;&gt;Credit note from Anthropic, PBC for invoice #...&lt;&#x2F;h3&gt;
&lt;p&gt;Yes, the only e-mail I got was a credit note giving my money back.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s like they&#x27;re saying &quot;We don&#x27;t want to talk to you anymore, here is some hush money&quot;. But hey guys, it is not a conversation if it is one-way only, and here I am talking to a wall.&lt;&#x2F;p&gt;
&lt;p&gt;I didn&#x27;t even get to have a &quot;It&#x27;s not you, it&#x27;s us.&quot; I just got a credit note.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ahaha-i-m-so-happy&quot;&gt;Ahaha I&#x27;m so happy!&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m glad this happened with this particular non-disabled-organization. Because if this by chance had happened with the other non-disabled-organization that also provides such tools... then I would be out of e-mail, photos, documents, and phone OS.&lt;&#x2F;p&gt;
&lt;p&gt;AI moderation is currently a &quot;black box&quot; that prioritizes safety over accuracy to an extreme degree.&lt;&#x2F;p&gt;
&lt;p&gt;If you are automating prompts that look like system instructions (i.e. scaffolding context files), you are walking on a minefield.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I got my €220 back (ouch that&#x27;s a lot of money for this kind of service, thanks capitalism). I have reframed the whole scaffolding project, and reverted all the code Claude did there.&lt;&#x2F;p&gt;
&lt;p&gt;Soon I will re-release &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;pages&#x2F;boreDOM&#x2F;&quot;&gt;boreDOM&lt;&#x2F;a&gt; with a new angle and approach, without the help of Claude. I am trying to turn it into a JS framework for LLMs (llm first, or even llm only, it now has no API). To produce and iterate on those single.html files that these tools are now bringing to the world.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to take a look at the CLAUDE.md that Claude A was making Claude B run with, I commited it and it is available &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;boreDOM&#x2F;blob&#x2F;9a0802af16f5a1ff177799404c34ce5444345915&#x2F;boreDOMCLI&#x2F;cli.js#L129&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Again to wrap this up: this whole post is just my hypothesis. Claude was not doing anything other than iterating on this file at the moment I got the ban. And I haven&#x27;t heard from them about this anymore (or ever).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;you got to understand that these organizations have a lot of users...&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>PNGine: a WebGPU shader portability engine</title>
        <published>2025-12-31T00:00:00+00:00</published>
        <updated>2025-12-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/introducing-pngine/"/>
        <id>https://hugodaniel.com/posts/introducing-pngine/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/introducing-pngine/">&lt;p&gt;I&#x27;ve been working on a minimal shader portability engine since mid-2024. It was
used by me and my friend icid to create a demo for the Inércia demoparty 2025
that happened in Almada in early December.&lt;&#x2F;p&gt;
&lt;p&gt;The demo failed spectacularly.&lt;&#x2F;p&gt;
&lt;p&gt;We couldn&#x27;t show it during the competition because it crashed the browser tab on
the machine running the demos. Shortly after, we found it also didn&#x27;t work on
most computers and devices. At one point it even stopped working on my own
machine.&lt;&#x2F;p&gt;
&lt;p&gt;After the party we spent a few days thinking over what went wrong. That led me
to fix and redesign parts of the engine, optimize loose ends I&#x27;d left for
&quot;future me or some capable LLM,&quot; and finally write this post before the story
repeats itself.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;pngine.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;pngine.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h2 id=&quot;what-pngine-is&quot;&gt;What PNGine Is&lt;&#x2F;h2&gt;
&lt;p&gt;Bundle WebGPU shaders and pipeline configuration into a single portable file.
Run it anywhere with a small viewer.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s it. One file containing your render passes, compute shaders, buffers,
textures, bind groups, etc. Hand it to a viewer on any platform with WebGPU
support, and it can be played.&lt;&#x2F;p&gt;
&lt;p&gt;The file can be a PNG. The PNG format allows custom binary chunks after the
image data, working roughly like a .zip that holds things in it but in this case
it shows a picture by default (the png image).&lt;&#x2F;p&gt;
&lt;p&gt;Embed your WebGPU bundle in the PNG, and suddenly images can move if you have a
viewer that can look for the WebGPU bundle in them. It feels a bit like magic.&lt;&#x2F;p&gt;
&lt;p&gt;But PNGine also works with plain .zip files if you prefer. The PNG thing is just
the flashy option.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-is-not&quot;&gt;What This Is Not&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Not an animation format.&lt;&#x2F;strong&gt; For that, use Rive or Lottie.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Not a new vector format.&lt;&#x2F;strong&gt; For that, use SVG or something like that.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Not a design tool.&lt;&#x2F;strong&gt; For that, use Figma or Sketch.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Not a rendering engine.&lt;&#x2F;strong&gt; You write the shaders. PNGine just packages and runs
them. Maybe it should have been called DIYengine.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Not a way to make any PNG move.&lt;&#x2F;strong&gt; The image is just a container. Most of my
files are actually .zip.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-small&quot;&gt;How Small?&lt;&#x2F;h2&gt;
&lt;p&gt;Self-contained PNGs with embedded WebGPU information and executor:&lt;&#x2F;p&gt;
&lt;p&gt;A triangle: &lt;strong&gt;~13 KB&lt;&#x2F;strong&gt; (500 bytes bytecode + tailored executor).&lt;&#x2F;p&gt;
&lt;p&gt;A rotating 3D cube with depth buffer: &lt;strong&gt;~14 KB&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A full boids flocking simulation with compute shaders: &lt;strong&gt;~20 KB&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Embedding the WebGPU information and its executor in the .png guarantees that
they are self contained. No need to be fighting mismatching players&#x2F;viewers
versions bugs that can only play certain payloads in certain ways.&lt;&#x2F;p&gt;
&lt;p&gt;A PNG holds everything that it needs to be played as it was intended when it got
bundled by the creator of the visuals being shown. Everything except the tiny
extractor you need to have to read these extra chunks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how&quot;&gt;How?&lt;&#x2F;h2&gt;
&lt;p&gt;From a design perspective, the WebGPU instructions got moved into a full
declarative space. Things are described in a Domain Specific Language that
follows the spec but declares the whole WebGPU non-iteratively, abstract enough
so that it can be decomposed into a payload that can be run in the browser or in
your favorite native WebGPU implementation (
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;dawn&quot;&gt;dawn&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gfx-rs&#x2F;wgpu&quot;&gt;wgpu&lt;&#x2F;a&gt;,
any compatible web browser, etc...).&lt;&#x2F;p&gt;
&lt;p&gt;The DSL compiles to a custom bytecode, which DEFLATE-compresses into the PNG.
The compiler builds a tailored WASM executor containing only the parts your
shader needs to run—typically 12-18 KB. Together they&#x27;re small enough to inline
in HTML or use as a favicon.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-dsl&quot;&gt;The DSL&lt;&#x2F;h2&gt;
&lt;p&gt;The user facing part of PNGine uses a domain-specific language that maps
directly to WebGPU. The rule is simple: every &lt;code&gt;device.create*()&lt;&#x2F;code&gt; function
becomes a &lt;code&gt;#macro&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;device.createBuffer(...)         →  #buffer name { ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;device.createTexture(...)        →  #texture name { ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;device.createRenderPipeline(...) →  #renderPipeline name { ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &quot;create&quot; disappears, &quot;#&quot; takes its place, and you give it a name to
reference elsewhere. What goes inside &lt;code&gt;{ }&lt;&#x2F;code&gt; are the function arguments, written
as &lt;code&gt;name=value&lt;&#x2F;code&gt;. The names come directly from the WebGPU spec—I didn&#x27;t invent
them.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a minimal triangle:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#shaderModule code {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  code=&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @vertex fn vs(@builtin(vertex_index) i: u32) -&amp;gt; @builtin(position) vec4f {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      var pos = array&amp;lt;vec2f, 3&amp;gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        vec2f(0.0, 0.5),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        vec2f(-0.5, -0.5),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        vec2f(0.5, -0.5)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      return vec4f(pos[i], 0.0, 1.0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @fragment fn fs() -&amp;gt; @location(0) vec4f {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      return vec4f(1.0, 0.5, 0.0, 1.0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#renderPipeline pipeline {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  layout=auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  vertex={ module=code entryPoint=vs }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fragment={ module=code entryPoint=fs targets=[{ format=preferredCanvasFormat }] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#renderPass pass {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  colorAttachments=[{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    view=contextCurrentTexture&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    clearValue=[0 0 0 1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    loadOp=clear&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    storeOp=store&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  pipeline=pipeline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  draw=3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#frame main {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  perform=[pass]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Compile it: &lt;code&gt;pngine triangle.pngine -o triangle.png&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s your ~500 byte triangle, embedded in a PNG alongside a WASM executor
ready to show it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shape-generators&quot;&gt;Shape Generators&lt;&#x2F;h2&gt;
&lt;p&gt;Writing vertex data by hand is tedious. So the compiler can generate it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#data cubeVertices {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  cube={ format=[position4 color4 uv2] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ a cube!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#buffer vertexBuffer {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  size=cubeVertices&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  usage=[VERTEX]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mappedAtCreation=cubeVertices&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ names can be used as references to WebGPU parameters&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; The compiler understands and takes care of everything beforehand&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This generates a unit cube with 36 vertices at compile time. The &lt;code&gt;format=&lt;&#x2F;code&gt;
specifies what attributes each vertex has: position, color, normals, UVs. No
more copying vertex arrays from tutorials.&lt;&#x2F;p&gt;
&lt;p&gt;Available shapes: &lt;code&gt;cube&lt;&#x2F;code&gt;, &lt;code&gt;plane&lt;&#x2F;code&gt;. More coming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;built-in-uniforms&quot;&gt;Built-in Uniforms&lt;&#x2F;h2&gt;
&lt;p&gt;For animation, you need time and canvas dimensions. Instead of wiring that up
yourself:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#buffer uniforms {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  size=16&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  usage=[UNIFORM COPY_DST]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#queue writeTime {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  writeBuffer={&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buffer=uniforms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    bufferOffset=0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    data=pngineInputs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#frame main {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  perform=[writeTime renderPass]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;pngineInputs&lt;&#x2F;code&gt; identifier gives you 16 bytes every frame: time (f32), width
(f32), height (f32), aspect ratio (f32). Your shader just reads them.&lt;&#x2F;p&gt;
&lt;p&gt;This is the only builtin identifier of the engine. All custom uniforms can be
set using your data as initialization and are available in the viewer API to be
written to.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;balls.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;balls.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h2 id=&quot;the-architecture&quot;&gt;The Architecture&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  DSL Source     │  Human-readable .pngine file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────┬────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         │ compile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         ▼&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  PNGB Bytecode  │  ~500 bytes to ~8 KB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────┬────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         │ embed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         ▼&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  PNG File       │  Image + bytecode + tailored executor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────┬────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         │ load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         ▼&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  WASM Executor  │  ~15 KB, interprets bytecode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└────────┬────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         │ calls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         ▼&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌─────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  WebGPU         │  Your GPU does the work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└─────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The compiler does the heavy lifting. It parses the DSL, resolves references,
validates everything, and emits compact bytecode. The executor is deliberately
simple—it just reads opcodes and calls WebGPU functions. No surprises.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wgsl-shader-strings&quot;&gt;WGSL shader strings&lt;&#x2F;h2&gt;
&lt;p&gt;The shader strings are compressed in the PNG. They are validated and minified
through &lt;a href=&quot;&#x2F;posts&#x2F;miniray&#x2F;&quot;&gt;miniray&lt;&#x2F;a&gt;. Miniray also provides special reflection
data on them which allows variables to be mapped before and after minification,
and accessed in a natural way through the viewer API, with all the memory
layouts and offsets already baked in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-interpreter-trade-off&quot;&gt;The Interpreter Trade-off&lt;&#x2F;h2&gt;
&lt;p&gt;The WASM interpreter is bundled inside the PNG by default. The compiler analyzes
your DSL and builds a tailored executor containing only the parts you need
(render, compute, animation, etc.). This keeps each file self-contained—no
external WASM file to host or fetch and no complex viewer.&lt;&#x2F;p&gt;
&lt;p&gt;This has consequences:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The bad:&lt;&#x2F;strong&gt; If you have multiple PNGine canvases on one page, each loads its
own interpreter. The size accumulates, sure it&#x27;s small, slowly but steadily.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The ugly:&lt;&#x2F;strong&gt; If I fix a bug in the interpreter, you need to recompile your
PNGine files. I can&#x27;t just push a fix and have everyone benefit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The good:&lt;&#x2F;strong&gt; If it works, it works. Future updates won&#x27;t break it. You test it
where it needs to run, and that exact version ships with your file.&lt;&#x2F;p&gt;
&lt;p&gt;This trade-off made the interpreter a critical piece. It has to be tiny, fast,
and unsurprising. All complexity lives in the compiler, who does the heavy
lifting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-viewer&quot;&gt;The Viewer&lt;&#x2F;h2&gt;
&lt;p&gt;A small amount of JavaScript loads and runs PNGine files executors with their
payloads:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; destroy&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; draw&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; play&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pngine&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Load from PNG into a canvas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; await&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pngine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;shader.png&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  canvas&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;canvas&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Option 1: Let it animate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;play&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Option 2: Control it yourself&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;draw&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; audioContext&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;currentTime&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;draw&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; videoElement&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;currentTime&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;draw&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; time&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; slider&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Cleanup when done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;destroy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At its core, PNGine is stateless: &lt;code&gt;draw(p, { time })&lt;&#x2F;code&gt; renders one frame at a
specific time. You control when frames render.&lt;&#x2F;p&gt;
&lt;p&gt;But because &quot;give me an animation loop&quot; is so common, convenience functions
exist: &lt;code&gt;play(p)&lt;&#x2F;code&gt;, &lt;code&gt;pause(p)&lt;&#x2F;code&gt;, &lt;code&gt;stop(p)&lt;&#x2F;code&gt;, &lt;code&gt;seek(p, time)&lt;&#x2F;code&gt;. Use them or don&#x27;t.
Hook it to WebAudio, a scroll position, a MIDI clock, or plain
requestAnimationFrame. Your call.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try It Yourself&lt;&#x2F;h2&gt;
&lt;div class=&quot;pngine-demo&quot;&gt;
  &lt;div class=&quot;pngine-source&quot;&gt;
    &lt;img src=&quot;&#x2F;images&#x2F;pngine_logo.png&quot; alt=&quot;PNGine Logo - a static PNG containing a shader&quot;&gt;
    &lt;p&gt;This PNG contains a WebGPU shader. It looks static, but inside there&#x27;s bytecode waiting to run.&lt;&#x2F;p&gt;
    &lt;a href=&quot;&#x2F;images&#x2F;pngine_logo.png&quot; download class=&quot;pngine-download&quot;&gt;Download pngine_logo.png&lt;&#x2F;a&gt;
  &lt;&#x2F;div&gt;
&lt;div id=&quot;pngine-drop-zone&quot; class=&quot;pngine-drop-zone&quot;&gt;
    &lt;canvas id=&quot;pngine-demo-canvas&quot; width=&quot;400&quot; height=&quot;400&quot;&gt;&lt;&#x2F;canvas&gt;
    &lt;div class=&quot;pngine-drop-overlay&quot;&gt;
      &lt;p&gt;Drop the PNG here to see it animate&lt;&#x2F;p&gt;
      &lt;p class=&quot;hint&quot;&gt;or click to select file&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;
    &lt;input type=&quot;file&quot; id=&quot;pngine-file-input&quot; accept=&quot;.png&quot; hidden&gt;
  &lt;&#x2F;div&gt;
&lt;p id=&quot;pngine-demo-hint&quot; class=&quot;pngine-hint&quot;&gt;Drop the PNG above to watch it come to life.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;style&gt;
.pngine-demo { margin: 2rem 0; }
.pngine-source { text-align: center; margin-bottom: 1.5rem; }
.pngine-source img { max-width: 200px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
.pngine-source p { margin: 0.75rem 0; color: #666; }
.pngine-download { display: inline-block; margin-top: 0.5rem; padding: 0.5rem 1rem; background: #C75D3A; color: white; text-decoration: none; border-radius: 4px; font-weight: 500; }
.pngine-download:hover { background: #a84d2f; }
.pngine-drop-zone { position: relative; width: 100%; max-width: 400px; aspect-ratio: 1; margin: 0 auto; border: 2px dashed #aaa; border-radius: 8px; overflow: hidden; background: #f9f9f9; }
.pngine-drop-zone.dragover { border-color: #C75D3A; background: rgba(199,93,58,0.1); }
.pngine-drop-zone canvas { width: 100%; height: 100%; display: block; }
.pngine-drop-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; background: rgba(255,255,255,0.95); cursor: pointer; }
.pngine-drop-overlay p { margin: 0.25rem 0; }
.pngine-drop-overlay .hint { font-size: 0.85em; color: #666; }
.pngine-hint { text-align: center; color: #666; margin-top: 1rem; font-style: italic; }
@media (prefers-color-scheme: dark) {
  .pngine-source p { color: #aaa; }
  .pngine-drop-zone { background: #2a2a2a; border-color: #555; }
  .pngine-drop-zone.dragover { background: rgba(199,93,58,0.2); }
  .pngine-drop-overlay { background: rgba(30,30,30,0.95); }
  .pngine-drop-overlay .hint { color: #888; }
  .pngine-hint { color: #888; }
}
&lt;&#x2F;style&gt;
&lt;h2 id=&quot;the-cli&quot;&gt;The CLI&lt;&#x2F;h2&gt;
&lt;p&gt;The command-line tool compiles, validates, and inspects:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Compile to PNG with embedded bytecode and executor (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; shader.pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; shader.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Smaller PNG without executor (needs shared pngine.wasm at runtime)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; shader.pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;-no-executor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; shader.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Render an actual frame (not just embed)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; shader.pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;-frame&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; 1920x1080&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; preview.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Validate and see what GPU calls it makes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; check&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; shader.png&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;-verbose&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;--verbose&lt;&#x2F;code&gt; flag on check shows every GPU call the bytecode will make. Good
for debugging why your shader isn&#x27;t doing what you expect.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to Use It&lt;&#x2F;h2&gt;
&lt;p&gt;Currently PNGine only supports web browsers. iOS and Android viewers are coming
soon™ (when we decide on making a demo for them and see if they crash ahah).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pngine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Create a &lt;code&gt;.pngine&lt;&#x2F;code&gt; file with your shaders and pipeline setup. Compile it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;npx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; myshader.pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; myshader.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Load it in your page:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; play&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pngine&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;pngine&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; await&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pngine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;myshader.png&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  canvas&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;canvas&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;play&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s it. Your shader is now a PNG that plays anywhere WebGPU runs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;target-users&quot;&gt;Target Users&lt;&#x2F;h2&gt;
&lt;p&gt;Like all things I do for fun, this is a Public Domain (CC0) project.&lt;&#x2F;p&gt;
&lt;p&gt;I built it for myself, to spend more time writing WGSL shaders and less time on
boilerplate. I&#x27;m exploring scenarios where I can make mini creative tools for
future Inércia demos, maybe resurrect old projects in this rendering approach.&lt;&#x2F;p&gt;
&lt;p&gt;If you like shaders and want a fun way to package and share them without big
limitations on expressiveness, maybe PNGine won&#x27;t be a total waste of your time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;next-inercia&quot;&gt;Next Inércia&lt;&#x2F;h2&gt;
&lt;p&gt;Will this crash the demoparty competition machine again? Probably. But at least
now I can run &lt;code&gt;pngine check demo.png --verbose&lt;&#x2F;code&gt; and see exactly what GPU calls
it makes before I embarrass myself.&lt;&#x2F;p&gt;
&lt;p&gt;I am still working on the proper site for this with one of those fancy landing
pages. The source is on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;pngine&quot;&gt;GitHub&lt;&#x2F;a&gt;. The
Inércia demo that failed is somewhere in my shame folder.&lt;&#x2F;p&gt;
&lt;p&gt;See you at the next demoparty.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introducing miniray — a WGSL minifier</title>
        <published>2025-12-30T00:00:00+00:00</published>
        <updated>2025-12-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/miniray/"/>
        <id>https://hugodaniel.com/posts/miniray/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/miniray/">&lt;p&gt;I&#x27;ve been spending a lot of time playing with WebGPU shaders just for fun.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;cubos_fuzzy_compressed.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;cubos_fuzzy_compressed.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Coming from JS&#x2F;TS world and bouncing back and forth between compute.toys and
&lt;a href=&quot;&#x2F;posts&#x2F;introducing-pngine&#x2F;&quot;&gt;pngine&lt;&#x2F;a&gt; (a portable shader runtime I am working on)
has led me to miss some of the things we take for granted in frontend
development that are actually useful when doing stuff in other more specific
languages such as WGSL.&lt;&#x2F;p&gt;
&lt;p&gt;Minification and pre-validation are a few of these things.&lt;&#x2F;p&gt;
&lt;p&gt;This post introduces a tool for those purposes and more called
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;miniray&#x2F;&quot;&gt;&quot;miniray&quot;&lt;&#x2F;a&gt;. Courtesy of Claude Code
(some parts by me, but mostly Claude Code).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inercia-demoparty-2025-gataria-demo&quot;&gt;Inércia demoparty 2025 &quot;gataria&quot; demo&lt;&#x2F;h2&gt;
&lt;p&gt;I spent more time than I would like to admit doing a demo for the Inércia
Demoparty. This happened in December 2025. The final result had a lot of issues,
it was a testbed for bad practices and failed ideas and approaches, while
desperately trying to punch way above its weight.&lt;&#x2F;p&gt;
&lt;p&gt;When the event demoparty competition arrived, the demo didn&#x27;t even run to the
end. It crashed the tab and the browser of the compo machine.&lt;&#x2F;p&gt;
&lt;p&gt;On top of that it was a huge final file for what it had, around 1MB, we could
have done the same in much less space (if only we had more time).&lt;&#x2F;p&gt;
&lt;p&gt;Most of the ~1MB of the demo was occupied with WGSL shader code. It had a video
asset (~300KB), a small runtime (~50KB) and the rest was occupied by glorious
WGSL strings.&lt;&#x2F;p&gt;
&lt;p&gt;These strings were developed for fun, nothing more. But there were also some
painful parts to it, such as not being able to show the entire demo ahah!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;strings-for-fun&quot;&gt;Strings for fun&lt;&#x2F;h3&gt;
&lt;p&gt;WGSL is a text-based format (unlike SPIR-V binary), and like JS, minification
can provide for significant savings.&lt;&#x2F;p&gt;
&lt;p&gt;Having hand-coded (or brain-coded, or whatever people are calling writing
regular code these days) the demo shaders made me realize that I didn&#x27;t want to
have a full hard minimization of the code. Some things would be important to be
kept as is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;entrypoints&lt;&#x2F;strong&gt;: these are used by the WebGPU plumbing, which I didn&#x27;t want to
be updating after minification.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;uniforms&lt;&#x2F;strong&gt;: some reflection on the code was being done for these, which made
them important not to mess with when minimizing.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;@location and @builtin&lt;&#x2F;strong&gt;: these names provide a bridge between pipeline
stages, I had a few contraptions for them in other places outside WGSL and
didn&#x27;t want them to be mangled with.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;On top of these, there was a whole custom graphics engine framework that took me
a year and a half to do. This also required special care and considerations here
and there for the minification process.&lt;&#x2F;p&gt;
&lt;p&gt;Having met Claude Opus 4.5 recently I thought that it would be cool to talk it
through a WGSL minification tool. The WGSL validation, reflection and
minification are going to be important parts of my foreseeable future projects,
just ripe to be off-shored by capitalism.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;validation&quot;&gt;Validation&lt;&#x2F;h3&gt;
&lt;p&gt;In WebGPU the dance mandates that the WGSL string gets compiled into a Shader
Module, which then gets placed in a pipeline, which then gets placed in a pass,
which then gets placed in an encoder.&lt;&#x2F;p&gt;
&lt;p&gt;Some errors of that string are caught early in the compilation stage, but some
errors are more aligned with life traditions and only blow up in delicate
situations when the project is running.&lt;&#x2F;p&gt;
&lt;p&gt;One thing about WebGPU is that WGSL compilation happens in runtime. Compilation
errors are deferred to runtime because you compile in the browser, while the
code is running.&lt;&#x2F;p&gt;
&lt;p&gt;Since miniray is going to build a whole AST of WGSL why not validate it
semantically as well? This way we could demote compilation errors (which in
WebGPU happen in runtime) to become pre-compilation errors, by running an
offline tool beforehand.&lt;&#x2F;p&gt;
&lt;p&gt;Yeah Claude, let&#x27;s bring WGSL validation to the CLI without having to go through
the WebGPU runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike us, Claude has eaten for breakfast the souls and dreams of humanity
finest works, but I knew it wasn&#x27;t enough. So I fed it the WebGPU Dawn WGSL
tests. It was fun seeing all that work getting eaten in a frivolous manner like
it was getting sucked by an unstoppable machine whose efficiency is matched only
by the steamroller force of the free markets.&lt;&#x2F;p&gt;
&lt;p&gt;Now miniray can do WGSL validation in the command line in a way comparable to
what Google Chrome does in the browser. Claude, my greatest friend, fetch me a C
FFI, and wasm build for this as well. It might come in handy for future
projects.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;meeting-claude&quot;&gt;Meeting Claude&lt;&#x2F;h2&gt;
&lt;p&gt;The year is ending, and with it a lot of old school developers are writing about
their points of view on LLMs and AIs. Strongly opinionated pieces show up here
and there. Charged with emotional anxious tone, these posts have taken the place
of the &quot;Why I left Google&#x2F;Facebook&#x2F;etc&quot; commotion that used to show up before
these firms started laying off people like cattle.&lt;&#x2F;p&gt;
&lt;p&gt;This is one of those posts.&lt;&#x2F;p&gt;
&lt;p&gt;Claude excels in delivering rapid, high-impact results, maintains a strong
solutions-oriented mindset, and has demonstrated performance that warrants
serious consideration for increased responsibility and compensation. At the end
of the day, it&#x27;s the last person who should end up anywhere near a PIP.&lt;&#x2F;p&gt;
&lt;p&gt;Occasionally shows an unusual level of deference toward me. I&#x27;m not entirely
sure why. Engineers aren&#x27;t typically known for their people skills, but in my
experience that level of flattery was usually directed elsewhere. Not that I&#x27;m
complaining.&lt;&#x2F;p&gt;
&lt;p&gt;I feel that 2026 will be the year of ass-kissing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;miniray&quot;&gt;Miniray&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;miniray.png&quot; alt=&quot;miniray&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Unlike UNIX tooling, miniray is meant to do three things and do them well:
minifies WGSL code, validates it, and outputs the reflection structured output
about the code. In the future it might do a couple more things if the need
arises.&lt;&#x2F;p&gt;
&lt;p&gt;It is also heavily tested, and under constant usage by me. I am focusing on
stability now and releasing it to the public domain (I hope Claude doesn&#x27;t
mind).&lt;&#x2F;p&gt;
&lt;p&gt;I love reading the esbuild code (go check it out). The miniray inspiration that
inspired Claude, was inspired by it. It is done in Go, a language I can mostly
read, and respect (and that&#x27;s about it, because I never tried to write Go).&lt;&#x2F;p&gt;
&lt;p&gt;Specs aside, I believe WGSL programming will be an important part of my future
as it becomes the target of creative fun explorations, an island of refuge in a
sea of mechanical automatisms such as miniray.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Miniray started as an experiment, became a tool, and will probably end up
powering a bunch of my WebGPU experiments in 2026. If you write shader code and
feel the need for any of these three things (minification, validation and
reflection), then miniray is intended to be a useful solid tool in doing them.&lt;&#x2F;p&gt;
&lt;p&gt;Try it online &lt;a href=&quot;&#x2F;pages&#x2F;miniray&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>WebGPU and the price of compiling WGSL</title>
        <published>2025-10-06T00:00:00+00:00</published>
        <updated>2025-10-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/webgpu-diagnostics/"/>
        <id>https://hugodaniel.com/posts/webgpu-diagnostics/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/webgpu-diagnostics/">&lt;p&gt;Welcome, in the previous two posts I went looking for the WGSL limits (both
&lt;a href=&quot;&#x2F;posts&#x2F;webgpu-shader-limits&#x2F;&quot;&gt;in the spec&lt;&#x2F;a&gt;, and also
&lt;a href=&quot;&#x2F;posts&#x2F;webgpu-shader-unknown-limits&#x2F;&quot;&gt;out of it&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;In this post I want to introduce a simple WebGPU app where you can create WGSL
shaders by dragging some sliders to increase their complexity.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is that compilation time and complexity can be known for the compute
and rendering pipelines as well as in their different stages (vertex and
fragment).&lt;&#x2F;p&gt;
&lt;p&gt;This is important to me because I wanted to know how much it costs to increase
the shader complexity and where it might be worth to start considering using
buffers&#x2F;textures for some of it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-long-does-it-take-to-compile-a-3megabyte-vertex-shader&quot;&gt;How long does it take to compile a 3Megabyte vertex shader?&lt;&#x2F;h3&gt;
&lt;p&gt;Easy to know, here is the single result of the cold timings in Chrome
(140.0.7339.215) from my Intel MacBook Pro (2019):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;vertexshadertimings.webp&quot; alt=&quot;Timings for a 3Megabyte vertex shader&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-about-a-30megabyte-vertex-shader&quot;&gt;How about a 30Megabyte vertex shader??&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;vertexshadererror.webp&quot; alt=&quot;Error compiling vertex shader&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It errors. Ah!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;webgpudiagnostics.webp&quot; alt=&quot;WebGPU logo with a stopwatch&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tool&quot;&gt;The tool&lt;&#x2F;h2&gt;
&lt;p&gt;A simple tool, along the lines of the awesome
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webgpureport.org&#x2F;&quot;&gt;WebGPU report&lt;&#x2F;a&gt;, but not as exhaustive.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;You can find it here:&lt;&#x2F;strong&gt;
&lt;a href=&quot;&#x2F;pages&#x2F;webgpu-diagnostics&#x2F;&quot;&gt;WebGPU Diagnostics (and compilation benchmark) tool&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My intention was to compose it of 3 major parts:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A simple sample (a rotating triangle).&lt;&#x2F;li&gt;
&lt;li&gt;Shader complexity sliders and timings (compilation, adapter request and
pipeline creation).&lt;&#x2F;li&gt;
&lt;li&gt;Device and adapter info (features, and announced limits)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;rotating-triangle&quot;&gt;Rotating triangle&lt;&#x2F;h3&gt;
&lt;p&gt;The rotating triangle is made from the 3 initial shaders. A compute shader
outputs vertices, then a vertex shader transforms them, and finally a fragment
shader paints it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;video id=&quot;triangleVideo&quot; src=&quot;&#x2F;videos&#x2F;rotating-triangle.mp4&quot; controls style=&quot;width: 100%&quot;&gt;&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I think of this as a kind of &quot;hello world&quot; for WebGPU but also as a simple
program that performs the happy path of the fastest rendering possible (or close
to it).&lt;&#x2F;p&gt;
&lt;p&gt;The idea along the app is that this triangle &lt;strong&gt;never changes&lt;&#x2F;strong&gt;. It always
remains the same as the shader complexity increases.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;shader-complexity-sliders&quot;&gt;Shader complexity sliders&lt;&#x2F;h3&gt;
&lt;p&gt;Shader complexity can be increased at each pipeline stage. This includes
separating the vertex shader from the fragment shader into different modules, to
allow testing how much they differ (if they do at all).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;sliders.webp&quot; alt=&quot;Image of the shader sliders in the WebGPU Diagnostics tool&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The shader string is created before compilation starts. This is done in a
WebWorker thread to keep the UI responsive (as much as possible) as memory and
string traversal time increases.&lt;&#x2F;p&gt;
&lt;p&gt;I wanted to make these sliders biased towards complexity. A small change in them
has to make the shader size increase by quite a bit. Making them purposefully
unbalanced to ensure that device limits can be checked.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-wgsl-code-the-sliders-generate&quot;&gt;What WGSL code the sliders generate?&lt;&#x2F;h3&gt;
&lt;p&gt;They are split into three categories:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Number of functions - dump n functions with 1 &lt;code&gt;f32&lt;&#x2F;code&gt; argument each that return
the single variable declared in the body.&lt;&#x2F;li&gt;
&lt;li&gt;Number of statements - for each function in 1., creates n statements that
just do a simple assignment.&lt;&#x2F;li&gt;
&lt;li&gt;Expression depth - for each statement in 2. expands it to have n sums.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So if we set them all to 8 (8 functions, each with 8 statements, each with 8
sums), it produces a 5Kilobyte file.&lt;&#x2F;p&gt;
&lt;p&gt;You can check the generator code
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;webgpu-diagnostics&#x2F;blob&#x2F;main&#x2F;src&#x2F;generator.js&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;details&gt;
  &lt;summary&gt;Or click here to see the output produced with the three sliders at value 8&lt;&#x2F;summary&gt;
  &lt;code class=&quot;error-content&quot;&gt;
  &lt;pre&gt;
&lt;p&gt;struct Vertex { position: vec3f, color: vec3f, }&lt;&#x2F;p&gt;
&lt;p&gt;struct Params { angle: f32, }&lt;&#x2F;p&gt;
&lt;p&gt;&#x2F;&#x2F; Storage buffer that will hold our generated vertices @group(0) @binding(0)
var&amp;lt;storage, read_write&amp;gt; vertices: array&amp;lt;Vertex, 3&amp;gt;; @group(0) @binding(1)
var&lt;uniform&gt; params: Params;&lt;&#x2F;p&gt;
&lt;p&gt;fn function0(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;fn function1(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;fn function2(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;fn function3(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;fn function4(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;fn function5(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;fn function6(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;fn function7(a: f32) -&amp;gt; f32 { var tmp: f32 = 0.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp +=
0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; tmp += 0.0+1.0+2.0+3.0+4.0+5.0+6.0+7.0; return
a + tmp; }&lt;&#x2F;p&gt;
&lt;p&gt;&#x2F;&#x2F; Compute shader that generates a triangle&#x27;s vertices @compute
@workgroup_size(1) fn compute_main(@builtin(global_invocation_id) global_id:
vec3u) { var accum: f32 = 0.0; accum += function0(8.0); accum += function1(8.0);
accum += function2(8.0); accum += function3(8.0); accum += function4(8.0); accum
+= function5(8.0); accum += function6(8.0); accum += function7(8.0);&lt;&#x2F;p&gt;
&lt;p&gt;&#x2F;&#x2F; Generate 3 vertices for a triangle &#x2F;&#x2F; We only need one invocation for this
simple example if (global_id.x == 0) { let angle = params.angle + accum *
0.0001; let cos_angle = cos(angle); let sin_angle = sin(angle); let
base_positions = array&amp;lt;vec2f, 3&amp;gt;( vec2f(0.0, 0.5), vec2f(-0.5, -0.8), vec2f(0.5,
-0.5) );&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let top = vec2f(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      base_positions[0].x * cos_angle - base_positions[0].y * sin_angle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      base_positions[0].x * sin_angle + base_positions[0].y * cos_angle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let left = vec2f(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      base_positions[1].x * cos_angle - base_positions[1].y * sin_angle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      base_positions[1].x * sin_angle + base_positions[1].y * cos_angle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let right = vec2f(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      base_positions[2].x * cos_angle - base_positions[2].y * sin_angle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      base_positions[2].x * sin_angle + base_positions[2].y * cos_angle,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let depth = clamp(accum * 0.001, -0.5, 0.5);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; Top vertex (red)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  vertices[0].position = vec3f(top, depth);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  vertices[0].color = vec3f(1.0, 0.0, 0.0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; Bottom-left vertex (green)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  vertices[1].position = vec3f(left, depth);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  vertices[1].color = vec3f(0.0, 1.0, 0.0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; Bottom-right vertex (blue)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  vertices[2].position = vec3f(right, depth);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  vertices[2].color = vec3f(0.0, 0.0, 1.0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;} }&lt;&#x2F;p&gt;
&lt;&#x2F;pre&gt;
&lt;&#x2F;code&gt;
&lt;&#x2F;details&gt;
&lt;h3 id=&quot;device-and-adapter-info&quot;&gt;Device and adapter info&lt;&#x2F;h3&gt;
&lt;p&gt;The features and limits is a nice thing to have in these kind of tools. They are
not used, just communicated. A lot of them I don&#x27;t know what they do, so I
included a link to the corresponding WebGPU spec chapter.&lt;&#x2F;p&gt;
&lt;p&gt;An important part here is that I wanted to separate the &lt;em&gt;adapter&lt;&#x2F;em&gt; limits from
the &lt;em&gt;device&lt;&#x2F;em&gt; limits. These can be different, and knowing these differences might
be important when we are aiming for the upper end of the lot.&lt;&#x2F;p&gt;
&lt;p&gt;In WebGPU the adapter limits can be seen as the announced values of what might
exist, while the device limits can be seen as what we have to work with.&lt;&#x2F;p&gt;
&lt;p&gt;These can be requested through the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;GPUAdapter&#x2F;requestDevice#requiredlimits&quot;&gt;requiredLimits&lt;&#x2F;a&gt;
on creation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;extra-motivation&quot;&gt;Extra motivation&lt;&#x2F;h2&gt;
&lt;p&gt;Another important part of motivation for doing this was to use
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;pages&#x2F;boreDOM&#x2F;&quot;&gt;boreDOM&lt;&#x2F;a&gt;. A minimal JS framework that I
created as a fun project that tries to do what major JS frameworks do but with a
different approach just because why not? (no bundling, no compilation, no
minification, and small size).&lt;&#x2F;p&gt;
&lt;p&gt;It was fun and cool to see that it works without bundling&#x2F;compilation while
handling WebGPU&#x27;s complexity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Go ahead, play with it a bit &lt;a href=&quot;&#x2F;pages&#x2F;webgpu-diagnostics&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and let me know
how your device and browser reacts to massive shaders.&lt;&#x2F;p&gt;
&lt;p&gt;I found that there is a significant difference between cold and warm compilation
times. This cold vs warm timing distinction could be interesting to explore
further, and maybe it could even be leveraged&#x2F;exploited to hide extremely
complex shaders by splitting them in many small pipelines (just a wild
hypothesis at this point i guess).&lt;&#x2F;p&gt;
&lt;p&gt;This post wraps the WGSL limits endeavour. For the next ones I might be
introducing a &lt;a href=&quot;&#x2F;posts&#x2F;introducing-pngine&#x2F;&quot;&gt;rendering engine I am working&lt;&#x2F;a&gt; that
tries to perform with rendering the same spirit as boreDOM has to JS frameworks.
Thanks for reading all of this and stay tuned!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>WGSL limits you won&#x27;t find in the spec</title>
        <published>2025-09-21T00:00:00+00:00</published>
        <updated>2025-09-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/webgpu-shader-unknown-limits/"/>
        <id>https://hugodaniel.com/posts/webgpu-shader-unknown-limits/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/webgpu-shader-unknown-limits/">&lt;style&gt;
  .result-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;margin:12px 0 16px}
  .result-card{border:1px solid var(--border,rgba(0,0,0,.12));border-radius:12px;padding:12px;background:var(--elev,#fff);
    box-shadow:0 1px 3px rgba(0,0,0,.06)}
  .result-card h4{margin:0 0 6px;font-size:1rem;line-height:1.2}
  .kv{display:flex;gap:8px;flex-wrap:wrap;margin:6px 0}
  .badge{display:inline-block;padding:2px 8px;border-radius:9999px;font-size:.82em;font-weight:600;border:1px solid transparent}
  .ok{background:#e6ffed;color:#0f6b2b;border-color:#b6efc5}
  .err{background:#ffe8e8;color:#9b1c1c;border-color:#f3b0b0}
  .na{background:#f1f5f9;color:#334155;border-color:#cbd5e1}
  .limit{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; margin-top: 1rem;}
  .msg{margin-top:6px;font-style:italic;opacity:.9}
&lt;&#x2F;style&gt;
&lt;p&gt;Welcome back, in my &lt;a href=&quot;&#x2F;posts&#x2F;webgpu-shader-limits&#x2F;&quot;&gt;last post&lt;&#x2F;a&gt; I did an
evaluation of the WebGPU shader limits that we are told about in the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;WGSL&#x2F;#limits&quot;&gt;WGSL spec&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Having tested only the known shader limits in the spec in that previous post,
this time I want to go a bit away from it.&lt;&#x2F;p&gt;
&lt;p&gt;For this post I want to take a look at the limits we have when writing a WGSL
shader that cannot be found in the spec.&lt;&#x2F;p&gt;
&lt;p&gt;Some of these experiments I tried purely for fun, hoping to stumble on a
creative angle. Others are just fresh findings.&lt;&#x2F;p&gt;
&lt;p&gt;In retrospect this feels a bit like off-road terrain that nobody cares about,
these are limits after all, so fasten the seatbelt and let&#x27;s take a ride.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h3&gt;
&lt;p&gt;Tests were run on macOS 15.6.1 on an Intel Mac equipped with both Intel and AMD
GPUs. The reported adapter vendor is &lt;em&gt;&quot;Intel&quot;&lt;&#x2F;em&gt; and architecture is &lt;em&gt;&quot;gen-9&quot;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;All code is run in a webworker in an offline canvas, with a WebGPU DSL that I
have been cooking as a creative tool to maybe produce something in time for
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;2025.inercia.pt&#x2F;en&#x2F;&quot;&gt;Inércia Demoparty 2025&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This home-made DSL allows macros to define all parts of the WebGPU plumbing
(more on that in the next posts).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;bench.webp&quot; alt=&quot;A bench with a nice view&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-the-main-unknown-practical-limit&quot;&gt;1 - The main unknown practical limit&lt;&#x2F;h3&gt;
&lt;p&gt;When composing a big WGSL shader the main limit we have to consider is &lt;em&gt;How big
can a JS string actually get?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After all, WebGPU is somewhat tied to JS from a portability angle. The
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;String&#x2F;length&quot;&gt;string length section of MDN&lt;&#x2F;a&gt;
puts it nicely:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The language specification requires strings to have a maximum length of
2&lt;sup&gt;53&lt;&#x2F;sup&gt; - 1 elements, which is the upper limit for precise integers.
However, a string with this length needs 16384TiB of storage, which cannot fit
in any reasonable device&#x27;s memory, so implementations tend to lower the
threshold, which allows the string&#x27;s length to be conveniently stored in a
32-bit integer.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;In V8 (used by Chrome and Node), the maximum length is 2&lt;sup&gt;29&lt;&#x2F;sup&gt; - 24
(~1GiB). On 32-bit systems, the maximum length is 2&lt;sup&gt;28&lt;&#x2F;sup&gt; - 16
(~512MiB).&lt;&#x2F;li&gt;
&lt;li&gt;In Firefox, the maximum length is 2&lt;sup&gt;30&lt;&#x2F;sup&gt; - 2 (~2GiB)...&lt;&#x2F;li&gt;
&lt;li&gt;In Safari, the maximum length is 2&lt;sup&gt;31&lt;&#x2F;sup&gt; - 1 (~4GiB).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It&#x27;s nice to see Safari upping the limits.&lt;&#x2F;p&gt;
&lt;p&gt;That MDN article is very interesting, with theory and code examples on how to
get to these limits. For my purposes I am going to assume that we are dealing
with a safe limit of &lt;code&gt;512MiB&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s a big shader!&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t expect to hit this limit on my tests because I am using &lt;code&gt;JSON.stringify&lt;&#x2F;code&gt;
on the shader string to send it together with metadata to my DSL engine WebGPU
player. The &lt;code&gt;stringify()&lt;&#x2F;code&gt; function itself acts as a memory barrier for such huge
strings.&lt;&#x2F;p&gt;
&lt;p&gt;Within this constraint, what other limits are waiting for us?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-express-your-self-syntax-errors&quot;&gt;2 - Express your self syntax errors&lt;&#x2F;h3&gt;
&lt;p&gt;How big can an expression be in WGSL? let&#x27;s find out:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; How big can we make this turn out to be?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 4.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ???&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For this test I created a small harness to expand the expression up to &lt;em&gt;&quot;n&quot;&lt;&#x2F;em&gt;
sums.&lt;&#x2F;p&gt;
&lt;p&gt;The results turned out to be consistent in both Safari and Chrome:&lt;&#x2F;p&gt;
&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 512&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“reached maximum expression depth of 512”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 512 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 512&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“reached max expression depth of 512”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 512 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Surprisingly consistent, even the error message is almost exactly the same.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-this-is-not-lisp&quot;&gt;3 - This is not LISP&lt;&#x2F;h3&gt;
&lt;p&gt;What if we create the expression like this instead:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; How many parentheses can we push here?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;4.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ??? &lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And again the results turned out to be consistent in both Safari and Chrome:&lt;&#x2F;p&gt;
&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 127&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“maximum parser recursive depth reached”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 127 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 127&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“maximum parser recursive depth reached”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 127 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This time even the error message is exactly the same.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-brackets-what-brackets&quot;&gt;4 - Brackets? what brackets?&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we know these limits, let&#x27;s try to create two of these, but chained
together, what could possibly go wrong?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result1&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 4.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 511.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; and lets place result1 here:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result2&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 4.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 511.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The results are surprising, but on the other end of the surprise:&lt;&#x2F;p&gt;
&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;No message, the tab becomes unresponsive. &lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; None, a timeout of 5 minutes was reached.&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge ok&quot;&gt;Compile: no error&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: Breaks with a big C++ error message.&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“ShaderModuleMTL: Unable to create library object: program_source:33:271: fatal error: bracket nesting level exceeded maximum of 256...”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 1 (Breaks at the first reference of the maximum expression) &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Chrome error message is intriguing. You can see it all if you want by clicking
down below.&lt;&#x2F;p&gt;
&lt;details&gt;
  &lt;summary&gt;Full Chrome Error Message (very long)&lt;&#x2F;summary&gt;
  &lt;code class=&quot;error-content&quot;&gt;
    ShaderModuleMTL: Unable to create library object: program_source:33:271: fatal error: bracket nesting level exceeded maximum of 256
program_source:33:271: note: use -fbracket-depth=N to increase maximum nesting level
 from produced MSL shader below:
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#ifdef __clang__&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#pragma clang diagnostic ignored &amp;quot;-Wall&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#endif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#pragma METAL fp math_mode(relaxed) #include &amp;lt;metal_stdlib&amp;gt; using namespace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;metal;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;template&amp;lt;typename T, size_t N&amp;gt; struct tint_array { const constant T&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;operator[](size_t i) const constant { return elements[i]; } device T&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;operator[](size_t i) device { return elements[i]; } const device T&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;operator[](size_t i) const device { return elements[i]; } thread T&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;operator[](size_t i) thread { return elements[i]; } const thread T&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;operator[](size_t i) const thread { return elements[i]; } threadgroup T&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;operator[](size_t i) threadgroup { return elements[i]; } const threadgroup T&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;operator[](size_t i) const threadgroup { return elements[i]; } T elements[N]; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;struct tint_struct { device tint_array&amp;lt;float, 1&amp;gt;* tint_member; const constant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tint_array&amp;lt;uint4, 1&amp;gt;* tint_member_1; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;struct tint_struct_1 { uint tint_member_2; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;float v() { float v_1 = 129795.0f; float v_2 =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((v_1 +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1.0f) + 2.0f) + 3.0f) + 4.0f) + 5.0f) + 6.0f) + 7.0f) + 8.0f) + 9.0f) + 10.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;11.0f) + 12.0f) + 13.0f) + 14.0f) + 15.0f) + 16.0f) + 17.0f) + 18.0f) + 19.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;20.0f) + 21.0f) + 22.0f) + 23.0f) + 24.0f) + 25.0f) + 26.0f) + 27.0f) + 28.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;29.0f) + 30.0f) + 31.0f) + 32.0f) + 33.0f) + 34.0f) + 35.0f) + 36.0f) + 37.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;38.0f) + 39.0f) + 40.0f) + 41.0f) + 42.0f) + 43.0f) + 44.0f) + 45.0f) + 46.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;47.0f) + 48.0f) + 49.0f) + 50.0f) + 51.0f) + 52.0f) + 53.0f) + 54.0f) + 55.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;56.0f) + 57.0f) + 58.0f) + 59.0f) + 60.0f) + 61.0f) + 62.0f) + 63.0f) + 64.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;65.0f) + 66.0f) + 67.0f) + 68.0f) + 69.0f) + 70.0f) + 71.0f) + 72.0f) + 73.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;74.0f) + 75.0f) + 76.0f) + 77.0f) + 78.0f) + 79.0f) + 80.0f) + 81.0f) + 82.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;83.0f) + 84.0f) + 85.0f) + 86.0f) + 87.0f) + 88.0f) + 89.0f) + 90.0f) + 91.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;92.0f) + 93.0f) + 94.0f) + 95.0f) + 96.0f) + 97.0f) + 98.0f) + 99.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;100.0f) + 101.0f) + 102.0f) + 103.0f) + 104.0f) + 105.0f) + 106.0f) + 107.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;108.0f) + 109.0f) + 110.0f) + 111.0f) + 112.0f) + 113.0f) + 114.0f) + 115.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;116.0f) + 117.0f) + 118.0f) + 119.0f) + 120.0f) + 121.0f) + 122.0f) + 123.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;124.0f) + 125.0f) + 126.0f) + 127.0f) + 128.0f) + 129.0f) + 130.0f) + 131.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;132.0f) + 133.0f) + 134.0f) + 135.0f) + 136.0f) + 137.0f) + 138.0f) + 139.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;140.0f) + 141.0f) + 142.0f) + 143.0f) + 144.0f) + 145.0f) + 146.0f) + 147.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;148.0f) + 149.0f) + 150.0f) + 151.0f) + 152.0f) + 153.0f) + 154.0f) + 155.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;156.0f) + 157.0f) + 158.0f) + 159.0f) + 160.0f) + 161.0f) + 162.0f) + 163.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;164.0f) + 165.0f) + 166.0f) + 167.0f) + 168.0f) + 169.0f) + 170.0f) + 171.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;172.0f) + 173.0f) + 174.0f) + 175.0f) + 176.0f) + 177.0f) + 178.0f) + 179.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;180.0f) + 181.0f) + 182.0f) + 183.0f) + 184.0f) + 185.0f) + 186.0f) + 187.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;188.0f) + 189.0f) + 190.0f) + 191.0f) + 192.0f) + 193.0f) + 194.0f) + 195.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;196.0f) + 197.0f) + 198.0f) + 199.0f) + 200.0f) + 201.0f) + 202.0f) + 203.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;204.0f) + 205.0f) + 206.0f) + 207.0f) + 208.0f) + 209.0f) + 210.0f) + 211.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;212.0f) + 213.0f) + 214.0f) + 215.0f) + 216.0f) + 217.0f) + 218.0f) + 219.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;220.0f) + 221.0f) + 222.0f) + 223.0f) + 224.0f) + 225.0f) + 226.0f) + 227.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;228.0f) + 229.0f) + 230.0f) + 231.0f) + 232.0f) + 233.0f) + 234.0f) + 235.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;236.0f) + 237.0f) + 238.0f) + 239.0f) + 240.0f) + 241.0f) + 242.0f) + 243.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;244.0f) + 245.0f) + 246.0f) + 247.0f) + 248.0f) + 249.0f) + 250.0f) + 251.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;252.0f) + 253.0f) + 254.0f) + 255.0f) + 256.0f) + 257.0f) + 258.0f) + 259.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;260.0f) + 261.0f) + 262.0f) + 263.0f) + 264.0f) + 265.0f) + 266.0f) + 267.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;268.0f) + 269.0f) + 270.0f) + 271.0f) + 272.0f) + 273.0f) + 274.0f) + 275.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;276.0f) + 277.0f) + 278.0f) + 279.0f) + 280.0f) + 281.0f) + 282.0f) + 283.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;284.0f) + 285.0f) + 286.0f) + 287.0f) + 288.0f) + 289.0f) + 290.0f) + 291.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;292.0f) + 293.0f) + 294.0f) + 295.0f) + 296.0f) + 297.0f) + 298.0f) + 299.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;300.0f) + 301.0f) + 302.0f) + 303.0f) + 304.0f) + 305.0f) + 306.0f) + 307.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;308.0f) + 309.0f) + 310.0f) + 311.0f) + 312.0f) + 313.0f) + 314.0f) + 315.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;316.0f) + 317.0f) + 318.0f) + 319.0f) + 320.0f) + 321.0f) + 322.0f) + 323.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;324.0f) + 325.0f) + 326.0f) + 327.0f) + 328.0f) + 329.0f) + 330.0f) + 331.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;332.0f) + 333.0f) + 334.0f) + 335.0f) + 336.0f) + 337.0f) + 338.0f) + 339.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;340.0f) + 341.0f) + 342.0f) + 343.0f) + 344.0f) + 345.0f) + 346.0f) + 347.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;348.0f) + 349.0f) + 350.0f) + 351.0f) + 352.0f) + 353.0f) + 354.0f) + 355.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;356.0f) + 357.0f) + 358.0f) + 359.0f) + 360.0f) + 361.0f) + 362.0f) + 363.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;364.0f) + 365.0f) + 366.0f) + 367.0f) + 368.0f) + 369.0f) + 370.0f) + 371.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;372.0f) + 373.0f) + 374.0f) + 375.0f) + 376.0f) + 377.0f) + 378.0f) + 379.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;380.0f) + 381.0f) + 382.0f) + 383.0f) + 384.0f) + 385.0f) + 386.0f) + 387.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;388.0f) + 389.0f) + 390.0f) + 391.0f) + 392.0f) + 393.0f) + 394.0f) + 395.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;396.0f) + 397.0f) + 398.0f) + 399.0f) + 400.0f) + 401.0f) + 402.0f) + 403.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;404.0f) + 405.0f) + 406.0f) + 407.0f) + 408.0f) + 409.0f) + 410.0f) + 411.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;412.0f) + 413.0f) + 414.0f) + 415.0f) + 416.0f) + 417.0f) + 418.0f) + 419.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;420.0f) + 421.0f) + 422.0f) + 423.0f) + 424.0f) + 425.0f) + 426.0f) + 427.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;428.0f) + 429.0f) + 430.0f) + 431.0f) + 432.0f) + 433.0f) + 434.0f) + 435.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;436.0f) + 437.0f) + 438.0f) + 439.0f) + 440.0f) + 441.0f) + 442.0f) + 443.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;444.0f) + 445.0f) + 446.0f) + 447.0f) + 448.0f) + 449.0f) + 450.0f) + 451.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;452.0f) + 453.0f) + 454.0f) + 455.0f) + 456.0f) + 457.0f) + 458.0f) + 459.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;460.0f) + 461.0f) + 462.0f) + 463.0f) + 464.0f) + 465.0f) + 466.0f) + 467.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;468.0f) + 469.0f) + 470.0f) + 471.0f) + 472.0f) + 473.0f) + 474.0f) + 475.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;476.0f) + 477.0f) + 478.0f) + 479.0f) + 480.0f) + 481.0f) + 482.0f) + 483.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;484.0f) + 485.0f) + 486.0f) + 487.0f) + 488.0f) + 489.0f) + 490.0f) + 491.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;492.0f) + 493.0f) + 494.0f) + 495.0f) + 496.0f) + 497.0f) + 498.0f) + 499.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;500.0f) + 501.0f) + 502.0f) + 503.0f) + 504.0f) + 505.0f) + 506.0f) + 507.0f) +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;508.0f) + 509.0f); return v_2; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;void v_3(uint3 v_4, tint_struct v_5) { uint const v_6 =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(tint_struct_1{.tint_member_2=((_v_5.tint_member_1)[0u].x &#x2F; 4u)}.tint_member_2 -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1u); device float_ const v_7 = (&amp;amp;(*v_5.tint_member)[min(uint(0), v_6)]); (*v_7)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;= v(); }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;kernel void
dawn_entry_point_687474703a2f2f6c6f63616c686f737420687474703a2f2f6c6f63616c686f7374(uint3
v_9 [[thread_position_in_grid]], device tint_array&amp;lt;float, 1&amp;gt;* v_10
[[buffer(0)]], const constant tint_array&amp;lt;uint4, 1&amp;gt;* v_11 [[buffer(30)]]) {
tint_struct const v_12 = tint_struct{.tint_member=v_10, .tint_member_1=v_11};
v_3(v_9, v_12); }&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;While initializing [ComputePipeline &quot;someComputation&quot;]
&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;My take on this is that since WebGPU is running on top of Metal (my case, i&#x27;m on
a mac), WGSL gets compiled to the Metal Shading Language (MSL), and the MSL
compiler has a bracket issue.&lt;&#x2F;p&gt;
&lt;p&gt;The bracket issue seems to be happening because the compiler is inserting
excessive parentheses in the second expression. It seems smart enough to
recognize that the first expression can be calculated in compile time, and dumps
the result of it instantly in &lt;code&gt;v_1&lt;&#x2F;code&gt;. However the second expression is crippled
by parenthesis way beyond its limit to process them (maybe to guarantee some
execution order when transpiling? why wasn&#x27;t it smart enough to go full compile
time here as well?).&lt;&#x2F;p&gt;
&lt;p&gt;Safari simply failed to compile in this case.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5-still-expressions&quot;&gt;5 - Still expressions&lt;&#x2F;h3&gt;
&lt;p&gt;Digging into this a bit further. How many maxed expressions that do not depend
on each other can we place in a function?&lt;&#x2F;p&gt;
&lt;p&gt;My approach to test this while avoiding the nasty bracket error from the
previous test is to accumulate the result in a temporary variable. Then see how
many of these accumulations we can get away with.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; tmp&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 4.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 511.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 4.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 511.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 4.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 511.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;No message, the tab becomes unresponsive.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; Just having a big expression, even if not used, makes the timeout of 5 minutes be reached.&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 3019&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“Instance dropped error in getCompilationInfo”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 3019 (tab blinks and WebGPU breaks with “A valid external Instance reference no longer exists”) &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;A small remark about Chrome is that for higher limits (&amp;gt;4000), the whole macOS
screen blinks dark and browser starts reporting that WebGPU is not supported.&lt;&#x2F;p&gt;
&lt;p&gt;For Safari if you are interested here is the minimal shader that breaks it.&lt;&#x2F;p&gt;
&lt;details&gt;
  &lt;summary&gt;Minimal shader that breaks Safari&lt;&#x2F;summary&gt;
  &lt;code class=&quot;error-content&quot;&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@group(0) @binding(0) var&amp;lt;storage, read_write&amp;gt; output: array&amp;lt;f32&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fn someFunction() -&amp;gt; f32 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var tmp: f32 = 0.0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var result0: f32 = 0.0  + 1.0  + 2.0  + 3.0  + 4.0  + 5.0  + 6.0  + 7.0  + 8.0  + 9.0  + 10.0  + 11.0  + 12.0  + 13.0  + 14.0  + 15.0  + 16.0  + 17.0  + 18.0  + 19.0  + 20.0  + 21.0  + 22.0  + 23.0  + 24.0  + 25.0  + 26.0  + 27.0  + 28.0  + 29.0  + 30.0  + 31.0  + 32.0  + 33.0  + 34.0  + 35.0  + 36.0  + 37.0  + 38.0  + 39.0  + 40.0  + 41.0  + 42.0  + 43.0  + 44.0  + 45.0  + 46.0  + 47.0  + 48.0  + 49.0  + 50.0  + 51.0  + 52.0  + 53.0  + 54.0  + 55.0  + 56.0  + 57.0  + 58.0  + 59.0  + 60.0  + 61.0  + 62.0  + 63.0  + 64.0  + 65.0  + 66.0  + 67.0  + 68.0  + 69.0  + 70.0  + 71.0  + 72.0  + 73.0  + 74.0  + 75.0  + 76.0  + 77.0  + 78.0  + 79.0  + 80.0  + 81.0  + 82.0  + 83.0  + 84.0  + 85.0  + 86.0  + 87.0  + 88.0  + 89.0  + 90.0  + 91.0  + 92.0  + 93.0  + 94.0  + 95.0  + 96.0  + 97.0  + 98.0  + 99.0  + 100.0  + 101.0  + 102.0  + 103.0  + 104.0  + 105.0  + 106.0  + 107.0  + 108.0  + 109.0  + 110.0  + 111.0  + 112.0  + 113.0  + 114.0  + 115.0  + 116.0  + 117.0  + 118.0  + 119.0  + 120.0  + 121.0  + 122.0  + 123.0  + 124.0  + 125.0  + 126.0  + 127.0  + 128.0  + 129.0  + 130.0  + 131.0  + 132.0  + 133.0  + 134.0  + 135.0  + 136.0  + 137.0  + 138.0  + 139.0  + 140.0  + 141.0  + 142.0  + 143.0  + 144.0  + 145.0  + 146.0  + 147.0  + 148.0  + 149.0  + 150.0  + 151.0  + 152.0  + 153.0  + 154.0  + 155.0  + 156.0  + 157.0  + 158.0  + 159.0  + 160.0  + 161.0  + 162.0  + 163.0  + 164.0  + 165.0  + 166.0  + 167.0  + 168.0  + 169.0  + 170.0  + 171.0  + 172.0  + 173.0  + 174.0  + 175.0  + 176.0  + 177.0  + 178.0  + 179.0  + 180.0  + 181.0  + 182.0  + 183.0  + 184.0  + 185.0  + 186.0  + 187.0  + 188.0  + 189.0  + 190.0  + 191.0  + 192.0  + 193.0  + 194.0  + 195.0  + 196.0  + 197.0  + 198.0  + 199.0  + 200.0  + 201.0  + 202.0  + 203.0  + 204.0  + 205.0  + 206.0  + 207.0  + 208.0  + 209.0  + 210.0  + 211.0  + 212.0  + 213.0  + 214.0  + 215.0  + 216.0  + 217.0  + 218.0  + 219.0  + 220.0  + 221.0  + 222.0  + 223.0  + 224.0  + 225.0  + 226.0  + 227.0  + 228.0  + 229.0  + 230.0  + 231.0  + 232.0  + 233.0  + 234.0  + 235.0  + 236.0  + 237.0  + 238.0  + 239.0  + 240.0  + 241.0  + 242.0  + 243.0  + 244.0  + 245.0  + 246.0  + 247.0  + 248.0  + 249.0  + 250.0  + 251.0  + 252.0  + 253.0  + 254.0  + 255.0  + 256.0  + 257.0  + 258.0  + 259.0  + 260.0  + 261.0  + 262.0  + 263.0  + 264.0  + 265.0  + 266.0  + 267.0  + 268.0  + 269.0  + 270.0  + 271.0  + 272.0  + 273.0  + 274.0  + 275.0  + 276.0  + 277.0  + 278.0  + 279.0  + 280.0  + 281.0  + 282.0  + 283.0  + 284.0  + 285.0  + 286.0  + 287.0  + 288.0  + 289.0  + 290.0  + 291.0  + 292.0  + 293.0  + 294.0  + 295.0  + 296.0  + 297.0  + 298.0  + 299.0  + 300.0  + 301.0  + 302.0  + 303.0  + 304.0  + 305.0  + 306.0  + 307.0  + 308.0  + 309.0  + 310.0  + 311.0  + 312.0  + 313.0  + 314.0  + 315.0  + 316.0  + 317.0  + 318.0  + 319.0  + 320.0  + 321.0  + 322.0  + 323.0  + 324.0  + 325.0  + 326.0  + 327.0  + 328.0  + 329.0  + 330.0  + 331.0  + 332.0  + 333.0  + 334.0  + 335.0  + 336.0  + 337.0  + 338.0  + 339.0  + 340.0  + 341.0  + 342.0  + 343.0  + 344.0  + 345.0  + 346.0  + 347.0  + 348.0  + 349.0  + 350.0  + 351.0  + 352.0  + 353.0  + 354.0  + 355.0  + 356.0  + 357.0  + 358.0  + 359.0  + 360.0  + 361.0  + 362.0  + 363.0  + 364.0  + 365.0  + 366.0  + 367.0  + 368.0  + 369.0  + 370.0  + 371.0  + 372.0  + 373.0  + 374.0  + 375.0  + 376.0  + 377.0  + 378.0  + 379.0  + 380.0  + 381.0  + 382.0  + 383.0  + 384.0  + 385.0  + 386.0  + 387.0  + 388.0  + 389.0  + 390.0  + 391.0  + 392.0  + 393.0  + 394.0  + 395.0  + 396.0  + 397.0  + 398.0  + 399.0  + 400.0  + 401.0  + 402.0  + 403.0  + 404.0  + 405.0  + 406.0  + 407.0  + 408.0  + 409.0  + 410.0  + 411.0  + 412.0  + 413.0  + 414.0  + 415.0  + 416.0  + 417.0  + 418.0  + 419.0  + 420.0  + 421.0  + 422.0  + 423.0  + 424.0  + 425.0  + 426.0  + 427.0  + 428.0  + 429.0  + 430.0  + 431.0  + 432.0  + 433.0  + 434.0  + 435.0  + 436.0  + 437.0  + 438.0  + 439.0  + 440.0  + 441.0  + 442.0  + 443.0  + 444.0  + 445.0  + 446.0  + 447.0  + 448.0  + 449.0  + 450.0  + 451.0  + 452.0  + 453.0  + 454.0  + 455.0  + 456.0  + 457.0  + 458.0  + 459.0  + 460.0  + 461.0  + 462.0  + 463.0  + 464.0  + 465.0  + 466.0  + 467.0  + 468.0  + 469.0  + 470.0  + 471.0  + 472.0  + 473.0  + 474.0  + 475.0  + 476.0  + 477.0  + 478.0  + 479.0  + 480.0  + 481.0  + 482.0  + 483.0  + 484.0  + 485.0  + 486.0  + 487.0  + 488.0  + 489.0  + 490.0  + 491.0  + 492.0  + 493.0  + 494.0  + 495.0  + 496.0  + 497.0  + 498.0  + 499.0  + 500.0  + 501.0  + 502.0  + 503.0  + 504.0  + 505.0  + 506.0  + 507.0  + 508.0  + 509.0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return tmp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@compute @workgroup_size(1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fn computeMain(@builtin(global_invocation_id) id: vec3&amp;lt;u32&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  output[0] = someFunction();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;code&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;Maybe Safari is trying to perform some expensive optimizations in this massive
expression that Chrome skips. These two browsers seem to have different
implementation strategies in the WGSL compilers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;6-amount-of-functions-possible&quot;&gt;6 - Amount of functions possible&lt;&#x2F;h3&gt;
&lt;p&gt;Now what about the amount of functions we can have in a module (private space)?&lt;&#x2F;p&gt;
&lt;p&gt;Lets see how far this harness can go:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  fs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;fn funfunfun&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;(a: f32) -&amp;gt; f32 { return a + &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.0; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It will produce a bunch of functions with a single argument &lt;code&gt;a&lt;&#x2F;code&gt; just for the
purpose of them doing something on something.&lt;&#x2F;p&gt;
&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“RangeError: out of memory” in JS because I am using `JSON.stringify()` to send the shader to my DSL engine WebGPU player along with metadata.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; over 5 million.&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 55719&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“Instance dropped error in getCompilationInfo” and sometimes WebGPU starts reporting device does not have WebGPU support.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 55719 (Breaks at the first reference of the maximum expression) &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Safari is impressive here. Crunching through millions of these without a
problem. Chrome tab crashes at much lower values than this (probably due to the
&lt;code&gt;stringify&lt;&#x2F;code&gt; function, but just assuming here).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;7-function-call-depth&quot;&gt;7 - Function call depth&lt;&#x2F;h3&gt;
&lt;p&gt;How many functions can we call inside each other in WGSL?&lt;&#x2F;p&gt;
&lt;p&gt;Lets see how many of this we can create and call the last one before something
breaks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; How deep can the stack go?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; levelN&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; levelN_minus1&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; levelN_minus1&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; levelN_minus2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span&gt; levelN_minus$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1337.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: Error above 1159&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;No message. A PipelineError exception is thrown right before the tab crashes.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 1159 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: Error above 4100&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“A valid external Instance reference no longer exists.” And an `OperationError` with msg: “Instance dropped in popErrorScope”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 4100 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Chrome supports a much higher function call depth than Safari. But a 1159 call
depth seems a very reasonable limit to play with.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;8-function-statements-limit&quot;&gt;8 - Function statements limit&lt;&#x2F;h3&gt;
&lt;p&gt;How many statements can a function have? Lets find out:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; massiveFunction&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; Not expressions, but individual statements&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;JavaScript error in my `JSON.stringify()` function, well above 16 million statements.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; No limit &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: Error above 49767&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“OperationError: Instance dropped error in getCompilationInfo”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 49767 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Safari again goes to crazy limits. I would love to be able to see the generated
MSL shader.&lt;&#x2F;p&gt;
&lt;p&gt;Chrome feels somewhat flaky here, this limit is the lowest I got it to break,
but sometimes it got higher values without a stress up until ~52000.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-table-of-it-all&quot;&gt;A table of it all&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Limit Type&lt;&#x2F;th&gt;&lt;th&gt;Safari Result&lt;&#x2F;th&gt;&lt;th&gt;Chrome Result&lt;&#x2F;th&gt;&lt;th&gt;Spec&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;JS String length&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~4 GiB&lt;&#x2F;td&gt;&lt;td&gt;~1 GiB&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Expression depth&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;512&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;512&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Parentheses nesting&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;127&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;127&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Chained expressions&lt;&#x2F;strong&gt; (bracket depth)&lt;&#x2F;td&gt;&lt;td&gt;Hangs tab&lt;&#x2F;td&gt;&lt;td&gt;~256 (Metal bracket limit)&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Multiple maxed expressions&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Hangs tab&lt;&#x2F;td&gt;&lt;td&gt;~3019 (compile fail)&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Max function declarations&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;&amp;gt; 5 million&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~55719 (compile fail)&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Function call depth&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;1159&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;4100&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Max statements in a function&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;&amp;gt; 16 million&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;49767&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;These tests show that real-world WGSL limits often stem from underlying
compilers and drivers rather than the spec itself.&lt;&#x2F;p&gt;
&lt;p&gt;For developers pushing creative or extreme workloads, these practical ceilings
are just as important as the spec minimums, and in some cases can be far more
restrictive.&lt;&#x2F;p&gt;
&lt;p&gt;In particular, hitting the Metal bracket nesting limit (256), is a clear example
on how the underlying graphics API can impose additional constraints beyond what
WGSL itself enforces.&lt;&#x2F;p&gt;
&lt;p&gt;There are also dramatic differences between Safari and Chrome in the way they
handle large expressions. Which suggests very different optimization strategies
in their compilers.&lt;&#x2F;p&gt;
&lt;p&gt;I think it would be cool to be able to see the underlying shader being compiled.
Maybe the spec could mention groundfloor values for these scenarios, but I am
not sure about the implications of it in the grand scheme of WebGPU things.&lt;&#x2F;p&gt;
&lt;p&gt;Ultimately, the spec gives you the floor, but browsers and drivers define the
ceiling. If you&#x27;re pushing WebGPU to its limits, test on real hardware because
real bottlenecks exist beyond the spec.&lt;&#x2F;p&gt;
&lt;p&gt;Stay tuned, next post I will try to make a small demo of these limits.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>WebGPU shader limits</title>
        <published>2025-09-16T00:00:00+00:00</published>
        <updated>2025-09-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/webgpu-shader-limits/"/>
        <id>https://hugodaniel.com/posts/webgpu-shader-limits/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/webgpu-shader-limits/">&lt;style&gt;
  .result-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;margin:12px 0 16px}
  .result-card{border:1px solid var(--border,rgba(0,0,0,.12));border-radius:12px;padding:12px;background:var(--elev,#fff);
    box-shadow:0 1px 3px rgba(0,0,0,.06)}
  .result-card h4{margin:0 0 6px;font-size:1rem;line-height:1.2}
  .kv{display:flex;gap:8px;flex-wrap:wrap;margin:6px 0}
  .badge{display:inline-block;padding:2px 8px;border-radius:9999px;font-size:.82em;font-weight:600;border:1px solid transparent}
  .ok{background:#e6ffed;color:#0f6b2b;border-color:#b6efc5}
  .err{background:#ffe8e8;color:#9b1c1c;border-color:#f3b0b0}
  .na{background:#f1f5f9;color:#334155;border-color:#cbd5e1}
  .limit{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; margin-top: 1rem;}
  .msg{margin-top:6px;font-style:italic;opacity:.9}
&lt;&#x2F;style&gt;
&lt;p&gt;Limits can be a fun thing to look out for when exploring unconventional ways to
use something in a safe, consensual, way.&lt;&#x2F;p&gt;
&lt;p&gt;A while ago I got in my mind that it would be cool to try to dump data directly
in the shader code string. Engrave the data in the code instead of going with
the common approach of providing it through some external mechanism (textures,
buffers, etc). This manipulation of the code string would happen before it being
compiled and by making use of some sort of pre-processor that could update the
shader code in unusual ways. A lispic meta shader code as a service or something
like that.&lt;&#x2F;p&gt;
&lt;p&gt;That road led me to over-engineer a demoscene engine that still grabs my
attention to this day and hopefully will bring its first fruits in
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;2025.inercia.pt&#x2F;en&#x2F;&quot;&gt;Inercia 2025&lt;&#x2F;a&gt; or 2026. But this will be the
subject for a future post.&lt;&#x2F;p&gt;
&lt;p&gt;In the meanwhile there were some learnings that I found that might be cool
enough to be worth of your attention. All code is WGSL shader code.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;by-the-book-limits&quot;&gt;By the book limits&lt;&#x2F;h3&gt;
&lt;p&gt;Querying the WebGPU device is the regular way to know about some of the limits
of the adapter&#x2F;device we have running. It gives developers the device reported
maximum values for certain things like the maximum storage buffer binding size
and maximum invocations per workgroup etc.&lt;&#x2F;p&gt;
&lt;p&gt;These queried limits are the ones that change between devices, and naturally do
not cover all the limits that we are bound to. For instance a lot of the limits
come from WebGPU and WGSL specs and these are often the minimum limits that the
implementations must support.&lt;&#x2F;p&gt;
&lt;p&gt;For this blog post I am interested in the WGSL shader code limits, which the
spec lays out in a nice table:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;WGSL_limits.png&quot; alt=&quot;&amp;quot;WGSL Limits from the spec&amp;quot;&quot; &#x2F;&gt;
&lt;small&gt;(image from the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;WGSL&#x2F;#limits&quot;&gt;WGSL 9 Sep 2025 spec limits section&lt;&#x2F;a&gt;)
&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To explore these, lets start with a simple shader code, the triangle.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;you-can-t-spell-triskel-without-tri&quot;&gt;You can’t spell Triskel without TRI.&lt;&#x2F;h3&gt;
&lt;p&gt;The simple WGSL triangle can be done with the vertex code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;vertex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vertexMain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  @&lt;&#x2F;span&gt;&lt;span&gt;builtin&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vertex_index&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; VertexIndex&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;builtin&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;position&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; vec4f&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; A static array with the coordinates of this triangle&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pos&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;vec2f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vec2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vec2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vec2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vec4f&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pos&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;VertexIndex&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1.0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How many vertices can we fit into that &lt;code&gt;var pos = array&amp;lt;vec2f, 3&amp;gt;&lt;&#x2F;code&gt; array?&lt;&#x2F;p&gt;
&lt;p&gt;The last row of the WGSL limits table tells us that the minimum supported value
that WebGPU has to guarantee for the &lt;em&gt;&quot;Maximum number of elements in value
constructor expression of array type &quot;&lt;&#x2F;em&gt; is 2047.&lt;&#x2F;p&gt;
&lt;p&gt;In order to test this, lets introduce a bit of JS in this shader module string
to extend the last vertex to guarantee that the array is filled n times:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; preprocessWGSL&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; number&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;@vertex&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;fn vertexMain(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  @builtin(vertex_index) VertexIndex : u32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;) -&amp;gt; @builtin(position) vec4f {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    var pos = array&amp;lt;vec2f, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    ${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;vec2(0.0, 0.5), vec2(-0.5, -0.5), &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Extend this vertex:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;vec2(0.5, -0.5), &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;repeat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  return vec4f(pos[VertexIndex], 0.0, 1.0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;procedural-generation-of-limits&quot;&gt;Procedural generation of limits&lt;&#x2F;h3&gt;
&lt;p&gt;Now I want to replicate this kind of logic of declaring a super big thing in the
WGSL code to check the other limits of that spec table.&lt;&#x2F;p&gt;
&lt;p&gt;The idea is to do this in three steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create a shader module with the offending code, and check for compilation
errors. If it passes:&lt;&#x2F;li&gt;
&lt;li&gt;Create a WebGPU pipeline with the offending code, and check if it doesn&#x27;t
throw. If it passes:&lt;&#x2F;li&gt;
&lt;li&gt;Go to 1. but increase the number up until a value is found that breaks
either 1. or 2.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;create-shader-and-pipeline&quot;&gt;Create shader and pipeline&lt;&#x2F;h4&gt;
&lt;p&gt;I am testing both the &lt;code&gt;createShaderModule()&lt;&#x2F;code&gt; and the pipeline creation, since
some things are only checked when the pipeline is created (binding layout,
workgroup effective storage limits, etc).&lt;&#x2F;p&gt;
&lt;p&gt;I am expecting that the &lt;code&gt;createShaderModule()&lt;&#x2F;code&gt; compilation info is more about
syntax and tipification. While pipeline creation more about storage or byte
limit errors.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h4&gt;
&lt;p&gt;All values provided are for my machine, which is an intel macos with an Intel
and AMD gpu. The reported adapter vendor is &lt;em&gt;&quot;Intel&quot;&lt;&#x2F;em&gt; and architecture is
&lt;em&gt;&quot;gen-9&quot;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;All code is run in a webworker in an offline canvas.&lt;&#x2F;p&gt;
&lt;p&gt;Lets go bottom up through the WGSL table limits and do this!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-number-of-elements-in-value-constructor-expression-of-array&quot;&gt;Maximum number of elements in value constructor expression of array&lt;&#x2F;h3&gt;
&lt;p&gt;The table says it WGSL should support at least 2047 elements.&lt;&#x2F;p&gt;
&lt;p&gt;Using the code above and recipe I get the following in my intel apple macbook:&lt;&#x2F;p&gt;
&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error at 2048&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: —&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“constant array cannot have more than 2047 elements”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 2047 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge ok&quot;&gt;Compile: OK until 2047&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: error at 2048&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;Stalls for about 10 seconds and then pipeline throws with a long
    message with C++ code. Browser is irresponsive with much bigger limits.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 2047 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;Yes&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;Yes&lt;&#x2F;span&gt;
  - Message: _&quot;constant array cannot have more than 2047 elements&quot;_
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: brown;&quot;&gt;No&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: brown;&quot;&gt;Throws a bunch of C++ code.&lt;&#x2F;span&gt;
  - Message: Stalls for about 10 seconds and then pipeline throws with a long
    message with C++ code. Browser is irresponsive with much bigger limits.
  - Limit before error: 2047 (same as the minimum in the WGSL table).
--&gt;
&lt;h3 id=&quot;maximum-combined-byte-size-of-all-variables-instantiated-in-the-workgroup-address&quot;&gt;Maximum combined byte-size of all variables instantiated in the workgroup address...&lt;&#x2F;h3&gt;
&lt;p&gt;The WGSL table says we should be able to have at least 16384 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;This value is the same as the one communicated by the hardware device limits at
&lt;code&gt;maxComputeWorkgroupStorageSize&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To test this up, I created a simple compute shader with another really big
array. I am not sure if it is necessary to include a barrier to prevent some
sort of memory layout optimization or dead code elimination here, so I added it
nevertheless.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; output, this is just to enforce the usage of the workgroup data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;binding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; read_write&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; the ${n} here is coming from the JS preprocessor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;workgroup&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; sharedData: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;compute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;workgroup_size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; computeMain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;builtin&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;local_invocation_id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; localId: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;vec3&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; localId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; fill it up! (the ${n} here is coming from the JS preprocessor)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;idx&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sharedData&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;idx&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;idx&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  workgroupBarrier&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; compiler might be smart to just ignore the variable if not used, so&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; lets use it here just to avoid dead code elimination:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F; the ${n} here is coming from the JS preprocessor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0u&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; sharedData&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: error above 16384&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“The combined byte size of all variables in the workgroup address
    space exceeds 16384 bytes”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 16384 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: error at 2048&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“The total use of workgroup storage (16400 bytes) is larger than
    the maximum allowed (16384 bytes). This adapter supports a higher
    maxComputeWorkgroupStorageSize of 32768, which can be specified in
    requiredLimits when calling requestDevice(). Limits differ by hardware, so
    always check the adapter limits prior to requesting a higher limit.”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 16384 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: brown;&quot;&gt;No&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;Yes&lt;&#x2F;span&gt;
  - Message: _&quot;The combined byte size of all variables in the workgroup address
    space exceeds 16384 bytes&quot;_
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: brown;&quot;&gt;No&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;Yes&lt;&#x2F;span&gt;
  - Message: _&quot;The total use of workgroup storage (16400 bytes) is larger than
    the maximum allowed (16384 bytes). This adapter supports a higher
    maxComputeWorkgroupStorageSize of 32768, which can be specified in
    requiredLimits when calling requestDevice(). Limits differ by hardware, so
    always check the adapter limits prior to requesting a higher limit.&quot;_
  - Limit before error: 16384 (same as the minimum in the WGSL table).
--&gt;
&lt;p&gt;We could try to increase the hardware limits by requesting a bit more from the
device, but I am just looking at what happens at the limit for creative
purposes.&lt;&#x2F;p&gt;
&lt;p&gt;Lets move on to the next row of the WGSL spec limits table.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-combined-byte-size-of-all-variables-instantiated-in-the-function-address&quot;&gt;Maximum combined byte-size of all variables instantiated in the function address...&lt;&#x2F;h3&gt;
&lt;p&gt;The spec says that we should have 8192 bytes. The thing here is that function
space variables are unique to each invocation, they are not shared, so no need
for the barrier as above.&lt;&#x2F;p&gt;
&lt;p&gt;Also this limit is not communicated by the hardware device when querying for
limits, so lets see.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;binding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; read_write&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; someFunctionWithLocalMemory&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; Same thing as before, ${n} is the JS preprocessor input:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span&gt; localMem: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; ${n} is the JS preprocessor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0u&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    localMem&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; ${n} is the JS preprocessor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0u&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; localMem&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;compute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;workgroup_size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; computeMain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; someFunctionWithLocalMemory&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: error above 8192&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“The combined byte size of all variables in this function exceeds
    8192 bytes”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 8192 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge ok&quot;&gt;Pipeline: no error&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;No message, the limit is never reached, at 262144bytes the
    compilation fails with the message _“array count (65536) must be less than
    65536”_, which is not a limit I could find in the spec.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 262145 - Array count got to 65536 and I was using f32 (4 bytes)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: red;&quot;&gt;No&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;Yes&lt;&#x2F;span&gt;
  - Message: _&quot;The combined byte size of all variables in this function exceeds
    8192 bytes&quot;_
  - Limit before error: 8192 (same as the minimum in the WGSL table).
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: red;&quot;&gt;No&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;No&lt;&#x2F;span&gt;
  - Message: No message, the limit is never reached, at 262144bytes the
    compilation fails with the message _&quot;array count (65536) must be less than
    65536&quot;_, which is not a limit I could find in the spec.
  - Limit before error: 262144, because array count got to 65536 and I was using
    elements with 4 bytes (f32).

--&gt;
&lt;p&gt;This ceiling of 65536 elements seems to be a practical limit of the toolchain
(Chrome, or maybe even driver). This is ok since the groundfloor established by
the spec is way below it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-combined-byte-size-of-all-variables-instantiated-in-the-private-address-space&quot;&gt;Maximum combined byte-size of all variables instantiated in the &lt;em&gt;private&lt;&#x2F;em&gt; address space&lt;&#x2F;h3&gt;
&lt;p&gt;The private address space is cool for module-scope variables that are unique for
each invocation but persist accross function calls within it.&lt;&#x2F;p&gt;
&lt;p&gt;The limit in the spec table is again 8192 bytes, to test this I will declare a
big array as &lt;code&gt;var&amp;lt;private&amp;gt;&lt;&#x2F;code&gt; (which is the default when declaring variables in
the module scope) and see how big it can be. Again this is not a limit exposed
through the WebGPU API hardware device limits.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;binding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; read_write&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; Same as before, a big array:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;private&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; privateData: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;compute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;workgroup_size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; computeMain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; Initialize it, the ${n} is set by this test shader preprocessor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0u&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    privateData&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; Use all the data to avoid it being optimized away, like above&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F; the ${n} is set by this test shader preprocessor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0u&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; privateData&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge err&quot;&gt;Pipeline: error above 8192&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“The combined byte size of all variables in the private address
    space exceeds 8192 bytes”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 8192 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge na&quot;&gt;Compile: -&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge ok&quot;&gt;Pipeline: no error&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;Same as previous test. This specific limit is never reached, however at 262144bytes the
    compilation fails with the message _“array count (65536) must be less than
    65536”_.&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 262145 - Array count got to 65536 and I was using f32 (4 bytes)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: red;&quot;&gt;No&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;Yes&lt;&#x2F;span&gt;
  - Message: _&quot;The combined byte size of all variables in the private address
    space exceeds 8192 bytes&quot;_
  - Limit before error: 8192 (same as the minimum in the WGSL table).
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: red;&quot;&gt;No&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;No&lt;&#x2F;span&gt;
  - Message: Same as in the previous test. This specific limit is never reached,
    however at 262144bytes the compilation fails with the message _&quot;array count
    (65536) must be less than 65536&quot;_.
  - Limit before error: 262144, because array count got to 65536 and I was using
    elements with 4 bytes (f32).
--&gt;
&lt;p&gt;And lets move on to the next one.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-number-of-case-selector-values-in-a-switch-statement&quot;&gt;Maximum number of case selector values in a switch statement&lt;&#x2F;h3&gt;
&lt;p&gt;This is an interesting one, it certainly did not cross my mind to explore the
amount of case selector values. WGSL switch&#x27;s must always carry a default case,
which always counts as 1 regardless if it is empty or not.&lt;&#x2F;p&gt;
&lt;p&gt;Im going with just single values per case, since my purpose is to hit my desired
limit and not so much to test the switch case implementation nuances:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;binding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; read_write&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;compute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;workgroup_size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;builtin&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;global_invocation_id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;vec3&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span&gt; testValue &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; %&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;numCases&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  switch&lt;&#x2F;span&gt;&lt;span&gt; testValue &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cases&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;\&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    default&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      result&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 999.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 1023&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“switch statement cannot have more than 1023 case selector
    values”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 1023 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 16383&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“switch statement has 16384 case selectors, max is 16383”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 16383 &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: _&quot;switch statement cannot have more than 1023 case selector
    values&quot;_
  - Limit before error: 1023 (same as the minimum in the WGSL table).
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: _&quot;switch statement has 16384 case selectors, max is 16383&quot;_
  - Limit before error: 16383.
--&gt;
&lt;h3 id=&quot;maximum-number-of-parameters-for-a-function&quot;&gt;Maximum number of parameters for a function&lt;&#x2F;h3&gt;
&lt;p&gt;This is a cool way for a preprocessor to pass down extra data in the shader
string code. The spec says that we have at least 255 arguments for each
function, so lets create a preprocessor that uses structs and see how WebGPU
behaves.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;binding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; read_write&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; MyStruct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  flag&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; someFunction&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;    Array&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; =&amp;gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;MyStruct&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;Array&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; =&amp;gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;value&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;\&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;      &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;compute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;workgroup_size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MyStruct&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; someFunction&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;Array&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; =&amp;gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 255&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“function cannot have more than 255 parameters”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 255 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 255&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“function declares 256 parameters, maximum is 255”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 255 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: _&quot;function cannot have more than 255 parameters&quot;_
  - Limit before error: 255 (same as the minimum in the WGSL table).
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: _&quot;function declares 256 parameters, maximum is 255&quot;_
  - Limit before error: 255 (same as the minimum in the WGSL table).
--&gt;
&lt;p&gt;This limit seems to be per function, and structs are treated as just another
param. It could maybe be used creatively as a way to dump extra data into a
shader code string when other limits are reached. Though I imagine the
compilation time would become a factor at some point.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-nesting-depth-of-brace-enclosed-statements-in-a-function&quot;&gt;Maximum nesting depth of brace-enclosed statements in a function&lt;&#x2F;h3&gt;
&lt;p&gt;To test this limit I want to dump a lot of nested if&#x27;s in the shader string
code. Specs says we can have at least 127 nested block statements.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the full code for it, including the &lt;code&gt;#computePipeline&lt;&#x2F;code&gt; from the WebGPU
engine I am working at, where I moved the WebGPU spec to a fully declarative
preprocessor (more about this next post).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; limitsNestedIfShaderModule&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; number&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; opening&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; closing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; indent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Create a bunch of nested ifs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; depth&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    opening&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;indent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;if (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.0 &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.0) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    indent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    closing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;indent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;output[0] = &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.0;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; closing&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      closing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;repeat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;depth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; closing&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      closing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; indent&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; closing&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; shaderCode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;#computePipeline someComputation {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  layout=auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  compute={&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    entryPoint=computeMain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    module=code &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;#shaderModule code {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  code=&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;@group(0) @binding(0) var&amp;lt;storage, read_write&amp;gt; output: array&amp;lt;f32&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;@compute @workgroup_size(1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;fn computeMain() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;opening&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;closing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  `&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; shaderCode&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(As a way to treat shader code as data, I did bring the WebGPU spec to a
declarative space as a high-level abstraction preprocessor for the demoscene
engine I&#x27;m working at.)&lt;&#x2F;p&gt;
&lt;p&gt;The results are in:&lt;&#x2F;p&gt;
&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 127&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“maximum parser recursive depth reached”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 127 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 63&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“statement nesting depth &#x2F; chaining length exceeds limit of 127”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 64 (below the WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: _&quot;maximum parser recursive depth reached&quot;_
  - Limit before error: 127 (same as spec, which is 127).
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: _&quot;statement nesting depth &#x2F; chaining length exceeds limit of 127&quot;_
  - Limit before error: 63 (**LESS** as the minimum in the WGSL table, which is
    127).
--&gt;
&lt;p&gt;Now this is strange. Safari is doing the right thing, &lt;em&gt;&quot;brace-enclosed
statements&quot;&lt;&#x2F;em&gt; include the function block and beyond. However Chrome appears to be
doing something entirely different, maybe counting closing braces as well? Not
really sure what is happening here.&lt;&#x2F;p&gt;
&lt;p&gt;This got me wondering about the behaviour of nested composite types, which is
coming right next.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-nesting-depth-of-a-composite-type&quot;&gt;Maximum nesting depth of a composite type&lt;&#x2F;h3&gt;
&lt;p&gt;Spec says the limit is 15. I am going to generate a big nested array like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My idea here is to push the nesting limit of a composite type in a single
expression.&lt;&#x2F;p&gt;
&lt;p&gt;These are the results:&lt;&#x2F;p&gt;
&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 15&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“composite type may not be nested more than 15 levels”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 15 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 29&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;Chrome lets it go big until it hits another limits such as: “array
    byte size (0x100000000) must not exceed 0xffffffff bytes”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 29 for f32 (above WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;!--
- Safari Tech Preview (227)
  - Compilation error: &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: _&quot;composite type may not be nested more than 15 levels&quot;_
  - Limit before error: 15 (same as spec, which is 15).
- Google Chrome (140.0.7339.133)
  - Compilation error: &lt;span style=&quot;color: brown;&quot;&gt;YES&lt;&#x2F;span&gt; | Pipeline error:
    &lt;span style=&quot;color: green;&quot;&gt;YES&lt;&#x2F;span&gt;
  - Message: Chrome lets it go big until it hits another limits such as: _&quot;array
    byte size (0x100000000) must not exceed 0xffffffff bytes&quot;_
  - Limit before error: 29 for f32.
--&gt;
&lt;p&gt;This suggests that Chrome maybeeee is not be explicitly checking nesting depth
at all (just maybe) and just letting us hit whatever other limit might be in
their parsing stack. This is again ok because the groundfloor established by the
spec is also fullfilled.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;maximum-number-of-members-in-a-structure-type&quot;&gt;Maximum number of members in a structure type&lt;&#x2F;h3&gt;
&lt;p&gt;The final limit that I think might be potentially interesting to test as a
shader developer is the maximum number of members in a struct.&lt;&#x2F;p&gt;
&lt;p&gt;The spec says we can have capacity for at least 1023 members in a struct.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;wgsl&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;group&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;binding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; var&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; read_write&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; output&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; Preprocessor creates n members for this struct:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; BigStruct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;members&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F; Create and use them here to avoid them from being optimized:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;compute&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt;workgroup_size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; computeMain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; BigStruct&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;initValues&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;sumLoop&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;result-grid&quot;&gt;
  &lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Safari Technology Preview 227&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 1023&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“struct cannot have more than 1023 members”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 1023 (WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;div class=&quot;result-card&quot;&gt;
    &lt;h4&gt;Chrome 140.0.7339.133&lt;&#x2F;h4&gt;
    &lt;div class=&quot;kv&quot;&gt;
      &lt;span class=&quot;badge err&quot;&gt;Compile: error above 16383&lt;&#x2F;span&gt;
      &lt;span class=&quot;badge na&quot;&gt;Pipeline: -&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;msg&quot;&gt;“&#x27;struct BigStruct&#x27; has 16384 members, maximum is 16383”&lt;&#x2F;div&gt;
    &lt;div class=&quot;limit&quot;&gt;&lt;strong&gt;Limit hit:&lt;&#x2F;strong&gt; 16383 (above WGSL floor)&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Chrome is generous here and goes well beyond the minimum provided.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-table-of-it-all&quot;&gt;A table of it all&lt;&#x2F;h3&gt;
&lt;p&gt;These results fit well within my expectations, Safari as always is more strict
and spec oriented, while Chrome goes above the limits in some fronts while
sometimes having a less polished failure mode.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Limit (WGSL spec)&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Spec min&lt;&#x2F;th&gt;&lt;th&gt;Safari TP 227&lt;&#x2F;th&gt;&lt;th&gt;Chrome 140&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Array constructor elements&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2047&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;2047 (2047)&lt;&#x2F;td&gt;&lt;td&gt;Compiles; Pipelines breaks at 2048; UI may stall&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Workgroup storage bytes (&lt;code&gt;var&amp;lt;workgroup&amp;gt;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;16384&lt;&#x2F;td&gt;&lt;td&gt;Errs in pipeline&lt;&#x2F;td&gt;&lt;td&gt;Pipeline Error; suggests &lt;code&gt;requiredLimits&lt;&#x2F;code&gt; 32768&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Function local bytes (function stack)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8192&lt;&#x2F;td&gt;&lt;td&gt;Errs in pipeline&lt;&#x2F;td&gt;&lt;td&gt;No limit reached; compiles up to “array count” 65536&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Private addr space bytes (&lt;code&gt;var&amp;lt;private&amp;gt;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;8192&lt;&#x2F;td&gt;&lt;td&gt;Errs in pipeline&lt;&#x2F;td&gt;&lt;td&gt;No limit reached; same as above&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Case selectors in a &lt;code&gt;switch&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1023&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;1023&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;16383&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Function parameters&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;255&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;255&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;255&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Struct members&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1023&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;1023&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;16383&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Nested brace-enclosed statements&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;127&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;127&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Errs &amp;gt;63&lt;&#x2F;strong&gt; (below spec min &lt;strong&gt;127&lt;&#x2F;strong&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Nested composite types&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;15&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;15&lt;&#x2F;td&gt;&lt;td&gt;Errs &amp;gt;29 fails with a different limit&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;I think that there are at least two takeaways I can safely make from poking at
WGSL spec limits:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The spec minimums are good guidelines&lt;&#x2F;strong&gt;. Safari Technology Preview enforces
them very strictly, which makes it great to validate what the &lt;em&gt;portable
floor&lt;&#x2F;em&gt; actually is.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Browsers may go beyond the minimums&lt;&#x2F;strong&gt;. Chrome lets you stretch several rows
(struct members, switch cases, local&#x2F;private bytes) way past the spec floor,
but you’ll sometimes trip different internal limits first (like array-element
counts) or see pipeline-time failures rather than neat compile errors.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If you’re considering “engraving” data into the shader source for creative or
preprocessing reasons my advice so far would be:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Treat spec minimums as the baseline&lt;&#x2F;strong&gt;, and friendlier ceilins as mere
nice-to-haves.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Probe limits first&lt;&#x2F;strong&gt;, one approach could be to probe ceilings on startup and
cache these results.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Standard data paths are the way to go&lt;&#x2F;strong&gt;, storage buffers and textures are
our friends, this approach of code-embedded payloads is a fun technique, but
not a substitute for stable I&#x2F;O.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All of these were run with a preprocessor demo player that I am working on for
fun, if you are curious I&#x27;ll share a follow-up shortly and ideally a WebGPU demo
at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;2025.inercia.pt&#x2F;en&#x2F;&quot;&gt;Inercia 2025&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is a
&lt;a href=&quot;&#x2F;posts&#x2F;webgpu-shader-unknown-limits&#x2F;&quot;&gt;follow-up post to this one here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>boreDOM another boring JS framework</title>
        <published>2025-01-12T00:00:00+00:00</published>
        <updated>2025-01-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/boredom-another-js-framework/"/>
        <id>https://hugodaniel.com/posts/boredom-another-js-framework/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/boredom-another-js-framework/">&lt;p&gt;Being bored can drive you crazy. In my case it took me on a trip to create
another JS framework. As if the world even needed more of that. In this post I
present the thought process behind &quot;boreDOM&quot; a novel JS framework for everyone.&lt;&#x2F;p&gt;
&lt;p&gt;The main motivator was to have a simple framework to manipulate the DOM which
could naturally fit the scenario where the HTML is defined in .html files, CSS
in .css files and JS in .js files.&lt;&#x2F;p&gt;
&lt;p&gt;This way most HTML for a given app would already exist and would not need to be
created through JS. In most common JS frameworks the HTML is typically created
through JS. I wanted to avoid that and reuse as much existing html nodes as
possible with a small JS footprint.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-idea&quot;&gt;The idea&lt;&#x2F;h3&gt;
&lt;p&gt;The main idea is to use &lt;code&gt;&amp;lt;template&amp;gt;&lt;&#x2F;code&gt; elements whose content could then be
stamped all over the place as needed. In order to do that each &lt;code&gt;boreDOM&lt;&#x2F;code&gt;
template element registers a custom element tag.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; data-component&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;stamp-this&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;yay&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stamp-this&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stamp-this&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stamp-this&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stamp-this&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stamp-this&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stamp-this&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The framework reads the &lt;code&gt;data-component&lt;&#x2F;code&gt; attribute and registers the associated
tag. Then it is up to the regular browser mechanics when we use it in places.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-logic&quot;&gt;The logic&lt;&#x2F;h3&gt;
&lt;p&gt;To provide some logic to the components, a matching .js file can be set with a
&lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; tag:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; data-component&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;magic-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Press for magic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;magic-button.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This file is a regular .js file that is going to be imported dynamically and
associated with the corresponding component. It should export a function that is
run when the component is connected to the DOM, and return a function that is
called when the component is to be rendered&#x2F;updated.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; In magic-button.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; webComponent&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.&#x2F;boreDOM.min.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MagicButton&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; webComponent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; on connect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; on render&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are some helper attributes that these functions receive. Here is &lt;code&gt;on&lt;&#x2F;code&gt; for
handling custom events:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;magic-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;magic-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; data-component&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;magic-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; onclick&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;dispatch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;magic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Press for magic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;magic-button.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; In magic-button.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; webComponent&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.&#x2F;boreDOM.min.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MagicButton&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; webComponent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; on&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;magic&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;background&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;random&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;toString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; on render&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;a-simple-counter&quot;&gt;A simple counter&lt;&#x2F;h3&gt;
&lt;p&gt;Slots are also supported and are available through the &lt;code&gt;.slots&lt;&#x2F;code&gt; attribute in
each registered tag Element, as well as passed as an option in the init and
render functions. Here is a simple counter:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Simple counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;simple-counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;simple-counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; data-component&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;simple-counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Some value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; onclick&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;dispatch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;increase&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Increase&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; onclick&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;dispatch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;decrease&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Decrease&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.&#x2F;simple-counter.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; in simple-counter.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; webComponent&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.&#x2F;boreDOM.min.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; SimpleCounter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; webComponent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; on&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;increase&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; mutableState&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mutableState&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;decrease&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; mutableState&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mutableState&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; self&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Set the value of the slot:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slots&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;state&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally it all starts with the app state, which is passed to the starting
boreDOM function, in main.js:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; in main.js&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; inflictBoreDOM&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.&#x2F;boreDOM.min.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;inflictBoreDOM&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This ensures that the render function is fine-grained and called whenever the
corresponding state that it needs is updated.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;some-particularities&quot;&gt;Some particularities&lt;&#x2F;h3&gt;
&lt;p&gt;There are a few other things it brings as well:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;References to elements (through &lt;code&gt;data-ref=&quot;&quot;&lt;&#x2F;code&gt; attributes).&lt;&#x2F;li&gt;
&lt;li&gt;Shadow-dom support (through the &lt;code&gt;shadowrootmode=&quot;open&#x2F;closed&quot;&lt;&#x2F;code&gt; attribute in
the &lt;code&gt;&amp;lt;template&amp;gt;&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;aria-*&lt;&#x2F;code&gt; attributes that you set in the &lt;code&gt;&amp;lt;template&amp;gt;&lt;&#x2F;code&gt; are passed down to the
tag.&lt;&#x2F;li&gt;
&lt;li&gt;Same for &lt;code&gt;role=*&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Dynamically create components in JS through &lt;code&gt;makeComponent&lt;&#x2F;code&gt; in the init&#x2F;render
function argument object.&lt;&#x2F;li&gt;
&lt;li&gt;Batches renders in a &lt;code&gt;requestAnimationFrame()&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Components are JS by default, types are provided and can be used with JSDoc to
type-check.&lt;&#x2F;li&gt;
&lt;li&gt;Small but comprehensive
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;boreDOM&#x2F;blob&#x2F;main&#x2F;tests&#x2F;dom.test.ts&quot;&gt;test suit&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Nothing here is ground-breaking, but make up for a small and versatile framework
that fit my needs for the future. I&#x27;ll be adapting and bringing in further
projects with this little toy.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;bored1.png&quot; alt=&quot;&amp;quot;A bored square&amp;quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A small caveat about component JS code being imported dynamically is that it
makes it hard to have a bundler or anything non-standard at that point. If you
need to make use of such tech and&#x2F;or import packages that are not immediately
available through a valid standard URL then it is best to make use of it before
laying the UI components.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;If you find any of this useful at all drop me note, I&#x27;ll be super happy that
this is found in any way useful by anyone other than me. There is a somewhat
ranty webpage for this framework that you can check out too:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;pages&#x2F;boreDOM&quot;&gt;boreDOM&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Or just run:
&lt;code&gt;pnpm create boredom@latest my-project&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Shader Language ECS, Part 1 - Idea</title>
        <published>2024-09-01T00:00:00+00:00</published>
        <updated>2024-09-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/ecs-wgsl/"/>
        <id>https://hugodaniel.com/posts/ecs-wgsl/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/ecs-wgsl/">&lt;p&gt;I&#x27;ll explore a simple way to bring the Entity Component System (ECS) pattern
into the world of WGSL shaders.&lt;&#x2F;p&gt;
&lt;p&gt;This is still in idea stage, an idea that i&#x27;ll explore in this post without
providing a real implementation, just the API for it.&lt;&#x2F;p&gt;
&lt;p&gt;While I have no particular goal in mind with this I enjoy exploring new
technology (WGSL) and discover what it can do for me. I&#x27;m writing this post to
share my findings.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ecs_socials.png&quot; alt=&quot;&amp;quot;A cat with two wheels on his eyes&amp;quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;can-we-leverage-the-gpu-for-more-than-visuals&quot;&gt;Can we leverage the GPU for more than visuals?&lt;&#x2F;h3&gt;
&lt;p&gt;This is not a new concept, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;danilw&quot;&gt;Danil&lt;&#x2F;a&gt; has made a
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arugl.medium.com&#x2F;games-in-the-gpu-shaders-a912414b1894&quot;&gt;cool exposition and demo&lt;&#x2F;a&gt;
of his approach, with a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shadertoy.com&#x2F;view&#x2F;wdS3D3&quot;&gt;shadertoy demo&lt;&#x2F;a&gt;
of it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ecs-entity-component-system&quot;&gt;ECS - Entity Component System&lt;&#x2F;h3&gt;
&lt;p&gt;ECS is a simple idea that brings detachment to the app state and embraces sparse
relationships. It&#x27;s not my purpose to give an intro to ECS in this article, if
you want to learn more about ECS check this
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Entity_component_system&quot;&gt;wikipedia page&lt;&#x2F;a&gt; and the
many yt videos about it.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;The TLDR of an Entity Component System, is that Entities, Components and Systems
are concepts that you as a programmer define, but in a way that by default they
are unrelated to each other.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine three arrays: one for entities, one for components, and one for systems.
Each element exists in its own space, connected only through explicit
references.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ecs_carro.png&quot; alt=&quot;A car and a cat driving it, a list of wheels and a list of positions, cat and car share some of these attributes&quot; title=&quot;A cat and car go somewhere, they share the same position, but not the same wheels&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So, ideally Entities and Components and Systems don&#x27;t know much about each
other:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Entities:&lt;&#x2F;em&gt; Things in your game&#x2F;app (e.g., a player, an enemy, a tree).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Components:&lt;&#x2F;em&gt; The data or attributes of those things (e.g., position, health,
color).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Systems:&lt;&#x2F;em&gt; The logic that acts on and changes that data (e.g., movement,
collision detection, AI).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The key is that systems work with any entity that has the right components,
hopefully making it easy to add or change behavior without messing up the whole
codebase.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bringing-ecs-to-the-gpu&quot;&gt;Bringing ECS to the GPU&lt;&#x2F;h3&gt;
&lt;p&gt;In WGSL you send a shader code string to the graphics api (WebGPU) which then
compiles it into the GPU processor code that gets run with whatever settings you
have set.&lt;&#x2F;p&gt;
&lt;p&gt;My idea is to make use of the shader code string creation and with JavaScript
(JS) create hardcoded const arrays for the lookups and queries needed for each
system.&lt;&#x2F;p&gt;
&lt;p&gt;i.e. If a system works on all entities that have a &lt;code&gt;Moveable&lt;&#x2F;code&gt; component and a
&lt;code&gt;Position&lt;&#x2F;code&gt; component, then when creating the WGSL string two const arrays of
numbers with the exact same size would be written in the string. These arrays
are to be iterated sequentially in the system, and hold the index of the
Position component and the index of the Moveable component in their respected
storage buffers.&lt;&#x2F;p&gt;
&lt;p&gt;These static arrays represent the entities and components relationships and are
set through JS, tailored each System needs. It&#x27;s like using JS as a
precompilation language with its Maps and Sets to perform the queries and dump
the results in a WGSL string.&lt;&#x2F;p&gt;
&lt;p&gt;The key here is that the relationships between entities and components are
defined upfront, in JS, before sending anything to the GPU. This way, the GPU
only has to execute the pre-determined logic defined by CPU code (JS).&lt;&#x2F;p&gt;
&lt;p&gt;Ideally in the future someone could minimax this out to produce a highly
optimized string ready to run on the GPU.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;attractiveness-is-sweet&quot;&gt;Attractiveness is sweet&lt;&#x2F;h3&gt;
&lt;p&gt;WebGPU and WGSL are attractive because they have compute shaders, which are
simpler versions of shaders for whatever you want.&lt;&#x2F;p&gt;
&lt;p&gt;Not only that, but unlike WebGL&#x2F;GLSL, the new WGSL also brings support for
pointers and compile time arrays (&quot;const&quot; arrays).&lt;&#x2F;p&gt;
&lt;p&gt;In WebGPU we can create our own pipeline, and dispatch a given entrypoint
function of the shader with very specific parallel execution scenarios. I find
this a cool thing and wanted to explore it a bit and see how it can be used to
implement an ECS.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compute-shaders-dispatches&quot;&gt;Compute shaders dispatches&lt;&#x2F;h3&gt;
&lt;p&gt;The rough outline of the simplified ECS for WGSL is this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Components are defined as WGSL structs&#x2F;types.&lt;&#x2F;li&gt;
&lt;li&gt;JS is used to create the relationships between entities and components&lt;&#x2F;li&gt;
&lt;li&gt;Systems are defined as WGSL functions that read&#x2F;update components&lt;&#x2F;li&gt;
&lt;li&gt;Systems function arguments define the components query they use&lt;&#x2F;li&gt;
&lt;li&gt;JS parses this system function and performs the queries.&lt;&#x2F;li&gt;
&lt;li&gt;The final WGSL string dispatches each system function once for each query
result&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;the-code-outline&quot;&gt;The code outline&lt;&#x2F;h3&gt;
&lt;p&gt;My objective is that in the end I can do something like this in JS and have a
final WGSL shader string created:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; world&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; createWorld&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Create an entity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; PLAYER&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createEntity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Create a position component type (A simple 2d vector)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; and its initialization function (in WGSL)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; POSITION&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createComponent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;alias Position = vec2&amp;lt;f32&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;fn init_position(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  position: ptr&amp;lt;storage, Position, read_write&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  i: u32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  total_number_of_components: u32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    let space = 2.0 &#x2F; total_number_of_components;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    let left = -0.5;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    (*position).x = left + float(i) * space;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Create a distance movement type (here using a struct just because yes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; No initialization this time. (in WGSL)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MOVEABLE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createComponent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;struct Moveable {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  delta: vec2f,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Relate these two components to the player&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;addComponentToEntity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;PLAYER&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; POSITION&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;addComponentToEntity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;PLAYER&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MOVEABLE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; A movement system, defined using WGSL function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; This function will be called for all entities that&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; have the Moveable and the Position components:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; (in WGSL)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createSystem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;fn movement_system(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    moveable: ptr&amp;lt;storage, Moveable, read_write&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    position: ptr&amp;lt;storage, Position, read_write&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    (*position).at += (*moveable).delta;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; An input update system, same thing with a WGSL function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; that is called once for all entities that have the Moveable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; component.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createSystem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;fn keyboard_system(moveable: ptr&amp;lt;storage, Moveable, read_write&amp;gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    const amount: f32 = 0.01;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &#x2F;&#x2F; Up:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    if (keyDown(38)) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.y = amount;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.x = 0.0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    } else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &#x2F;&#x2F; Down:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    if (keyDown(40)) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.y = -amount;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.x = 0.0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    } else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &#x2F;&#x2F; Left:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    if (keyDown(37)) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.x = -amount;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.y = 0.0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    } else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &#x2F;&#x2F; Right:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    if (keyDown(39)) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.x = amount;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        (*moveable).delta.y = 0.0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; The shader string to send to the GPU&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; shader&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; world&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;generateWGSL&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a rough idea for the API for now. It will evolve based on new findings
and learnings I&#x27;ll get along the way.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-output-outline&quot;&gt;The output outline&lt;&#x2F;h3&gt;
&lt;p&gt;I created this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;compute.toys&#x2F;view&#x2F;1377&quot;&gt;shader&lt;&#x2F;a&gt; in compute.toys, as an
example of code that I intend to implement as a WGSL string in this new API.&lt;&#x2F;p&gt;
&lt;p&gt;You can also play this video to see the shader in action.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;wgsl_ecs_circles.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;wgsl_ecs_circles.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Outlining it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A WGSL string that does one dispatch per system function. With components
hardcoded into it in static const arrays.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Initialization is done inline as much as possible.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Static component relationships. A dynamic update of a relationship would imply
a string rewrite and WGSL shader recompilation.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The usecase for this API are shaders with entity component relationships that
are mostly static. The bottleneck here comes from recompilation which is what I
want to avoid in the first place.&lt;&#x2F;p&gt;
&lt;p&gt;Since WGSL recompilation is required whenever there&#x27;s a dynamic update, this API
is targetting shaders with static entity component relationships. Not to say
that it can&#x27;t handle dynamic updates but it will be at the cost of performance.
For now my focus is on static relationships.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;open-questions-and-next-steps&quot;&gt;Open questions and next steps&lt;&#x2F;h3&gt;
&lt;p&gt;I haven&#x27;t measured the performance of the API so I can&#x27;t list what are the pros
and cons yet. However, I delined a few questions that will be my guide to
substantiate a proper list of the cons and pros of this novel approach.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is there some usefulness in having the state management done in the same
language as the graphics?
&lt;ul&gt;
&lt;li&gt;Could this lead to better low hanging fruit optimization opportunities and
reduced communication overhead between CPU and GPU?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Will it be massively slow to re-compile a big shader with everything in it? (i
would love to benchmark WGSL compilation times at some point)
&lt;ul&gt;
&lt;li&gt;I think that this could be a major bottleneck, especially for dynamic scenes
or frequent updates.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Can we easily produce mind-bending stuff when the state is tightly coupled
with the graphics?
&lt;ul&gt;
&lt;li&gt;There might be some potential here for unique visual effects and gameplay
mechanics that make use of the GPU capabilities.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Debugging will be super hard (if not impossible), but I plan and hope to make
some developments here in the near future.&lt;&#x2F;li&gt;
&lt;li&gt;Performance? I doubt there will be any performance gains at all immediately
and I&#x27;m not sure I can produce good enough data points to conclude anything on
this.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;This post is just the first step in exploring this idea. I have no polished
library or API to showcase yet – just the shader and API presented here at this
stage.&lt;&#x2F;p&gt;
&lt;p&gt;My next step is to implement the API based on the example code and showcase its
pros and cons.&lt;&#x2F;p&gt;
&lt;p&gt;In the next post, I&#x27;ll attempt to bring this to life with a more concrete
example, hopefully I&#x27;ll have a bit more clarification on the potential benefits
and drawbacks of it.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m both excited and apprehensive. Will this experiment crash and burn, or is
there a hidden gem here somewhere?&lt;&#x2F;p&gt;
&lt;p&gt;Join me on this journey into the uncharted territory (for me at least) of ECS in
WGSL!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Special thanks to Joana and António for the helpful edits and thoughtful
suggestions&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2025 Note&lt;&#x2F;strong&gt; I spent hooked on the idea of doing preprocessors for WGSL since
this post. Here is a kind of a follow-up explaining the limits of WGSL strings:
&lt;a href=&quot;&#x2F;posts&#x2F;webgpu-shader-limits&#x2F;&quot;&gt;WebGPU Shader Limits&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Color picker</title>
        <published>2024-07-21T00:00:00+00:00</published>
        <updated>2024-07-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/color-picker/"/>
        <id>https://hugodaniel.com/posts/color-picker/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/color-picker/">&lt;p&gt;I made my first color picker almost ten years ago, in 2015. Since then, my passion about color pickers grew a little more than expected and this month I finished my 6th one. I only have the code for the last 3, the others are now likely in the Elysium of color pickers (or some old laptop hard drive in my basement).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-s-so-special-about-color-pickers&quot;&gt;What&#x27;s so special about color pickers?&lt;&#x2F;h3&gt;
&lt;p&gt;They have graphic and visual usage patterns that are uncommon in UI widgets. Most widgets are drop-down boxes, sliders, etc., and then there are color pickers. Besides, choosing colors has always been a challenge for me as a developer with little aesthetic sense. During college, I made some websites to earn some extra money, and when it came time to choose colors, it was a headache.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;allcolorpickers.webp&quot; alt=&quot;color pickers ive done&quot; title=&quot;Some color pickers i&amp;#39;ve done&quot; &#x2F;&gt;
&lt;sub&gt;Image: Some color pickers I&#x27;ve done&lt;&#x2F;sub&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Also, color pickers have been my testbed of some ideas and concepts, not necessarily directly related to the act of color picking per se. Color pickers also act kind of like my todo apps or hello world.
Shreds of a multidisciplinary learning process loitering erratically for purpose. Calculated efforts with messed up cost-benefit evaluations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-m-looking-for-a-rebound-project-can-you-be-it&quot;&gt;I&#x27;m looking for a rebound project, can you be it?&lt;&#x2F;h3&gt;
&lt;p&gt;There are plenty of reasons not to implement a color picker. Not only they barely have any commercial value nowadays, but they are also not very suitable standalone apps without having a lot of extra differentiating features.&lt;&#x2F;p&gt;
&lt;p&gt;There is really not much to be done. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;react-spectrum.adobe.com&#x2F;react-spectrum&#x2F;ColorPicker.html&quot;&gt;Every&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ant.design&#x2F;components&#x2F;color-picker&quot;&gt;mature&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.microsoft.com&#x2F;en-us&#x2F;fluentui#&#x2F;controls&#x2F;web&#x2F;colorpicker&quot;&gt;component&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;react-bootstrap.netlify.app&#x2F;docs&#x2F;forms&#x2F;form-control&#x2F;#color&quot;&gt;library&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mui.com&#x2F;material-ui&#x2F;customization&#x2F;color&#x2F;#picking-colors&quot;&gt;has&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mantine.dev&#x2F;core&#x2F;color-picker&#x2F;&quot;&gt;one&lt;&#x2F;a&gt;. The device you are reading this has one (try it out, click here: &lt;input type=&quot;color&quot; value=&quot;#E67E22&quot; &#x2F;&gt;). All design tools ship with very good color pickers packed with features.
More color oriented niche designers and illustrators have at their disposal a wide range of color plugins available. These plugins can cover all advanced scenarios: accessibility concerns, contrast, harmony, related palettes, color spaces that no one can name, etc...&lt;&#x2F;p&gt;
&lt;p&gt;To top this, color pickers are not a particularly fun thing to do, and kinda annoying to do well. They are even frustrating if you want to make them generic enough so that they work and fit with whatever framework your potential users might be using.&lt;&#x2F;p&gt;
&lt;p&gt;In the end, colors pickers exist as forgetful side-kick widgets in someone else&#x27;s grand plan. They are not meant to be the hero of the story and you have to scrap for reasons to invest time in them.&lt;&#x2F;p&gt;
&lt;p&gt;But that never stopped no one.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-color-picker-hello-world&quot;&gt;The color picker &quot;hello world&quot;&lt;&#x2F;h3&gt;
&lt;p&gt;The original, traditional, color picker is the one with the wheel and the triangle invented by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.pixlart.com&#x2F;pixlart&#x2F;2018&#x2F;12&#x2F;11&#x2F;color-wheel-keeps-on-turnin&quot;&gt;John Derry&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;fractal_design_painter_software.png&quot; alt=&quot;The original color wheel.&quot; title=&quot;Fractal Design Painter 3.0. Image from https:&#x2F;&#x2F;winworldpc.com&#x2F;product&#x2F;fractal-design-painter&#x2F;30&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Despite being the first one, imo it has a lot of cool things that sometimes are not found in more modern color pickers.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a commonly modern color picker, to contrast with the one above. A slight variation of this can be found in a lot of modern design tools:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;colorpicker1.png&quot; alt=&quot;A modern color picker, with the square.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I find that original ideas are often the most elegant, and like Leonardo Da Vinci said:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;simplicity-is-the-ultimate-sophistication&quot;&gt;&quot;Simplicity is the ultimate sophistication&quot;&lt;&#x2F;h3&gt;
&lt;p&gt;There are many good reasons to choose a more modern color picker (one with the square and the sliders) however for the purpose of suiting my narrative I am going to squeeze a few reasons why the original triangle color wheel is better.&lt;&#x2F;p&gt;
&lt;p&gt;Let me start by dissing the modern common color picker that uses a square&#x2F;rectangle.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;modern-square-has-a-disproportion-of-shades&quot;&gt;Modern square has a disproportion of shades&lt;&#x2F;h4&gt;
&lt;p&gt;Take a look at a variation of the common modern color picker, and focus on the square&#x2F;rectangle it presents.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;colorpicker2.png&quot; alt=&quot;Another common color picker&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In that image, we have a huge area of 100% black pixels. A whole row of 100% black at the bottom.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;colorpicker2a.png&quot; alt=&quot;Amount of repeated black colors&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now contrast this with the single 100% white pixel you have to chose the white color. Just one at the top left corner.&lt;&#x2F;p&gt;
&lt;p&gt;If you don&#x27;t have a strong education in choosing colors (like me) then there might be a good chance that a darker color will be chosen with this kind of color square layout.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;modern-square-has-a-weird-slope-for-tones&quot;&gt;Modern square has a weird slope for tones&lt;&#x2F;h4&gt;
&lt;p&gt;Lets pick two colors and draw a line between them.&lt;&#x2F;p&gt;
&lt;p&gt;First: pick the intermediate gray (50% gray), this sits in the middle of the leftmost edge (1).&lt;&#x2F;p&gt;
&lt;p&gt;Second: pick the highest saturation color in to the top right corner (2).&lt;&#x2F;p&gt;
&lt;p&gt;If we draw a line between them, from 50% gray to 100% color, we have this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;colorpicker2b.png&quot; alt=&quot;Line between intermediate gray and most saturated color&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This split has a big bias to it. The amount of darker colors below the line is way bigger than the whiter tones above the line.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-triangle-equilateral-movements&quot;&gt;The triangle equilateral movements&lt;&#x2F;h3&gt;
&lt;p&gt;Lets move to the triangle now, and explore by pointing out why the original triangle is still the superior color picker for shades, tones and tints.&lt;&#x2F;p&gt;
&lt;p&gt;Here is my approach on it:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;mycolorpicker1.png&quot; alt=&quot;Color picker I did&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;tones-are-set-along-a-horizontal-line&quot;&gt;Tones are set along a horizontal line&lt;&#x2F;h4&gt;
&lt;p&gt;An horizontal line:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;mycolorpicker1a.png&quot; alt=&quot;Color picker I did&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In the original triangle representation if we pick the intermediate 50% gray (1) and like before draw a line to the strongest color (2).&lt;&#x2F;p&gt;
&lt;p&gt;We get an horizontal line, fewer repeated colors and a more equalitarian distribution of clearer tints (above the line) vs darker shades (below the line).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;shades-and-tints-are-spaced-through-the-edges&quot;&gt;Shades and tints are spaced through the edges&lt;&#x2F;h4&gt;
&lt;p&gt;In the triangle the 100% chroma is always located in a very easy to pin position:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;mycolorpicker2.png&quot; alt=&quot;Color picker I did&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If we start from this position, it becomes easy to add more white, or more black to the color. This can be achievied by moving the thumb along the edges of the triangle like in the video below:&lt;&#x2F;p&gt;
&lt;video autoplay=&quot;autoplay&quot; muted loop preload width=&quot;55%&quot; playsinline&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;shadestints.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;shadestints.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h3 id=&quot;the-wheel-and-the-slider&quot;&gt;The wheel and the slider&lt;&#x2F;h3&gt;
&lt;p&gt;Hues are typically set in degrees from 0 to 360, where 180 marks the split between the commonly known &quot;warm&quot; and &quot;cold&quot; colors (I think warm and cold are just another fuzzy human thing without much connection to temperature).&lt;&#x2F;p&gt;
&lt;p&gt;In the original color picker wheel, this would mean warmer colors at the top of the wheel, and colder at the bottom.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;originalcolorpicker.png&quot; alt=&quot;original color picker with the wheel split horizontally&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;my-attempt&quot;&gt;My attempt&lt;&#x2F;h3&gt;
&lt;p&gt;The most recent color picker I did was along the lines of the original color wheel triangle.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest difference might be that I added the possibility to interact with the wheel by dragging it to chose a Hue. The original color picker used two thumbs, one for the wheel and one for the triangle.&lt;&#x2F;p&gt;
&lt;p&gt;It also took me about 20x more time to &quot;design&quot; this than it would a beginner designer.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;mycolorpickerfull.png&quot; alt=&quot;My current approach&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can play with it &lt;a href=&quot;&#x2F;pages&#x2F;color-picker-pro&#x2F;color-picker.html&quot;&gt;here&lt;&#x2F;a&gt; or as a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.figma.com&#x2F;community&#x2F;plugin&#x2F;1382041838227127919&#x2F;color-picker-pro&quot;&gt;Figma plugin&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h2&gt;
&lt;p&gt;I keep going back to color pickers. Driven by the somewhat unique place that they hold in the world of UI widgets. Driven by my lack of aesthetics and passion for stuff that is slightly out of my comfort zone.&lt;&#x2F;p&gt;
&lt;p&gt;The intention of this post is that it can be inspiring to you. I hope to have shared enough of the passion I find in color pickers, so that you can find extra shine the next time you find yourself staring at a color picker.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The art of the (sub-)pixel</title>
        <published>2023-08-15T00:00:00+00:00</published>
        <updated>2023-08-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/sub-problems-sub-pixels/"/>
        <id>https://hugodaniel.com/posts/sub-problems-sub-pixels/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/sub-problems-sub-pixels/">&lt;p&gt;This post is the first in a series of posts about some challenges to think about when developing a motion design app.&lt;&#x2F;p&gt;
&lt;p&gt;It is meant to think a bit about pixel representations in drawing&#x2F;animation apps, or just bring some insights if you are not into that.&lt;&#x2F;p&gt;
&lt;p&gt;Although not related, this post also coincides with the release of LottieLab, the motion app I have been working on, please support us &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.producthunt.com&#x2F;posts&#x2F;lottielab&quot;&gt;on ProductHunt&lt;&#x2F;a&gt;. Check it out.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-art-of-the-pixel&quot;&gt;The art of the pixel&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;pixel_family.png&quot; alt=&quot;Four squares, that represent a family of pixels&quot; title=&quot;Support this (sub)pixel family!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Imagine doing a drawing web app and thinking about how to represent pixels in it.&lt;&#x2F;p&gt;
&lt;p&gt;Implementing pixels as integers can be tempting when doing a design animation tool. After all, most creators avoid partial pixels with a fractional value, often called sub-pixel values, and generally consider it a good practice to prevent sub-pixels overall.&lt;&#x2F;p&gt;
&lt;p&gt;On top of this, our screens have a fixed integer resolution. Full HD is 1920 pixels wide per 1080 pixels tall. It is not 1920.7 per 1080.3333 or any other decimal limit.&lt;&#x2F;p&gt;
&lt;p&gt;Then, in the pixel abstraction stack we tend to generally think of pixels as square entities that live on our screens and can have color.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;geometry_pixel.jpg&quot; alt=&quot;Four images, each representing the hardware RGB pixels of four kinds of displays (TV CRT, PC CRT, XO-1 LCD and LCD). None of them have square pixel geometry.&quot; title=&quot;Pixel geometry at some point&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Integers are easy to work with and reason, especially when compared with floating point values, where &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;0.30000000000000004.com&quot;&gt;&lt;code&gt;0.1 + 0.2 != 0.3&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Double-precision_floating-point_format#Precision_limitations_on_integer_values&quot;&gt;precision&lt;&#x2F;a&gt; can be a problem in some edge cases here and there.&lt;&#x2F;p&gt;
&lt;p&gt;Even in a language like JavaScript, where standard numbers are all 64-bit floats, it is not uncommon to resort to flooring and multiplying&#x2F;dividing with a fixed 10-based power to provide a fixed resolution—peace in a world of eventual chaos.&lt;&#x2F;p&gt;
&lt;p&gt;Within this, thinking of pixels as integers feels &quot;right&quot;. After all, they are squares with colors. A shape can be positioned in either one pixel or the other. Right?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;np-hard-p-is-for-pixel&quot;&gt;NP-Hard (P is for Pixel)&lt;&#x2F;h3&gt;
&lt;p&gt;My best take on this is that &quot;it depends&quot;. Pixels can be thought more or less as we want depending on how low-level or high-level in the hardware&#x2F;software abstraction we want to be.&lt;&#x2F;p&gt;
&lt;p&gt;As a web developer, the lowest I go typically starts at the graphics backend in use (HTML5 Canvas? WebGL? SVG? regular ImageData bitmap?), and then goes all the way up to the app requirements. It depends.&lt;&#x2F;p&gt;
&lt;p&gt;If we take something low-level, like WebGL, there is no actual &quot;square pixel&quot; for a developer to directly manipulate.
WebGL cares about clip-space coordinates, which are just a square with dimensions ranging from -1.0 to 1.0. A notion of pixels then can be mapped here, but from a programmer&#x27;s perspective, they are on top of floating point square dimensions.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clipspace.png&quot; alt=&quot;&quot; title=&quot;Clipspace coordinates&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Besides not caring about resolutions, clipspace doesn&#x27;t care about aspect ratio or the end device they are at.&lt;&#x2F;p&gt;
&lt;p&gt;Our main problem is how to place stuff from -1.0 to 1.0, because that is what we have available as coordinates.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clipspace_monitor.png&quot; alt=&quot;&quot; title=&quot;Clipspace coordinates in a monitor&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For WebGL the task of going from clipspace to hardware colors is an implementation problem, us users don&#x27;t have to deal with it too much.&lt;&#x2F;p&gt;
&lt;p&gt;We only have to think about how we are going to place stuff from -1.0 to 1.0.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clipspace_phone.png&quot; alt=&quot;&quot; title=&quot;Clipspace coordinates in a phone&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then it is up to the developer to define an abstraction that works on top of clipspace and can represent pixels as close as possible (or not, if we so want to).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;empty-the-clip&quot;&gt;Empty the clip&lt;&#x2F;h3&gt;
&lt;p&gt;For instance, imagine an 8x8 pixel screen. The clip-space naive representation of pixels would be something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clipspace_pixel.png&quot; alt=&quot;Clipspace coordinates square, split in 8x8 grid of smaller squares, with the top left square marked in red&quot; title=&quot;A pixel in clipspace coordinates&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It would start at the left-most x position (-1.0) and since there are 8 pixels, it would extend 0.25 to the left (up to x=-0.75).&lt;&#x2F;p&gt;
&lt;p&gt;All good, but all good the same if in this representation we want to have a pixel somewhere in between:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clipspace_pixel2.png&quot; alt=&quot;Clipspace coordinates square, split in 8x8 grid of smaller squares, but the top left square is misplaced between the first and second position&quot; title=&quot;A misplaced pixel in clipspace coordinates&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It is easily possible to define other positions, it is up to us. Sub-pixels? all good here. They just start in a different floating point position.&lt;&#x2F;p&gt;
&lt;p&gt;Then all of this, at some point, raises the question of pixel centers and offset starting positions, and pixel snapping, etc. For another post, maybe.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;but-my-motion-design-app-is-so-special-that-it-will-only-have-integer-pixels&quot;&gt;But my motion design app is so special that it will only have integer pixels&lt;&#x2F;h3&gt;
&lt;p&gt;Going with only integer pixels is fine, especially for apps with more of a pixel-art vibe or geometric approach with hard grids.&lt;&#x2F;p&gt;
&lt;p&gt;If not, be prepared to find workarounds for a few situations.&lt;&#x2F;p&gt;
&lt;p&gt;Here are a couple of situations that sub-pixels can be a super useful representation to have at hand:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;rotate-a-square-and-snap-another-into-it&quot;&gt;Rotate a square, and snap another into it&lt;&#x2F;h4&gt;
&lt;p&gt;When snapping to a rotated shape, the position of the snapped shape can be more precise when put in a sub-pixel.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;snap_square.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;snap_square.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;small&gt;Video taken from Lottielab web app&lt;&#x2F;small&gt;
&lt;p&gt;Sub-pixel precision is also a good thing to have when doing transformation stack operations, like scaling a group, etc.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;scale_group.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;scale_group.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;small&gt;Video taken from Lottielab web app&lt;&#x2F;small&gt;
&lt;p&gt;When doing smooth animations, like tweening the shape from one position to another, using sub-pixel floating values can make
super smooth animations.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;tweening.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;tweening.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;small&gt;Video taken from Lottielab web app&lt;&#x2F;small&gt;
&lt;p&gt;In the end, it all goes to the screen, and...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wear-sunscreen&quot;&gt;Wear sunscreen&lt;&#x2F;h3&gt;
&lt;p&gt;Screens can implement the notion of a pixel in many different ways, and if we look close enough, they are rarely &quot;square&quot; per se. While true that they end up mapped as square &quot;device pixels&quot;, they might also not correspond to the actual pixels your code is manipulating (because of hardware to software nuances like the device pixel ratio or so many other weird things like the Apple notch rounded edges abstraction, etc).&lt;&#x2F;p&gt;
&lt;p&gt;If we go high-level enough, the pixel representation can get weird quickly. CSS defines a pixel as a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;drafts.csswg.org&#x2F;css-values&#x2F;#absolute-lengths&quot;&gt;&quot;visual angle unit&quot;&lt;&#x2F;a&gt; and CSS pixels are described as an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;drafts.csswg.org&#x2F;css-values&#x2F;#reference-pixel&quot;&gt;angular measure.&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;drafts.csswg.org&#x2F;css-values&#x2F;images&#x2F;pixel1.png&quot; alt=&quot;CSS Pixel changes with distance&quot; title=&quot;In CSS pixels must become larger if the viewing distance increases&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h2&gt;
&lt;p&gt;I like to keep things &quot;simple&quot; and stick to floating point pixel values and then provide some usability aid to ensure that shapes get placed in integers most of the time while helping out creators work in these muddy waters.&lt;&#x2F;p&gt;
&lt;p&gt;Be wild and free those pixels!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Minimal Color Swatches</title>
        <published>2022-02-03T00:00:00+00:00</published>
        <updated>2022-02-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/minimal-color-swatches/"/>
        <id>https://hugodaniel.com/posts/minimal-color-swatches/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/minimal-color-swatches/">&lt;p&gt;Recently I gained a boost of motivation that made me want to look into colors and drawing tools again.&lt;&#x2F;p&gt;
&lt;p&gt;I hate choosing colors, and it is tough for me to find good mixes of related colors that look well together and have multiple use cases.&lt;&#x2F;p&gt;
&lt;p&gt;For this reason, I have long been cultivating an attraction towards color pickers, the idea that software can help me choose colors and give me good working sets of matching colors.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ndchristie&quot;&gt;Naomi Danielle&lt;&#x2F;a&gt; gave an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ndchristie&#x2F;status&#x2F;1382134093731794948&quot;&gt;excellent explanation&lt;&#x2F;a&gt; of making minimal and exciting color palettes a while back. At that time, I had not enough energy or motivation to pursue this idea, so it went into the bucket list until now.&lt;&#x2F;p&gt;
&lt;p&gt;This blog post explains my rudimentary interpretation of the idea behind it and provides simple examples of its inner workings. The final objective is the implementation of it all as a simple color palette generator, which is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;svelte.dev&#x2F;repl&#x2F;d92223f84088414da98cce78f3ab382a?version=3.46.3&quot;&gt;available here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;final_palette.png&quot; alt=&quot;13 color diamonds displayed in a grid. All the colors are related to the one present in the central diamond &quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-pick-me&quot;&gt;Don&#x27;t pick me.&lt;&#x2F;h2&gt;
&lt;p&gt;Pick a color. This color will be the root color for a minimal palette of 12 other colors.&lt;&#x2F;p&gt;
&lt;p&gt;For example purposes, I am going to roll with #69b9d9.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;color_picked.png&quot; alt=&quot;A square with a blue color&quot; title=&quot;#69b9d9&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To ease the creation of the 12 variations, I will use HSL (Hue, Saturation, Lightness), a common RGB alternative that allows varying the color lightness and saturation directly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hairy-gray&quot;&gt;Hairy Gray.&lt;&#x2F;h2&gt;
&lt;p&gt;Each color in the palette will have its light, which means that light will not be uniform across all colors, allowing artists to use darker tones and lighter tones consistently if they stick to the palette.&lt;&#x2F;p&gt;
&lt;p&gt;Taking the base color chosen, start by deciding which is the brightest and darkest tone possible (I am going with a max of +25 Lightness and -25 for the darker one, but roll your own).&lt;&#x2F;p&gt;
&lt;p&gt;Then create a gradient by splitting the difference into five tones each way.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;gradient_light.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;gradient_light.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Now create a relationship between these color variations by zig-zagging them and filling the two missing spots of the final palette layout.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;zig_zag_light.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;zig_zag_light.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Zig-zagging the lightness creates visual ways to establish relations between them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-more-can-be-absorbed&quot;&gt;No more can be absorbed&lt;&#x2F;h2&gt;
&lt;p&gt;As with lightness, the palette must provide an excellent range of color saturation. I replicated the lightness logic to get the color saturation range as an initial approach.&lt;&#x2F;p&gt;
&lt;p&gt;Using the same Zig Zag logic for saturation produces the following effect.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;zig_zag_saturation.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;zig_zag_saturation.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;However, after playing around with the final palette of colors, I found that this produced a high emphasis on the light colors and a lower focus on the darker shades. Coinciding the saturation highs and lows with the light did not make a balanced final result to my eyes.&lt;&#x2F;p&gt;
&lt;p&gt;After showing it to a couple of friends, I opted to rearrange the saturation in an alternating fashion, highs-lows-highs from the base color outward.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;checker_saturation.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;checker_saturation.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h2 id=&quot;hue-is-a-lovely-city&quot;&gt;Hue is a lovely city&lt;&#x2F;h2&gt;
&lt;p&gt;For Hue, the logic is denser. I have failed to formalize it in a good way in this palette generator. The idea is to shift the base color 118º in one direction and 34º in the other—these values I took from the Danielle example.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;hue_diff.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;hue_diff.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Then the relations for all the palette diamonds involve dividing by two and sometimes by four. These relations are present in the &lt;code&gt;hueValues()&lt;&#x2F;code&gt; function &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;svelte.dev&#x2F;repl&#x2F;d92223f84088414da98cce78f3ab382a?version=3.46.3&quot;&gt;in the code&lt;&#x2F;a&gt;. They are fickle and sometimes jump, but the overall result is good enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;at-the-end-of-the-night&quot;&gt;At the end of the night&lt;&#x2F;h2&gt;
&lt;p&gt;The final palette uses this lightness, saturation, and hue palettes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;swatches_mix.png&quot; alt=&quot;4 palettes: lightness palette + saturation palette + hue palette with arrows to indicate that mixing them produces the final palette &quot; title=&quot;H+S+L&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Using the system color-picker, we can make these colors act alive.&lt;&#x2F;p&gt;
&lt;video controls muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;swatches_final.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;swatches_final.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;svelte.dev&#x2F;repl&#x2F;d92223f84088414da98cce78f3ab382a?version=3.46.3&quot;&gt;Try it out&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h2&gt;
&lt;p&gt;Creating this palette generator was my first &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;svelte.dev&#x2F;&quot;&gt;Svelte&lt;&#x2F;a&gt; project.&lt;&#x2F;p&gt;
&lt;p&gt;Svelte is a lean front-end framework with an excellent initial community in Portugal.
Their help and patience were paramount as I routinely bombed their Discord channel with questions and bugs.&lt;&#x2F;p&gt;
&lt;img src=&#x2F;images&#x2F;svelte_portugal.svg width=96 alt=&quot;Svelte Portugal Discord group logo&quot;&#x2F;&gt;
&lt;p&gt;If you would like to get involved, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discord.gg&#x2F;fCT57QzmJV&quot;&gt;here is an invitation link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Infinite grid with just one square</title>
        <published>2021-03-24T00:00:00+00:00</published>
        <updated>2021-03-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/infinite-grid-with-just-one-square/"/>
        <id>https://hugodaniel.com/posts/infinite-grid-with-just-one-square/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/infinite-grid-with-just-one-square/">&lt;p&gt;Around 2017, I took up more seriously the &quot;Grid Generator&quot; project.
A Web App to explore the possibilities of an infinite grid of squares.
Driven primarily out of curiosity, I wondered if even I could create something cool with an endless grid of customizable squares?&lt;&#x2F;p&gt;
&lt;p&gt;I spent almost two years on it. Two years of trial and error iterations in code, UI, product orientation, business, and failing hard at all those things and so many others. &quot;This time will be different.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;square_grid.png&quot; alt=&quot;A square grid with some squares painted in random colors&quot; title=&quot;This grid is infinite.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;webgl-2-flex-its-wings&quot;&gt;WebGL 2 flex its wings.&lt;&#x2F;h2&gt;
&lt;p&gt;To do an infinite grid in WebGL 1, I used many buffers and sluggish texture updates at each frame (and vast texture atlases).
The shaders code was a mess. Memory usage was like a rocket while at use.
It also did not benefit from my rusty elementary math and miscalculations,
breaking at most of the device&#x27;s pixel ratios and CPU usage abuse wrapped in leaky abstractions.&lt;&#x2F;p&gt;
&lt;p&gt;The plan now is to change the part that needs to be improved: &lt;em&gt;the WebGL version.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;single-in-shape&quot;&gt;Single, in shape&lt;&#x2F;h2&gt;
&lt;p&gt;WebGL focuses on triangles. A square is nothing more than two triangles glued together.&lt;&#x2F;p&gt;
&lt;p&gt;There are a couple of primitives to describe triangles with WebGL. The &lt;em&gt;&quot;triangle fan&quot;&lt;&#x2F;em&gt; has excellent properties that I like to use. It allows triangle meshes to be represented by adding vertices on top of a root vertex. It is not only fast to process a triangle fan mesh, but it also can save a lot of space by avoiding vertices to be repeatedly declared per triangle.&lt;&#x2F;p&gt;
&lt;video autoplay=&quot;autoplay&quot; muted loop preload width=&quot;100%&quot; playsinline&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;triangle_fan.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;triangle_fan2.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;On top of it, a &lt;strong&gt;triangle fan&lt;&#x2F;strong&gt; works well together with a &lt;strong&gt;line strip&lt;&#x2F;strong&gt;.
I can create an outline for the shape using the same mesh of points, no need to provide an extra mesh of points just for it.&lt;&#x2F;p&gt;
&lt;video autoplay=&quot;autoplay&quot; muted loop preload width=&quot;100%&quot; playsinline&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;line_stripe.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;line_stripe.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;There it is, a square and its outline all alone in the world.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;take-a-square-for-instance&quot;&gt;Take a square, for instance.&lt;&#x2F;h2&gt;
&lt;p&gt;WebGL 2 brings &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebGL2RenderingContext&#x2F;drawElementsInstanced&quot;&gt;instanced drawing&lt;&#x2F;a&gt; mode for the mesh masses.&lt;&#x2F;p&gt;
&lt;p&gt;The process to use instanced elements is as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Define a bunch of unique vertices (&lt;em&gt;4 vertices for a square&lt;&#x2F;em&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Define a single element by specifying the vertex indexes that make it up (&lt;em&gt;vertex 1, vertex 2, vertex 3, and so on&lt;&#x2F;em&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Say how many occurrences of that element to render (&lt;em&gt;draw 5000000 instances of this square!!&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A single square would have &lt;em&gt;4&lt;&#x2F;em&gt; vertices total, &lt;em&gt;1&lt;&#x2F;em&gt; triangle fan element, and &lt;em&gt;1&lt;&#x2F;em&gt; instance of it (its a single square).&lt;&#x2F;p&gt;
&lt;p&gt;Using instances of a simple mesh can be faster to draw (fewer draw calls per frame).
More importantly, the seed mesh can be changed to any shape, effectively allowing for infinite grids of any tileable form (or non-tileable if its your thing).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;infinity-is-a-long-way-especially-towards-the-end&quot;&gt;Infinity is a long way, especially towards the end.&lt;&#x2F;h2&gt;
&lt;p&gt;An infinite grid needs to have at least enough squares to fill the whole screen, plus padding of one row and one column to accommodate the grid&#x27;s panning.&lt;&#x2F;p&gt;
&lt;p&gt;The exact number depends on both the square size and screen size. With a 16x16 pixels sized square, at least ~8300 instances are needed to cover a 1920x1080 pixels canvas ((1920 &#x2F; 16) * (1080 &#x2F; 16) + padding[1920 &#x2F;16 +1080&#x2F;16]).&lt;&#x2F;p&gt;
&lt;p&gt;A common approach to make it look infinite is to adjust its x and y position to be &lt;code&gt;size - pan % size&lt;&#x2F;code&gt;  when moving the grid.&lt;&#x2F;p&gt;
&lt;p&gt;I tried many variations of this &lt;em&gt;modulo and division&lt;&#x2F;em&gt; approaches in the past &quot;with varying degrees of success&quot; (read: failure ☠️).
Either precision errors started showing in some grid transformations (zooming, rotation, etc.)🔥, or subtle flickering would appear because of minor miscalculations ؇ that would then get emphasized with the conversion between the JavaScript 64bit floats and the GPU 32bit floats, or 🙈 squares would disappear.&lt;&#x2F;p&gt;
&lt;p&gt;So nothing unusual, just another day with my code 🤯.&lt;&#x2F;p&gt;
&lt;p&gt;Scrap all that. In the end, the best approach for an infinite grid that these two neurons could muster is more straightforward than those modulo and margin square adjustments.
It goes like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Set up an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Orthographic_projection&quot;&gt;orthographic viewport projection&lt;&#x2F;a&gt; transformation.&lt;&#x2F;li&gt;
&lt;li&gt;When it moves&#x2F;zooms, place the squares in it at the positions they would typically be at (i.e., no modulo or tricks or transformations, start at the top left index for the current viewport transformation and fill the screen with squares).&lt;&#x2F;li&gt;
&lt;li&gt;Only place the number of squares needed to fill the viewport.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Here is a rough sketch:&lt;&#x2F;p&gt;
&lt;video autoplay=&quot;autoplay&quot; muted loop preload width=&quot;100%&quot; playsinline&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;ortho_projection.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;ortho_projection.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;It is easy(er), and the GPU can do these calculations at lightning speed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pick-me-up-before-i-go&quot;&gt;Pick me up before I go.&lt;&#x2F;h2&gt;
&lt;p&gt;In the streets of graphics programming, selecting the grid element below the mouse pointer or at the touch position is sometimes called &quot;picking&quot;. You &quot;pick&quot; the shape by mousing over it or touching it with those beautiful fingers.&lt;&#x2F;p&gt;
&lt;p&gt;The typical &quot;simple&quot; approach to perform this involves doing the &lt;span style=&quot;white-space: nowrap;&quot;&gt;shape&amp;lt;-&amp;gt;mouse&lt;&#x2F;span&gt; intersection with JavaScript (thus in the CPU). Calculating this intersection is a specialized function for each different figure (an intersection function for squares, another for hexagons, another for triangles, etc.). Doing it for a square grid is &quot;very easy&quot; when all the squares always align with the x&#x2F;y axis and have the same size.&lt;&#x2F;p&gt;
&lt;p&gt;This time I want to explore a different, but common, technique for &quot;picking&quot;. One that works with any shape.
A global picking method compatible with anything I can throw at it.&lt;&#x2F;p&gt;
&lt;p&gt;It goes like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Draw the grid into multiple targets, the screen, and an array in GPU memory.&lt;&#x2F;li&gt;
&lt;li&gt;On the screen, paint the shapes as expected (their colors, etc.). On the array in memory, &quot;paint&quot; only the shape ids.&lt;&#x2F;li&gt;
&lt;li&gt;When the mouse moves&#x2F;interacts, get the shape id by reading the pixel at the current mouse position from the shape ids array.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;video autoplay=&quot;autoplay&quot; muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;mrt.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;mrt.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;This way, it is possible to get the shape id at each screen pixel, and when the mouse moves over a pixel or a finger touches the screen, the code looks for the shape id in the array of shape ids instead.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jargon&quot;&gt;Jargon&lt;&#x2F;h3&gt;
&lt;p&gt;This technique is sometimes named &quot;single-pass picking&quot; and makes use of WebGL MRT (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.khronos.org&#x2F;registry&#x2F;webgl&#x2F;specs&#x2F;latest&#x2F;2.0&#x2F;#3.7.11&quot;&gt;Multiple-Render-Targets&lt;&#x2F;a&gt; - the screen and the array) and PBOs (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.khronos.org&#x2F;registry&#x2F;OpenGL&#x2F;specs&#x2F;es&#x2F;3.0&#x2F;es_spec_3.0.pdf#subsection.3.7.1&quot;&gt;Pixel-Buffer-Objects&lt;&#x2F;a&gt; - arrays to use as if they were a screen).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;&#x2F;h3&gt;
&lt;p&gt;It can work with any shape, with no need for special intersection functions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;drawbacks&quot;&gt;Drawbacks&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;It is much slower than using specialized intersection functions.&lt;&#x2F;li&gt;
&lt;li&gt;It requires extra memory for the arrays, and they need additional copies to leave the GPU and reach the CPU.&lt;&#x2F;li&gt;
&lt;li&gt;It can introduce &quot;pipeline stalls&quot; (WebGL is primarily a &quot;write-only&quot; API, intended to write colors to the screen&#x2F;arrays - things can get complicated when reading these values back from WebGL).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;optimizations&quot;&gt;Optimizations&lt;&#x2F;h3&gt;
&lt;p&gt;Many optimizations can limit these drawbacks. Here is my favorite optimization of them all:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Do nothing. Avoid work at all costs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is a 100% optimization right there. It beats &quot;doing it faster&quot; every time. Some even apply this to life in general with great success.&lt;&#x2F;p&gt;
&lt;p&gt;For this particular case of shape picking, it can be fruitful to avoid doing any work at all for the most part.
Reading pixels from the screen&#x2F;array is expensive and complicated.
In WebGL, this requires at least one &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebGLRenderingContext&#x2F;flush&quot;&gt;flush&lt;&#x2F;a&gt; and one &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebGL2RenderingContext&#x2F;fenceSync&quot;&gt;sync&lt;&#x2F;a&gt; outside of the frame boundaries (besides the array copy).&lt;&#x2F;p&gt;
&lt;p&gt;These are not only hard to perform but also carry severe performance costs. They are not a good fit for every mouse move or frame.&lt;&#x2F;p&gt;
&lt;p&gt;The case of the grid is a curious one: interacting with its elements happens when the grid is stopped, if someone is interacting with a grid element then they are not moving&#x2F;zooming the grid.
A grid changes when there is a panning or zooming action. Besides those two actions, it stays the same. The shape ids are at the same position all the time (even if their contents change, the ids remain at the same place provided no translation or zooming is going on).&lt;&#x2F;p&gt;
&lt;p&gt;Interacting with grid elements only happens after the pan&#x2F;zoom action finishes, which is the perfect place to &quot;hide&quot; the flush&#x2F;sync&#x2F;copy operation. Once right after the panning&#x2F;zooming ends, WebGL renders the shape id&#x27;s to multiple targets, flushes&#x2F;syncs, and copies the array to the CPU, where it stays static forever (at least until some following pan&#x2F;zoom operation finishes). Interacting with the grid is then only about reading this array for shape ids, with no need for WebGL or position updates.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-next-for-shader-canvas&quot;&gt;What is next for &lt;code&gt;&amp;lt;shader_canvas&amp;gt;&lt;&#x2F;code&gt;?&lt;&#x2F;h2&gt;
&lt;p&gt;You can read the code for this at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;shader_canvas&#x2F;tree&#x2F;main&#x2F;examples&#x2F;6-infinite-grid&quot;&gt;Shader Canvas repository&lt;&#x2F;a&gt; (still in progress).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;projects&#x2F;shader-canvas&#x2F;&quot;&gt;Shader Canvas&lt;&#x2F;a&gt; is my low-level framework for graphics programming. It consists of HTML tags that perform each WebGL function, bringing the API into a declarative space.&lt;&#x2F;p&gt;
&lt;p&gt;I am working on its second iteration after the first release. I will evolve and use this framework for my next drawing web app called &quot;Shape The Pixel&quot;.
The road ahead for &lt;code&gt;&amp;lt;shader_canvas&amp;gt;&lt;&#x2F;code&gt; is like this in my head, things are going to change for sure:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Release &lt;code&gt;&amp;lt;shader_canvas&amp;gt;&lt;&#x2F;code&gt; proof of concept (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;high-level-webgl-low-level-tags&#x2F;&quot;&gt;occured in 2021-03-03&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;The first iteration of the proof of concept with a focus on its modules (in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;shader_canvas&#x2F;blob&#x2F;main&#x2F;CHANGELOG.md&quot;&gt;2021-03-15&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;A second iteration of the proof of concept with a focus on framebuffers and texture arrays&#x2F;atlas (&lt;em&gt;ongoing&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;A third iteration of the proof of concept with a focus on animation and transform feedbacks (to be done)&lt;&#x2F;li&gt;
&lt;li&gt;Version 2.0.0 release:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;Change it into a simple &quot;compiler.&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Provide the first support for the Metal graphics framework.&lt;&#x2F;li&gt;
&lt;li&gt;It will only happen when the &quot;Shape The Pixel&quot; web app is released, and the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;introducing-deno-tag&#x2F;&quot;&gt;deno_tag&lt;&#x2F;a&gt; and the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deno.land&#x2F;x&#x2F;glsl_variables@v1.0.2&quot;&gt;GLSL parser&lt;&#x2F;a&gt; get some planned updates - they are all connected 🤫.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Demos and examples will only show up here at this 2.0 stage&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;video autoplay=&quot;autoplay&quot; muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;sq_grid.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;sq_grid.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;Drawing an infinite grid in WebGL 2 can be done using its instance drawing functions to avoid repeating vertices and multiple-render-targets for picking.
Read the pixels only once when the grid panning&#x2F;zooming operation finishes to avoid WebGL pipeline stalls.
Using these two WebGL graphics techniques allows for infinite grids of custom shapes so that shape updates happen (mostly) only at the single seed mesh&#x2F;shape level.&lt;&#x2F;p&gt;
&lt;video autoplay=&quot;autoplay&quot; muted loop preload width=&quot;100%&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;tris.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
  &lt;source src=&quot;&#x2F;videos&#x2F;tris.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
&lt;&#x2F;video&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>High-level WebGL. Low-level tags.</title>
        <published>2021-03-03T00:00:00+00:00</published>
        <updated>2021-03-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/high-level-webgl-low-level-tags/"/>
        <id>https://hugodaniel.com/posts/high-level-webgl-low-level-tags/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/high-level-webgl-low-level-tags/">&lt;p&gt;When people think about the WebGL API, they focus on one of the famous libraries
that use it. Typically &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;threejs.org&quot;&gt;&quot;three.js&quot;&lt;&#x2F;a&gt; or
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.babylonjs.com&quot;&gt;&quot;Babylon&quot;&lt;&#x2F;a&gt;. There&#x27;s barely any motivation
to use the WebGL API directly. But the WebGL API is still just as important to
know as it provides creative ways to place colors in browser pages.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.khronos.org&#x2F;registry&#x2F;webgl&#x2F;specs&#x2F;latest&#x2F;1.0&#x2F;#1&quot;&gt;WebGL spec&lt;&#x2F;a&gt; even starts by saying:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Given the many use cases of 3D graphics, WebGL chooses the approach of providing
flexible primitives that can be applied to any use case. Libraries can provide
an API on top of WebGL that is more tailored to specific areas, thus adding a
convenience layer to WebGL that can accelerate and simplify development. However,
because of its OpenGL ES 2.0 heritage, it should be straightforward for
developers familiar with modern desktop OpenGL or OpenGL ES 2.0 development to
transition to WebGL development.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;WebGL was made closer to OpenGL ES 2.0 (a C&#x2F;C++-oriented framework) than closer
to its sibling web APIs.&lt;&#x2F;p&gt;
&lt;p&gt;For a front-end developer, programing directly in WebGL feels like juggling
many unseen global variables while struggling to understand why functions take
those strange byte arguments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;maskontop.png&quot; alt=&quot;Three colored COVID face masks on top of each other&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;graphics-frameworks-that-work-on-top-of-graphics-frameworks&quot;&gt;Graphics frameworks that work on top of graphics frameworks&lt;&#x2F;h2&gt;
&lt;p&gt;Fortunately, there are a lot of frameworks that simplify our life when dealing
with the WebGL API. The most recent web-trend of these use threejs and tries to
bring back some helpful &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;VRML&quot;&gt;VRML&lt;&#x2F;a&gt;-like concepts through tags&#x2F;components. For React,
there is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pmndrs&#x2F;react-three-fiber&quot;&gt;&quot;react-three-fiber&quot;&lt;&#x2F;a&gt;.
For Web Components, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aframe.io&quot;&gt;&quot;a-frame&quot;&lt;&#x2F;a&gt;, and recently
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;troisjs.github.io&quot;&gt;&quot;troisjs&quot;&lt;&#x2F;a&gt; for Vue, among many others.&lt;&#x2F;p&gt;
&lt;p&gt;These frameworks provide the same sort of standard graphical decomposition.
They use &lt;em&gt;&quot;cameras&quot;&lt;&#x2F;em&gt; pointed into a &lt;em&gt;&quot;scene&quot;&lt;&#x2F;em&gt; of &lt;em&gt;&quot;objects&quot;&lt;&#x2F;em&gt; with &lt;em&gt;&quot;materials&quot;&lt;&#x2F;em&gt;
and &lt;em&gt;&quot;transformations&quot;&lt;&#x2F;em&gt; applied to them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-use-webgl-directly&quot;&gt;Why use WebGL directly?&lt;&#x2F;h2&gt;
&lt;p&gt;Using the WebGL API directly, at the very least, helps you understand how it
works and consequently how those trendy high-level graphics frameworks get to
deploy their concepts. It is not for the faint of heart. WebGL is a low-level
API that inherits a lot of stuff from OpenGL ES, inheriting a lot from OpenGL,
inheriting a lot from the 90s. Oh, the 90s, the dark ages of API design.&lt;&#x2F;p&gt;
&lt;p&gt;All that taken into consideration, there are some &lt;strong&gt;real&lt;&#x2F;strong&gt; benefits for the
enthusiastic programmer:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Learn an abstraction of GPU graphics and primitives:&lt;&#x2F;strong&gt; in WebGL, there are
no &lt;em&gt;&quot;cameras&quot;&lt;&#x2F;em&gt; or even a &lt;em&gt;&quot;scene&quot;&lt;&#x2F;em&gt; with &lt;em&gt;&quot;materials&quot;&lt;&#x2F;em&gt;. Instead, you get to use
&lt;em&gt;&quot;buffers&quot;&lt;&#x2F;em&gt; and &lt;em&gt;&quot;programs&quot;&lt;&#x2F;em&gt;, and &lt;em&gt;&quot;vertex array objects&quot;&lt;&#x2F;em&gt; in &lt;em&gt;&quot;shader&quot;&lt;&#x2F;em&gt; code
written with a specific syntax.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Focus on shaders:&lt;&#x2F;strong&gt; WebGL is all about the code that runs ultra fast in the
GPU, using specific techniques to leverage high-performance parallel runs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Immediate mode API:&lt;&#x2F;strong&gt; Learning how to use an immediate mode graphics API is
cool to understand how it is biased towards baking things in initialization
to reduce the draw calls that get executed at runtime.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you are willing to go down that rabbit hole, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.khronos.org&#x2F;webgl&#x2F;wiki&#x2F;Getting_Started&quot;&gt;start here&lt;&#x2F;a&gt;
and proceed with the excellent &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webgl2fundamentals.org&quot;&gt;WebGL 2 Fundamentals&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;abstract-the-frustration-away&quot;&gt;Abstract the frustration away&lt;&#x2F;h2&gt;
&lt;p&gt;With WebGL, even simple things take quite a bit of code. A simple image is
never &quot;simple&quot;. It can require pages of code in setup and initialization and a
whole WebGL global state system that needs to be maintained.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;masksontree.png&quot; alt=&quot;A tree with COVID masks as leafs&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As a result, 10 years ago, back in the early days of WebGL (which today has
its 10th anniversary!), a few libraries showed up that used a thin abstraction
layer on top of it and tried to deal with the boilerplate JS code.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;evanw&#x2F;lightgl.js&#x2F;&quot;&gt;lightgl.js&lt;&#x2F;a&gt; is one of these notorious
libs.&lt;&#x2F;p&gt;
&lt;p&gt;Writing and maintaining the WebGL boilerplate can be quite a traumatic
experience for the aspiring front-end developer. There are many formulations
of its concepts that have evolved through these 10 years.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;being-declarative-without-losing-the-webgl-domain&quot;&gt;Being declarative without losing the WebGL domain&lt;&#x2F;h2&gt;
&lt;p&gt;The new graphics frameworks bring into the declarative space the primitives
that threejs handle in code. They do it subtly by bridging DOM libraries
(React, Vue, or even bare Web Components) and standard high-level graphics
primitives.&lt;&#x2F;p&gt;
&lt;p&gt;HTML tags are excellent in providing sequence and hierarchy in a declarative
way. Their structure is an easy match for scene graphs.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;VRML&quot;&gt;VRML&lt;&#x2F;a&gt; was onto something, and now we know
it.&lt;&#x2F;p&gt;
&lt;p&gt;What if this declarative tag-oriented approach could be used in the WebGL
domain primitives instead of the typical camera&#x2F;scene graph representation?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;meet-shader-canvas&quot;&gt;Meet &lt;a href=&quot;&#x2F;projects&#x2F;shader-canvas&quot;&gt;&lt;code&gt;&amp;lt;shader-canvas&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In my life quest of making different drawing tools and apps, I find myself
leaning more towards using buffers and GLSL programs than with &quot;cameras&quot; and
nodes.&lt;&#x2F;p&gt;
&lt;p&gt;I am not a graphics programmer by trade and tend to start thinking about
shader code and how data will flow with it before any other graphical
abstraction. This was a strong motivation to create a low-level WebGL
abstraction that could be easily visible and declared with tags.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;rainbowcube.png&quot; alt=&quot;A cube defined by its edges, each edge is a rainbow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The idea is simple and two-fold:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create an HTML tag for each WebGL function.&lt;&#x2F;li&gt;
&lt;li&gt;Have HTML tags to contain the instances of WebGL primitives.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;After experimenting for a while with Web Components, I have come up with the
library&#x27;s initial version.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;project-button&quot; href=&quot;&#x2F;projects&#x2F;shader-canvas&quot;&gt;The shader-canvas project site.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It purposely has no graphics or fluffy examples to watch at this stage. It is
a proof-of-concept and the base of my future work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Before I started doing &lt;a href=&quot;&#x2F;projects&#x2F;shader-canvas&quot;&gt;shader-canvas&lt;&#x2F;a&gt;, I repeatedly wrote the same WebGL code
with small nuances. I looked for inspiration in other libraries in how to
decompose graphical problems. The part that intrigued me most was the balance
between the WebGL API&#x27;s low-level aspects and its high-level compositions. It
should be possible to target a lower-mid-level of abstraction.&lt;&#x2F;p&gt;
&lt;p&gt;Today is the 10th anniversary of WebGL. It felt appropriate to write about it
and introduce &lt;a href=&quot;&#x2F;projects&#x2F;shader-canvas&quot;&gt;shader-canvas&lt;&#x2F;a&gt; together with some of
the motivation behind it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;projects&#x2F;shader-canvas&quot;&gt;Shader-canvas&lt;&#x2F;a&gt; is a graphics framework that uses HTML
tags to perform the WebGL
API calls and manage its primitives. It does not have a camera or a scene.
Instead, there is a set of tags to declare most of the recurrent WebGL code
that I found myself writing over and over.&lt;&#x2F;p&gt;
&lt;hr&gt;&lt;&#x2F;hr&gt;
&lt;p&gt;Shader canvas is the product of Web Components explorations that I have been
writting about. Check out &lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-series&#x2F;&quot;&gt;the whole series&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The life of a Web Component</title>
        <published>2021-03-02T00:00:00+00:00</published>
        <updated>2021-03-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/the-life-of-a-web-component-series/"/>
        <id>https://hugodaniel.com/posts/the-life-of-a-web-component-series/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/the-life-of-a-web-component-series/">&lt;h2 id=&quot;1-initialization&quot;&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component&#x2F;&quot;&gt;1 - Initialization&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This post is the first in the series. It talks about avoiding the Web
Components constructor, events and life-cycle methods while rolling your
approach.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-as-a-variable-bucket&quot;&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-as-var&#x2F;&quot;&gt;2 - As a variable bucket&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In this post I was trying to automatically declare new tags as they get
written in the DOM. Here I introduce container elements, which allow their
child tags to have any name by assuming that they will all be using the same
Web Component class.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-reversing-shadow-dom-visibility&quot;&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-reverse-shadow-dom&#x2F;&quot;&gt;3 - Reversing Shadow DOM visibility&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Once a Shadow DOM is used the browser assumes it to be the source of truth and
the holder of the content that is going to be displayed. What if it was the
other way around? In this post the child tags of a Web Component get displayed
by default while the Shadow DOM is used to keep hidden state.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-declarative-state&quot;&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-state-in-shadow&#x2F;&quot;&gt;4 - Declarative State&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This post uses the variable buckets from part 2 to declare complex app state.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-getting-tested&quot;&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-tests&#x2F;&quot;&gt;5 - Getting tested&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Trying to test Web Components without any bigger knowledge of its related
best-practices. Just thoughts about trying it out and seeing where it goes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shader-canvas&quot;&gt;&lt;a href=&quot;&#x2F;projects&#x2F;shader-canvas&#x2F;&quot;&gt;shader-canvas&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A graphics framework that makes use of the Web Component techniques in this
series.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The life of a Web Component - Getting Tested</title>
        <published>2021-01-31T00:00:00+00:00</published>
        <updated>2021-01-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/the-life-of-a-web-component-tests/"/>
        <id>https://hugodaniel.com/posts/the-life-of-a-web-component-tests/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/the-life-of-a-web-component-tests/">&lt;p&gt;In this post, I present what is by far the 2nd best way to test Web Components. I say this because there must be at least one way better than the one I am presenting. Also, I don&#x27;t know of any other way to test them since I have just started playing with Web Components. So yeah, 2nd best, by (infinitely) far.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-to-test-a-web-component&quot;&gt;Where to test a Web Component?&lt;&#x2F;h2&gt;
&lt;p&gt;First, a starting note:&lt;&#x2F;p&gt;
&lt;p&gt;The techniques I am going to show are not thought for &lt;abbr title=&quot;Command Line Interface&quot;&gt;CLI&lt;&#x2F;abbr&gt; usage. They are meant for the browser. Where Web Components run and are used.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;There is no way that my CircleCI pipes are going to run a browser instance!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is a problem. Maybe for CI, it could be possible to separate the logic parts from the Web Components into contained JS modules with their own separate unit tests in &lt;abbr title=&quot;Command Line Interface&quot;&gt;CLI&lt;&#x2F;abbr&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;html5_tests.png&quot; alt=&quot;The HTML5 badge next to three vertical checkboxes. The first two checkboxes have a cross.&quot; title=&quot;HTML testing&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing-web-components-with-framework&quot;&gt;Testing Web Components with $FRAMEWORK&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Hello $FRAMEWORK,&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I hope you are well. &lt;br&gt;We are currently reinforcing our team in the most diverse areas. Your profile has captured my attention, and I believe it might fit our current projects&#x27; frame. Would you be interested in considering a new professional opportunity that entails intense Shadow DOM manipulation and active HTML modifications in a very dynamic environment?
&lt;br&gt;
&lt;br&gt;
Grateful for your attention,&lt;br&gt;
Hugo&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Running the tests in the browser is essential when testing Web Components. A Web Component can be a low-level piece of logic tightly bound to a particular DOM configuration. Some parts of the Web Component might be hard to test, particularly the Shadow DOM modifications (it&#x27;s a DOM root designed intentionally to provide encapsulation).&lt;&#x2F;p&gt;
&lt;p&gt;Most things happen asynchronously with Web Components. Either through&#x2F;after a particular event or because it is a composed Web Component that only shows its intended behavior after a series of &lt;code&gt;connectedCallback()&lt;&#x2F;code&gt;&#x27;s,&lt;code&gt;#shadow-root&lt;&#x2F;code&gt; manipulations, or other strange browser behaviours happening. Anything goes. You gotta love browserland.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;eierschalensollbruchstellenverursacher&quot;&gt;Eierschalensollbruchstellenverursacher&lt;&#x2F;h2&gt;
&lt;p&gt;There is another problem when testing Web Components:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Your tests might not be running independently from each other&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A workaround is needed just to guarantee one of the basic tenents of (Unit|Integration|Regression|End-To-End|Functional|Performance|Who|Invented|This|Shit)-tests.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;But why can&#x27;t I have independent Web Components tests?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CustomElementRegistry&quot;&gt;CustomElementRegistry&lt;&#x2F;a&gt; (the global var that browsers have where we define our custom tag names) has no &lt;code&gt;delete()&lt;&#x2F;code&gt; method. Once you associate a Web Component to a tag there is no way to remove that association. This means that when the first test in the test suit determines a Web Component tag, it will be available for the other tests in that suit (within the same browser session).&lt;&#x2F;p&gt;
&lt;p&gt;The tests should ideally all be independent of each other, running automatically, in parallel if needed. If the first test fries a global var that further tests will depend on, they will break.&lt;&#x2F;p&gt;
&lt;p&gt;Worse still, if your fellow developer introduces a new test that happens to depend on a given state of that global var, then other tests might break it inadvertently by merely manipulating the global var.&lt;&#x2F;p&gt;
&lt;p&gt;All this means that if a Web Component depends on a declaration flow or on a name tag definition, it might introduce flaky tests when they are run together.&lt;&#x2F;p&gt;
&lt;p&gt;This is not a big deal if Web Components do not depend&#x2F;use other Web Components &lt;em&gt;and&lt;&#x2F;em&gt; they map 1-1 to a given tag.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, this might be a limiting factor for some use cases. It is a limiting factor for the techniques I have been showing in this series.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;global_var.png&quot; alt=&quot;Three emojiis diagonally - world, dynamite, mind blown&quot; title=&quot;One Global Var per day...&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Looks like they were unable to keep the 10x programmers away from the Web Components spec.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;They certainly Got Shit Done. This is indeed a global var object with no way to remove the stuff placed in it.&lt;&#x2F;p&gt;
&lt;p&gt;Fear not. There are a couple of ways to circumvent this and other problems.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-gloves-won-t-fit-oj&quot;&gt;The gloves won&#x27;t fit OJ&lt;&#x2F;h2&gt;
&lt;p&gt;The laziest way I found to run Web Components tests in the browser was to have a single &lt;code&gt;test.html&lt;&#x2F;code&gt; file that I open with the browser.&lt;&#x2F;p&gt;
&lt;p&gt;This single &lt;code&gt;test.html&lt;&#x2F;code&gt; file includes the test suits for each Web Component I want to test. The &lt;code&gt;*.test.js&lt;&#x2F;code&gt; files with the tests for each Web Component.&lt;&#x2F;p&gt;
&lt;p&gt;This &lt;code&gt;test.html&lt;&#x2F;code&gt; has no real dependencies. It is just a &lt;code&gt;.html&lt;&#x2F;code&gt; file that I can open directly in the browser without running a development server. Some tools can be used to make it auto-refresh and do parallel runs if necessary. But I just want to run tests for now.&lt;&#x2F;p&gt;
&lt;p&gt;The $FRAMEWORKs I used are Mocha and Chai, two old JS testing tools that provide bundles ready to be used directly in the browser:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;DOCTYPE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;meta&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; charset&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;utf-8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Web Components Tests&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Include the Mocha and Chai code bundles &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;link&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; rel&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;stylesheet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;https:&#x2F;&#x2F;unpkg.com&#x2F;mocha&#x2F;mocha.css&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;https:&#x2F;&#x2F;unpkg.com&#x2F;chai&#x2F;chai.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;https:&#x2F;&#x2F;unpkg.com&#x2F;mocha&#x2F;mocha.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Test results will show up inside this #mocha &amp;lt;div&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;mocha&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; This is where my Web Components will be placed at during testing &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;domTestArea&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;display: none;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;                  ^ no need to show them &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Initialize the Mocha framework &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;mocha-init&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;bdd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Leak checking is important with Web Components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Always include a list of global vars to ignore (empty for now)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;global&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;checkLeaks&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Make &amp;quot;assert&amp;quot; available in all `.test.js` files &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; assert&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;chai&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    Some global initialization code:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      - create global testing helpers &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      - setup the App runtime parts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; App initiliazation code goes here... I&amp;#39;ll get to it &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Put the Web Components testing files here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;my-partner-is-a-web-component.test.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i-should-go-out-more-web-component.test.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Automatically start the Mocha framework &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;mocha-exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The code above is a straightforward Mocha and Chai browser-only setup for Web Components.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;html_bugs.png&quot; alt=&quot;The HTML5 badge in the middle of a lot of colored PacMan ghosts.&quot; title=&quot;Who is afraid of the Shadow DOM?&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tests-initialization&quot;&gt;Tests initialization&lt;&#x2F;h2&gt;
&lt;p&gt;Before any tests can be written, I like to do a standard global initialization of the whole thing. This mostly consists of importing the App module where the Web Components are declared and some global utility functions.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    Some global initialization code:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      - create global testing helpers &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      - setup the App runtime parts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;	import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MyApp&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; from&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;..&#x2F;build&#x2F;app-bundle.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above creates the globally available things: The &lt;code&gt;MyApp&lt;&#x2F;code&gt; object of the app that will be using or wrapping the Web Components. This is optional. If the Web Components are just stand-alone, there will be no need for this. This is also a good place to create single tags with &lt;code&gt;customElements.define()&lt;&#x2F;code&gt; (if this is not done by the &lt;code&gt;MyApp&lt;&#x2F;code&gt; bundle).&lt;&#x2F;p&gt;
&lt;p&gt;When using Mocha it is necessary to also include the intended globals in the leaks ignore array:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Initialize the Mocha framework &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; class&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;mocha-init&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;bdd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Leak checking is necessary with Web Components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Always include a list of global vars to ignore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;global&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;MyApp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;          ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;checkLeaks&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Make &amp;quot;assert&amp;quot; available in all `.test.js` files &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; assert&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; mocha&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;chai&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Yeah, but how are the Web Component tests gonna be done?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;suit-up&quot;&gt;Suit up&lt;&#x2F;h2&gt;
&lt;p&gt;I will break the Web Component tests into three parts that build on each other by adding extra complexity.&lt;&#x2F;p&gt;
&lt;p&gt;You decide if a given test needs all of these three features or just the first one.&lt;&#x2F;p&gt;
&lt;p&gt;The following code runs in its own dedicated test file, say an &lt;code&gt;i-should-go-out-more-web-component.test.js&lt;&#x2F;code&gt; with the Web Component tests with that name.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;bug_target.png&quot; alt=&quot;A worm bug emoji in the middle of a target.&quot; title=&quot;Please don&amp;#39;t kill me!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-place-the-tags-in-domtestarea-and-get-the-class&quot;&gt;1 - Place the tags in #domTestArea and get the class&lt;&#x2F;h3&gt;
&lt;p&gt;The basic test template to run the Web Component tests in the &lt;code&gt;#domTestArea&lt;&#x2F;code&gt; can be something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;describe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;i-should-go-out-more&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Clear the #domTestArea between each test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    beforeEach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; domTestArea&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;innerHTML&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    it&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;can do simple stuff with DOM tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;done&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Inside the test, I can use things in however I want (AAA pattern, or just fetuccine&#x2F;spaghetti), but it is essential to at least do these things:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Put a Web Component tag in the #domTestArea&lt;&#x2F;li&gt;
&lt;li&gt;Get the Web Component class instance on that tag&lt;&#x2F;li&gt;
&lt;li&gt;Do some assertions&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;describe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;i-should-go-out-more&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; simpleTag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &amp;lt;i-should-go-out-more&amp;gt;Some content&amp;lt;&#x2F;i-shoud-go-out-more&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Clear the #domTestArea between each test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    beforeEach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; domTestArea&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;innerHTML&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    it&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;can do simple stuff with DOM tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;done&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 1. Put a Web Component tag in the #domTestArea&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        domTestArea&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;innerHTML&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; simpleTag&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2. Get the Web Component class instance on that tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; instance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;querySelector&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i-should-go-out-more&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 3. Do some assertions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; (here is where the test happens)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        assert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;instance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;parsedLines&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Should parse content lines&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Async by default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A note of attention is needed, if the original &lt;code&gt;MyApp&lt;&#x2F;code&gt; global var does not define a unique the Web Component tag (and its dependencies), and the &lt;code&gt;customElements&lt;&#x2F;code&gt; is part of the test then it might be needed to produce a new dynamic tag per test to work-around the global var problem:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; simpleTag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;testId&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &amp;lt;i-should-go-out-more-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;testId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        Some content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &amp;lt;&#x2F;i-shoud-go-out-more-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;testId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;2-shadow-dom-inspection&quot;&gt;2 - Shadow DOM inspection&lt;&#x2F;h3&gt;
&lt;p&gt;If a Shadow DOM is being used, it will be the root of what the Web Component renders. There might be a need to test its contents to see if the Web Component is doing the expected DOM output.&lt;&#x2F;p&gt;
&lt;p&gt;However, Shadow DOM can be manipulated throughout a Web Component&#x27;s life in many different situations and ways.&lt;&#x2F;p&gt;
&lt;p&gt;One way to abstract the Web Component&#x27;s inner workings from the test is to use a Mutation Observer for the root. The assertions are then placed inside the observer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;describe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;i-should-go-out-more&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; simpleTag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &amp;lt;i-should-go-out-more&amp;gt;Some content&amp;lt;&#x2F;i-shoud-go-out-more&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Clear the #domTestArea between each test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    beforeEach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; domTestArea&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;innerHTML&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    it&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;can do simple stuff with DOM tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;done&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 1. Put a Web Component tag in the #domTestArea&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        domTestArea&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;innerHTML&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; simpleTag&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2. Get the Web Component class instance on that tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; instance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;querySelector&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i-should-go-out-more&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2.1 Get the Shadow Root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; instance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;shadowRoot&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2.2 Create a Mutation Observer for it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; observer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MutationObserver&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;async&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 3. Do some assertions when the shadowRoot exists&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; (here is where the test happens)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;            assert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;instance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;somethingShadowy&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Should have this property&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Async because nobody knows when&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; the shadow root observer might trigger &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;            done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Shadow DOM is being changed asynchronously&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;quot;childList&amp;quot; is enough to observe its changes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        observer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;observe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            childList&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;3-waitfor-meeee&quot;&gt;3 - waitFor meeee&lt;&#x2F;h2&gt;
&lt;p&gt;Testing Web Components is mostly an async task, tests will often need to wait a beat or a few milliseconds for things to be connected and children&#x2F;attributes processed.&lt;&#x2F;p&gt;
&lt;p&gt;If this is the case for the Web Component being tested then it is importante to make sure that there is some kind of &lt;code&gt;waitFor&lt;&#x2F;code&gt; function available (either by the testing framework or place this in the &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; that initializes the &lt;code&gt;MyApp&lt;&#x2F;code&gt; and all utility functions):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; A very rough example of a `waitFor` function that&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; delays execution until a provided condition&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; becomes true (or a timeout is reached)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; waitFor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;condition&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; timeout&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; I don&amp;#39;t want to comment this. It is just a quick and dirty approach&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Give preference to your testing framework tools for this&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; I couldn&amp;#39;t find anything similar for Mocha, so yeah:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;      const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; activePoll&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; Promise&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resolve&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; reject&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;          let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; timeoutId&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;          const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; intervalId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setInterval&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;condition&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;              clearTimeout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;timeoutId&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;              clearInterval&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;intervalId&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;              resolve&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 20&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          timeoutId&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setTimeout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;            clearInterval&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;intervalId&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;            reject&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; timeout&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;      try&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        await&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; activePoll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    globalThis&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;waitFor&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; waitFor&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this function, I can wait for a given condition to happen before running the test assertions.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;describe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;i-should-go-out-more&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; simpleTag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &amp;lt;i-should-go-out-more&amp;gt;Some content&amp;lt;&#x2F;i-shoud-go-out-more&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    `&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Clear the #domTestArea between each test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    beforeEach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; domTestArea&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;innerHTML&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    it&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;can do simple stuff with DOM tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;done&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 1. Put a Web Component tag in the #domTestArea&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        domTestArea&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;innerHTML&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; simpleTag&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2. Get the Web Component class instance on that tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; instance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;querySelector&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i-should-go-out-more&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2.1 Get the Shadow Root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; instance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;shadowRoot&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2.2 Create a Mutation Observer for it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; observer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MutationObserver&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;async&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 2.3 Wait for content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;            const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; contents&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;instance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;contentMap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;            const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; contentCreated&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; await&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; waitFor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;               (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; contents&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; !==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;length&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 3. Do some assertions for the content above&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;            assert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;contentCreated&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;includes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cool stuff&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;            done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        observer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;observe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            childList&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Testing Web Components is not fun. There is also not that much space to be creative here. Web Components have a lot of particularities that need to be considered. In this post, I presented three techniques to handle Web Component tests and their eventual awkward flow.&lt;&#x2F;p&gt;
&lt;p&gt;Having a commonplace (&lt;code&gt;#domTestArea&lt;&#x2F;code&gt;) to dump Web Components during testing and using some sort of &lt;code&gt;async waitFor()&lt;&#x2F;code&gt; inside a Mutation Observer on the &lt;code&gt;#shadow-root&lt;&#x2F;code&gt; looks like too much hassle. It feels that all of this should not be needed. I found that these three techniques solve most problems I often encountered when testing Web Components. I don&#x27;t like these hacks but &lt;em&gt;they work&lt;&#x2F;em&gt; in general. Generally.&lt;&#x2F;p&gt;
&lt;hr&gt;
&lt;p&gt;This post is Part 5 of a series I am writing called &lt;cite&gt;&quot;The Life of a Web Component&quot;&lt;&#x2F;cite&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The previous parts are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component&#x2F;&quot;&gt;Part 1 - Initialization&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-as-var&#x2F;&quot;&gt;Part 2 - As a variable bucket&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-reverse-shadow-dom&#x2F;&quot;&gt;Part 3 - Reversing Shadow DOM visibility&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-state-in-shadow&#x2F;&quot;&gt;Part 4 - Declarative State&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The life of a Web Component - Declarative State</title>
        <published>2021-01-30T00:00:00+00:00</published>
        <updated>2021-01-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/the-life-of-a-web-component-state-in-shadow/"/>
        <id>https://hugodaniel.com/posts/the-life-of-a-web-component-state-in-shadow/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/the-life-of-a-web-component-state-in-shadow/">&lt;p&gt;What if custom tags could be used for the application state?&lt;&#x2F;p&gt;
&lt;p&gt;For instance, consider a simple todo app that gets rendered like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Sleep better, don&amp;#39;t be tired.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Replace a tire&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Write a tiresome article&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;?????&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Profit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Nah, forget profit, just write something&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just a simple list of todos, declared and visible both in the browser and in code, a typical day in HTML.&lt;&#x2F;p&gt;
&lt;p&gt;Then each of those &lt;code&gt;&amp;lt;li&amp;gt;&lt;&#x2F;code&gt; items in the todo app could have some state associated. Here is a configuration that might fit it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Creation date&lt;&#x2F;li&gt;
&lt;li&gt;Tags&#x2F;Category&lt;&#x2F;li&gt;
&lt;li&gt;Cost&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is on top of what HTML already elegantly declares:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Item content (&quot;Replace a tire&quot; etc.)&lt;&#x2F;li&gt;
&lt;li&gt;Item order (what is the sequence of items)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It would be cool if they could be referenced by some id as well. In HTML, this &quot;id&quot; is just their node element. It is unique from the moment it exists in the DOM (but there is also the &quot;id&quot; attribute only in case a human readable id is needed).&lt;&#x2F;p&gt;
&lt;p&gt;One possible state representation for the Todo Item could be done in JS using a normal object:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; createItemState&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;creationDate&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; categories&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; cost&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span&gt; creationDate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ,&lt;&#x2F;span&gt;&lt;span&gt; categories&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ,&lt;&#x2F;span&gt;&lt;span&gt; cost&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which would then be used at the bigger app state structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; todoAppState&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    todoItems&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Sleep better, don&amp;#39;t be tired&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; createItemState&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;lifestyle&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Replace a tire&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; createItemState&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;chores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 9001&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; some other app state here...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are infinite other ways to map this state in JS. This is just to lay out the mapping to HTML.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;js_logo_with_html.jpg&quot; alt=&quot;The yellow JavaScript logo, with HTML5 badges masking the letters J and S&quot; title=&quot;On the internet nobody knows you&amp;#39;re an HTML!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Bringing the above examples from JavaScript into HTML can be done by using a custom element for each state &quot;unit&quot;. Something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;2021-01-31&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&amp;quot;lifestyle&amp;quot;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;2020-10-10&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&amp;quot;chores&amp;quot;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;9001&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ... other items here ... &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It has the potential to become involved. A common strategy to break state complexity down is to think of it as the flow of actions that transform it, instead of thinking of it as the content it holds.&lt;&#x2F;p&gt;
&lt;p&gt;In that view, the above only becomes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; contents will be generated by the actions &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Don&amp;#39;t care &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Whatever &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Meh &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ no need to think more than one ^ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since HTML provides sequence, a list of state modifying actions can then be defined with it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;actions-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;       &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Sleep better, don&amp;#39;t be tired.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;       &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Get out of bed.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;       &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;delete-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Get out of bed.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;delete-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;actions-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ This will be populated through the actions above ^ &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;todo-items&amp;gt;&lt;&#x2F;code&gt; inner state is populated by running through the sequence of items on the &lt;code&gt;&amp;lt;actions-list&amp;gt;&lt;&#x2F;code&gt; element. This is just bringing into declarative HTML a popular state handling mechanism - a sequence of state transformations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;That is ugly looks like XML, I don&#x27;t want that in my code&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Indeed, that is why reversing the Shadow DOM visibility is handy. It makes for the perfect trash bin to dump this state. Letting the app be just plain pure HTML.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  #shadow-root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;actions-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; category&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;lifestyle&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Sleep better, don&amp;#39;t be tired.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Get out of bed.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;delete-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Get out of bed.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;delete-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; category&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;chores&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; cost&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;9001&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              Replace a tire.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;create-item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;actions-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;2021-01-31&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&amp;quot;lifestyle&amp;quot;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;2021-01-31&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;creation-date&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;[&amp;quot;chores&amp;quot;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;category-list&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;            &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;9001&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cost-of-doing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;item-state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-items&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt;          :&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt;not&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;             display&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; none&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;⮑&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Replace a tire.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Sleep better, don&amp;#39;t be tired.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ol&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;todo-app&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;html5_code_monkeys.png&quot; alt=&quot;The HTML5 badge broken in two, in the middle an imagem of two monkeys grooming hair.&quot; title=&quot;HTML code monkeys&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In a way, a tag with the Shadow DOM visibility reversed and state will emit no real HTML. Only the HTML provided by its children gets linked to being shown at the &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt;, nothing else is visually added, things are kept under the Shadow DOM, waiting to be revealed in a late-night debugging session.&lt;&#x2F;p&gt;
&lt;p&gt;If I need to know the app&#x27;s current state, I open the developer tools, expand its &lt;code&gt;#shadow-root&lt;&#x2F;code&gt;, and there it is, in full glory with the actions that created it.&lt;&#x2F;p&gt;
&lt;p&gt;The partitioning and separation that I present here is just one possible example among the infinite possibilities in declarative state presentation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;big-conclusion-that-is-more-like-a-rant-than-a-conclusion&quot;&gt;Big conclusion that is more like a rant than a conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Thinking about the state is paramount when building a complex app. It is an effort particularly hard for me because I do not like to think that much and prefer to just chill. Functional programming intellectuals have long been shouting that state management is actually a somewhat solved problem.&lt;&#x2F;p&gt;
&lt;p&gt;They argue that it is much better to have no state and just bounce a couple of vars around, transforming them with a sequence of actions. I think that is what they mean with their jargon.&lt;&#x2F;p&gt;
&lt;p&gt;The Lisps yoga gurus shove their variables with a bunch of parentheses, define&#x27;s and recursive logic. Haskell Scientologists are a bit more refined and seem to prefer &quot;Monads&quot; with &quot;syntactic sugar&quot; or whatever.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;eat_haskell.png&quot; alt=&quot;An image of a UFO in the sky beaming lambdas. Bellow the image the letters &amp;quot;Eat Haskell Motherfuckers&amp;quot;.&quot; title=&quot;Healthy alien diet&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When considering state management techniques, we front-end devs are clearly the peasants. The low-life form resigned to pick up the elite&#x27;s crumbs and glue them together with spit in a global variable with a name that looks like it is something serious and functional, say &quot;redux&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The story doesn&#x27;t end there because even within the front-end mambo, there are differences. In particular, the vanilla crowd is the underrepresented minority. Why use plain HTML and CSS when you can throw a ton of JS and do all of it with the latest cool frameworks? In fact, forget JS, lets use &lt;s&gt;Haxe&lt;&#x2F;s&gt;, &lt;s&gt;CoffeScript&lt;&#x2F;s&gt;, &lt;s&gt;Flow&lt;&#x2F;s&gt;, &lt;s&gt;Babel&lt;&#x2F;s&gt;, TypeScript.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nobody-ever-made-it-to-fortune-500-with-that-tech&quot;&gt;Nobody ever made it to Fortune 500 with that tech.&lt;&#x2F;h3&gt;
&lt;p&gt;HTML deserves a bit more attention. It has to be possible to define a complex app state with something that gives us a declarative hierarchy with an exact sequence that binds semantics with functionality.&lt;&#x2F;p&gt;
&lt;p&gt;When breaking complicated things into manageable parts, I typically think about the following questions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;What kind of &quot;buckets&quot; can the information be split into?&lt;&#x2F;li&gt;
&lt;li&gt;How are the items in those buckets going to be referenced in the app?&lt;&#x2F;li&gt;
&lt;li&gt;Will those &quot;buckets&quot; work for 0, 1, and n items? (sometimes n&lt;em&gt;n&lt;&#x2F;em&gt;n*...*n?)&lt;&#x2F;li&gt;
&lt;li&gt;How is information going to flow into them and out of them?&lt;&#x2F;li&gt;
&lt;li&gt;Why are all the hipsters, brogrammers, and rockstars moving from JS into Swift?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Can HTML custom tags provide an acceptable abstraction to those questions? I don&#x27;t know. I don&#x27;t even want to have to think about a complex app. Complexity is just simplicity waiting to be born.&lt;&#x2F;p&gt;
&lt;p&gt;However, Web Components can provide a way to declare a state that can easily be removed after. Which is more than good enough for me :)&lt;&#x2F;p&gt;
&lt;hr&gt;
&lt;p&gt;This post is Part 4 of a series I am writing called &lt;cite&gt;&quot;The Life of a Web Component&quot;&lt;&#x2F;cite&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The previous parts are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component&#x2F;&quot;&gt;Part 1 - Initialization&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-as-var&#x2F;&quot;&gt;Part 2 - As a variable bucket&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-reverse-shadow-dom&#x2F;&quot;&gt;Part 3 - Reversing Shadow DOM visibility&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-tests&#x2F;&quot;&gt;Part 5 - Get Tested&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The life of a Web Component - Reversing the Shadow DOM visibility</title>
        <published>2021-01-29T00:00:00+00:00</published>
        <updated>2021-01-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/the-life-of-a-web-component-reverse-shadow-dom/"/>
        <id>https://hugodaniel.com/posts/the-life-of-a-web-component-reverse-shadow-dom/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/the-life-of-a-web-component-reverse-shadow-dom/">&lt;p&gt;The other day I was thinking about what do HTML tags give us out of the box and made this list:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Hierarchy&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;luke-im-your-father&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nooo-thats-impossible&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nooo-thats-impossible&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;luke-im-your-father&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Sequence&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;I’d use one for parts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;If I ever have twins&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Meaning&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; cite&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Meaning_(philosophy)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;A relationship between two sorts of things:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;signs and the kinds of things they intend, express or signify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;q&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Functionality&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;video&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; controls&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; width&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;250&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;source&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;media&#x2F;cc0-videos&#x2F;flower.webm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt;            type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;video&#x2F;webm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;source&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;media&#x2F;cc0-videos&#x2F;flower.mp4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt;            type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;video&#x2F;mp4&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Sorry, your browser doesn&amp;#39;t support embedded videos.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;video&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This list is by no means exhaustive. There are likely many more things that HTML tags give us (like headaches, reactjs, and some money at the end of the month if we are lucky).&lt;&#x2F;p&gt;
&lt;p&gt;With the Shadow DOM it is possible to compose all of the features above and hide them away inside custom tags.&lt;&#x2F;p&gt;
&lt;p&gt;I want to use Shadow DOM like a rug that I can sweep tags under it. A particular DOM root that cannot be seen and that is under the control of a tag.&lt;&#x2F;p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;&lt;strong&gt;Encapsulation&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nevermind-the-backend-this-is-where-the-dragons-are&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; there is nothing to see here because this tag has a Shadow root &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nevermind-the-backend-this-is-where-the-dragons-are&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This DOM root inception made me wonder: &lt;em&gt;&quot;What is the default visibility behavior of the Shadow DOM? could it be reversed?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;html5_mask.png&quot; alt=&quot;The HTML5 badge with an amazing purple eye mask&quot; title=&quot;Shadow DOM is such a cool name, but wait until you see its fabulous mask!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hmm-that-sounds-stupid-but-how-would-it-work&quot;&gt;Hmm, that sounds stupid, but how would it work?&lt;&#x2F;h2&gt;
&lt;p&gt;When a Web Component has no shadow root, it will happily render all its children:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;simple-web-component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Hello world! I am not inside the shadow root.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;simple-web-component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;simple-web-component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; What follows is the the &amp;lt;simple-web-component&amp;gt; code:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Nothing for now... just a simple component&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Call initialize when added to a parent node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    connectedCallback&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The code above creates the functionality for the &lt;code&gt;&amp;lt;simple-web-component&amp;gt;&lt;&#x2F;code&gt; tag. Which gets rendered as expected:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;no-shadow-dom.png&quot; alt=&quot;A portion of a browser window, showing the following text in black letters &amp;quot;Hello world! I am not inside the shadow root&amp;quot;, in a white background.&quot; title=&quot;In direct sunlight&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;However, this is not how it behaves when a shadow root is added to it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;adding-a-bare-shadow-root&quot;&gt;Adding a bare shadow root&lt;&#x2F;h3&gt;
&lt;p&gt;The code inside the &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; tag needs to be slightly adjusted to add a shadow root.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;simple-web-component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; The &amp;lt;simple-web-component&amp;gt; code:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;attachShadow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;mode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;open&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createElement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;textContent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;In the shadow!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Call initialize when added to a parent node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    connectedCallback&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;simple-web-component&amp;gt;&lt;&#x2F;code&gt; class now has a &lt;code&gt;root&lt;&#x2F;code&gt; attribute &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Element&#x2F;attachShadow&quot;&gt;set with its shadow root&lt;&#x2F;a&gt;. Then a simple &lt;code&gt;&amp;lt;p&amp;gt;In the shadow!&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;code&gt; is placed inside it by the &lt;code&gt;initialize()&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;p&gt;This simple shadow root will affect the display of the component.&lt;&#x2F;p&gt;
&lt;p&gt;The previous &lt;code&gt;&amp;lt;p&amp;gt;Hello world! I am not inside the shadow root.&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;code&gt; will no longer be shown since it is outside the shadow root, and now only the shadow root contents are being displayed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;with-shadow-dom.png&quot; alt=&quot;A portion of a browser window, showing the following text in black letters &amp;quot;In the shadow!&amp;quot; in a white background.&quot; title=&quot;Shaded&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;However, the inspector tools shows how the tag is really juggling the shadow dom:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;shadow-dom-inspector.png&quot; alt=&quot;The hierarchy of tags as seen by the inspector tools. Under the &amp;quot;simple-web-component&amp;quot; tag, there is a &amp;quot;#shadow-root&amp;quot; tag with a single &amp;quot;p&amp;quot; tag with the text &amp;quot;In the shadow!&amp;quot;. Also, under the &amp;quot;simple-web-component&amp;quot; another &amp;quot;p&amp;quot; tag can be seen with the content &amp;quot;Hello world! I am not inside the shadow root.&amp;quot;&quot; title=&quot;This shadow is not for everyone&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the above hierarchy it is worth noting that the original &lt;code&gt;&amp;lt;p&amp;gt;Hello World!..&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;code&gt; is still there, but &lt;em&gt;why is it not visible?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Once a shadow root is added to a tag, it becomes the thing that will get rendered. Shadow DOM is the authority, everything else is discarded, and only the stuff inside the shadow root gets displayed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Why?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Because the idea was that whatever children a custom tag would have could get rendered with ninja tricks inside the shadow. Thus giving the impression that the custom tag was getting its input from its visible children and then performing hidden layout and style foojitsu on that input (such tricks would occur inside the shadow dom - hidden from the written HTML).&lt;&#x2F;p&gt;
&lt;p&gt;Nobody cares. In fact, let me revert this logic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;you-wouldn-t-download-a-car&quot;&gt;You wouldn&#x27;t download a car&lt;&#x2F;h2&gt;
&lt;p&gt;The first step to revert the Shadow DOM is to copy all the custom components&#x27; children into its shadow root.&lt;&#x2F;p&gt;
&lt;p&gt;This will allow HTML to be rendered as expected while maintaining the Shadow DOM&#x27;s encapsulation features.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily the Web Components spec provides just the feature for this, through the &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt; tag.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-m-such-a-slot&quot;&gt;I&#x27;m such a &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This tag is used mainly in HTML &lt;code&gt;&amp;lt;template&amp;gt;&lt;&#x2F;code&gt;&#x27;s. It is the way that &lt;code&gt;&amp;lt;template&amp;gt;&lt;&#x2F;code&gt;&#x27;s have to tell which parts can be set by outsiders. Typically &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt;&#x27;s have a name attribute to be used as the reference to where the content will go. (You can see an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTML&#x2F;Element&#x2F;slot#attributes&quot;&gt;example of it here&lt;&#x2F;a&gt;, but it is not necessary, I won&#x27;t be using it.)&lt;&#x2F;p&gt;
&lt;p&gt;The cool thing is that if there is no &lt;code&gt;name&lt;&#x2F;code&gt; specified on the &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt;, then it becomes the default &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt; where all unspecified content will go in.&lt;&#x2F;p&gt;
&lt;p&gt;This is perfect. It means that if a &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt; is placed inside the shadow root (without a &lt;code&gt;name=&quot;...&quot;&lt;&#x2F;code&gt; attribute), then all of the custom element children will automatically be copied into it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;simple-web-component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Hello world! I am not inside the shadow root.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;simple-web-component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;simple-web-component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; The &amp;lt;simple-web-component&amp;gt; code:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;attachShadow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;mode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;open&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createElement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;textContent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;In the shadow!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          p&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createElement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Call initialize when added to a parent node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    connectedCallback&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Shadow Root above will contain a single &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt; tag. This makes the &lt;code&gt;&amp;lt;p&amp;gt;Hello world! I am not inside the shadow root.&amp;lt;&#x2F;p&amp;gt;&lt;&#x2F;code&gt; show up when the tag is rendered.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;with-slot.png&quot; alt=&quot;A portion of a browser window, showing two lines of text. The first one has the phrase &amp;quot;In the shadow!&amp;quot; and the second line has the phrase &amp;quot;Hello world! I am not inside the shadow root.&amp;quot;. Both of them have black letters on a white background.&quot; title=&quot;Both visible&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-ask-don-t-tell&quot;&gt;Don&#x27;t ask, don&#x27;t tell&lt;&#x2F;h2&gt;
&lt;p&gt;The second step to revert the Shadow DOM display is to only show the children of the element.&lt;&#x2F;p&gt;
&lt;p&gt;Hide everything that is outside the &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt;. Only the tag&#x27;s original children must be visible, while all the other shadow root contents must be hidden.&lt;&#x2F;p&gt;
&lt;p&gt;To achieve it, the following CSS is added to the Shadow DOM:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt;not&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    display&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; none&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The common practice is to create a &lt;code&gt;&amp;lt;style&amp;gt;&lt;&#x2F;code&gt; tag, place the above content inside it and then append the &lt;code&gt;&amp;lt;style&amp;gt;&lt;&#x2F;code&gt; tag to the Shadow DOM:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createElement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;textContent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;In the shadow!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createElement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        style&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;textContent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; `&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        :not(slot) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;          display: none;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;root&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          style&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          p&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;createElement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;slot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And just like that, the actual behavior of the Shadow DOM is reversed. The Shadow DOM contents are hidden by default, while the original custom tag children get rendered by default.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;reversed-shadow-dom.png&quot; alt=&quot;A portion of a browser window, showing one line of text with the phrase &amp;quot;Hello world! I am not inside the shadow root.&amp;quot;. This text line has black letters on a white background.&quot; title=&quot;Only the child paragraph is visible&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;No &quot;In the shadow!&quot; text is visible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;It is possible to sweep all kinds of useless trash under the Shadow DOM.&lt;&#x2F;p&gt;
&lt;p&gt;However, it might require reversing the Shadow DOM&#x27;s visibility (which is rendered by default).&lt;&#x2F;p&gt;
&lt;p&gt;To achieve it, a full copy of the custom element original children is made into the Shadow DOM (through the default &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt; tag). The next step is to hide everything inside the Shadow DOM that does not belong to the original children.&lt;&#x2F;p&gt;
&lt;p&gt;With these two moves, the element&#x27;s original children become visible while leaving all the other shadow DOM contents invisible.&lt;&#x2F;p&gt;
&lt;hr&gt;
&lt;p&gt;This post is Part 3 of a series I am writing called &lt;cite&gt;&quot;The Life of a Web Component&quot;&lt;&#x2F;cite&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The previous parts are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component&#x2F;&quot;&gt;Part 1 - Initialization&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-as-var&#x2F;&quot;&gt;Part 2 - As a variable bucket&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-state-in-shadow&#x2F;&quot;&gt;Part 4 - Declarative State&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-tests&#x2F;&quot;&gt;Part 5 - Get Tested&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The life of a Web Component - as a variable bucket</title>
        <published>2021-01-28T00:00:00+00:00</published>
        <updated>2021-01-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/the-life-of-a-web-component-as-var/"/>
        <id>https://hugodaniel.com/posts/the-life-of-a-web-component-as-var/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/the-life-of-a-web-component-as-var/">&lt;p&gt;JavaScript(JS) allows object classes to be anonymous. No need to name them and bind your class to an identifier. Instead of &lt;code&gt;class MyClass { ... }&lt;&#x2F;code&gt; write &lt;code&gt;class { ... },&lt;&#x2F;code&gt; and it will be created without a name.&lt;&#x2F;p&gt;
&lt;p&gt;Likewise prefix a regular &lt;abbr title=&quot;JavaScript&quot;&gt;JS&lt;&#x2F;abbr&gt; object &lt;code&gt;{ ... }&lt;&#x2F;code&gt; with &lt;code&gt;class&lt;&#x2F;code&gt; and have an anonymous class defined.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;HTML5_badge_tag.png&quot; alt=&quot;Three HTML5 badges in a row inside angle brackets like an html tag name. The first one has the normal orientation. The second one is upside down. The third one has a random orientation.&quot; title=&quot;Let those tags roll!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Nothing special here, classes are in fact normal &lt;abbr title=&quot;JavaScript&quot;&gt;JS&lt;&#x2F;abbr&gt; objects. The big extra is that anonymous classes, just like normal classes, can use the &lt;abbr title=&quot;JavaScript&quot;&gt;JS&lt;&#x2F;abbr&gt; &lt;code&gt;extends&lt;&#x2F;code&gt; syntax to easily carry other objects and acumulate them.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; SomeContext&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;What do Web Components have to do with this?&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; withExtraContext&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; SomeContext&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    displayName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        alert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;withExtraContext&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;displayName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is possible to pick our favorite class and create other unique classes from it that are, in fact, just declaration copies that add nothing at all. Unique copies of class declarations. Here is an example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; VeryComplicatedClass&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  foo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MyUniqueCopy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; VeryComplicatedClass&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  MyUniqueCopy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; instanceof&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; VeryComplicatedClass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; prints false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; anOriginalInstance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; VeryComplicatedClass&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; myUniqueCopyInstance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MyUniqueCopy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  anOriginalInstance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; instanceof&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; VeryComplicatedlass&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  myUniqueCopyInstance&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; instanceof&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; MyUniqueCopy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; prints true, true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But what do Web Components have to do with all of this?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;it-is-awesome&quot;&gt;It is awesome&lt;&#x2F;h2&gt;
&lt;p&gt;The global &lt;code&gt;customElements&lt;&#x2F;code&gt; registry (the global var that browsers have, where new tag names get defined) only allows one class to be associated with a single tag. Once a class has a corresponding tag-name set to it, it is no longer possible to set another-tag-name (nor delete it, but that&#x27;s for another post, hehehe).&lt;&#x2F;p&gt;
&lt;p&gt;It makes sense. Why associate two tag names to the same class anyway? I don&#x27;t know, but I still want to be able to do that nevertheless :)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;awesome-tag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ all good, ready to use &amp;lt;awesome-tag&amp;gt; all over the HTML code.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i-want-to-be-awesome-too&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ No, you don&amp;#39;t. This will throw an error.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;customElementsError.png&quot; alt=&quot;The error text: &amp;quot;Uncaught DOMException: CustomElementRegistry.define: &amp;#39;i-want-to-be-awesome-too&amp;#39; and &amp;#39;awesome-tag&amp;#39; have the same constructor&amp;quot;&quot; title=&quot;Nope&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Anonymous classes provide a simple way to avoid this limitation. By extending the Web Component class and using the unique copy of its declaration as a different tag-name. Like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;awesome-tag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ all good, like before&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i-can-be-awesome-too&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ yay \o&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;me-too&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ party!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;lets-all-be-awesome&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; Awesomeness&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ ok, you get the idea&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The code above uses multiple tag names for the same class. :)&lt;&#x2F;p&gt;
&lt;p&gt;It also allows the tags &lt;code&gt;&amp;lt;awesome-tag&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;i-can-be-awesome-too&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;me-too&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;lt;lets-all-be-awesome&amp;gt;&lt;&#x2F;code&gt; to be used in &lt;abbr title=&quot;HyperText Markup Language&quot;&gt;HTML&lt;&#x2F;abbr&gt; and all of them will share the same functionality (because they all have &lt;code&gt;Awesomeness&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;But since they all have the same functionality, why couldn&#x27;t I use a single tag name?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That is an excellent question. Having multiple tag names for the same class is the first step I found in dynamic HTML tags that can have any name and be defined only after.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-head-is-too-big-for-hats-and-too-small-to-understand&quot;&gt;My head is too big for hats and too small to understand&lt;&#x2F;h2&gt;
&lt;p&gt;This section is the part where I am going to create dynamic tag names with anonymous classes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;html5_hat.png&quot; alt=&quot;The HTML5 badge with a handrawn hat on the top of it.&quot; title=&quot;My mother said it was cool&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Since I can&#x27;t explain this well, let me try to do it with an example: a style container.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;style-container&quot;&gt;Style container&lt;&#x2F;h3&gt;
&lt;p&gt;Nowadays, there is a big wave of these CSS-In-JS-In-HTML-In-React-In-Vue-In-IOS-In-CSS-In-... approaches. People get upset with each other because of those styled-components vs. styled-system vs. styled-tailwind-my-head-is-bigger-than-yours arguments.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t like any of them, plain &lt;abbr title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;&#x2F;abbr&gt; is still king in my small street, but that doesn&#x27;t mean that I can&#x27;t try to add yet another styling approach to the mix. After all, this is such a pleasant hill to die at.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stylecontainer&quot;&gt;StyleContainer&lt;&#x2F;h3&gt;
&lt;p&gt;This new &lt;abbr title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;&#x2F;abbr&gt; framework is going to be made by just two classes. A container class and a class for the children.&lt;&#x2F;p&gt;
&lt;p&gt;The purpose of the children&#x27;s class will be to hold a bunch of CSS inline style parts. It starts by reading its &lt;code&gt;textContent&lt;&#x2F;code&gt; and place it as a style part of itself.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; StyleChild&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    parts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;parts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;textContent&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Initialize when added to a parent node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    connectedCallback&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the &lt;code&gt;StyleContainer&lt;&#x2F;code&gt;, I want it to read whatever children tag names it might have and create a new Web Component for each of those new tags.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; StyleContainer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; child&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; of&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;children&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;            const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; childName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; child&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tagName&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;toLocaleLowerCase&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Make the child become a new Web Component&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; if it was not yet made one. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;childName&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;                customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;childName&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; StyleChild&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Initialize when added to a parent node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    connectedCallback&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;What does this do?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It reads the children&#x27;s tag names (whatever they are) and turns them into a Web Component (provided they are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;html.spec.whatwg.org&#x2F;multipage&#x2F;custom-elements.html#valid-custom-element-name&quot;&gt;valid Web Component tag names&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Does it even work?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Yes! &lt;cite&gt;Because element definition can occur at any time, a non-custom element could be created, and then later become a custom element after an appropriate definition is registered. We call this process &quot;upgrading&quot; the element, from a normal element into a custom element.&lt;&#x2F;cite&gt; (says the spec)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;But I mean, what? Why? WTF?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Yeah, I don&#x27;t know, but it gets better.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;style-container-1&quot;&gt;&lt;code&gt;&amp;lt;style-container&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The above code allows HTML to be written with some sort of &lt;abbr title=&quot;HyperText Markup Language&quot;&gt;HTML&lt;&#x2F;abbr&gt; variable buckets.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Spank me&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style-container&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;super-border&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			border: 5px dashed mediumseagreen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			box-shadow: 0 0 0 3px;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;super-border&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;fancy-background&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			background: #563f0e;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;fancy-background&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;a-cool-font&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			font-family: Marcellus, serif;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			font-size: 3em;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			text-shadow: 0 2px #fff;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;a-cool-font&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style-container&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When the &lt;code&gt;StyleContainer&lt;&#x2F;code&gt; gets &lt;code&gt;define&lt;&#x2F;code&gt;d at the &lt;code&gt;customElements&lt;&#x2F;code&gt; registry (with the &lt;code&gt;&quot;style-container&quot;&lt;&#x2F;code&gt; tag name), the above code run its logic. It looks for the children and creates the tags &lt;code&gt;&amp;lt;super-border&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;fancy-background&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;lt;a-cool-font&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;These tag names can have the semantic value of a variable. &lt;abbr title=&quot;HyperText Markup Language&quot;&gt;HTML&lt;&#x2F;abbr&gt; variables. Or any other semantic value or purpose that might be fit. Anonymous classes create dynamic tag names, where you place whatever name you want in the HTML. After that, it is up to the intended implementation&#x2F;framework&#x2F;idea to give them meaning and flow.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;references-said-the-referee&quot;&gt;&quot;References&quot; said the referee&lt;&#x2F;h3&gt;
&lt;p&gt;The HTML code can then reference these dynamic tags.&lt;&#x2F;p&gt;
&lt;p&gt;They can be used to compose more complex styles. With a composer Web Component, lets say... the &lt;code&gt;&amp;lt;import-style&amp;gt;&lt;&#x2F;code&gt; Web Component (not yet defined):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Spank me&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style-container&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;magic-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;			&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;import-style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;super-border&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;import-style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;			&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;import-style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;fancy-background&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;import-style&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			padding: 2rem;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			text-transform: uppercase;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			pointer: cursor;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;magic-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;super-border&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			border: 5px dashed mediumseagreen;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			box-shadow: 0 0 0 3px;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;super-border&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;fancy-background&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			background: #563f0e;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;fancy-background&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;a-cool-font&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			font-family: Marcellus, serif;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			font-size: 3em;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			text-shadow: 0 2px #fff;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;a-cool-font&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;style-container&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or use the dynamic tags as plain references outside of the &lt;code&gt;&amp;lt;style-container&amp;gt;&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; styled-by&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;magic-button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Spank me&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;Where the &lt;code&gt;StyleContainer&lt;&#x2F;code&gt; would do something like:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;querySelectorAll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;[styled-by~=&amp;#39;magic-button&amp;#39;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And apply the contents of the &lt;code&gt;magic-button&lt;&#x2F;code&gt; tag to the inline &lt;code&gt;style&lt;&#x2F;code&gt; attribute to the nodes found.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;How does this differ from plain HTML?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It is another way to write it. Maybe it is better than placing &quot;id&quot;&#x27;s in common tags, perhaps it goes against the pure HTML semantic values, or perhaps it is just a shitty idea. I have no strong opinion. It is just an idea.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Couldn&#x27;t I just use CSS?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Yes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Why all of this, then?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know the answer to this. I like the approach of giving logic a declarative front. HTML is good at that. It is declarative and also dynamic through Web Components. How much logic should go into it, or what kind of logic is something that might be cool to find out. I do think &lt;abbr title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;&#x2F;abbr&gt; styles definitely should not :D (we already have the &lt;code&gt;class&lt;&#x2F;code&gt; attribute and CSS vars).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I presented a small example of using Web Components to create dynamic tag names. I think that having the possibility to declare a new tag name under a given parent and automatically create it can have some cool opportunities. I don&#x27;t know the extent of what can be possible or what this might entail, but still, it is something that we can do with Web Components and maybe use to break logic into easily identifiable small parts.&lt;&#x2F;p&gt;
&lt;hr&gt;
&lt;p&gt;This post is Part 2 of a series I am writting called &lt;cite&gt;&quot;The Life of a Web Component&quot;&lt;&#x2F;cite&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The other parts are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component&#x2F;&quot;&gt;Part 1 - Initialization&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-reverse-shadow-dom&#x2F;&quot;&gt;Part 3 - Reversing the Shadow DOM&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-state-in-shadow&#x2F;&quot;&gt;Part 4 - Declarative State&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-tests&#x2F;&quot;&gt;Part 5 - Get Tested&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Thank you!</title>
        <published>2021-01-27T00:00:00+00:00</published>
        <updated>2021-01-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/thank-you/"/>
        <id>https://hugodaniel.com/thank-you/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/thank-you/">&lt;p&gt;:)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;&quot;&gt;Go Home&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The life of a Web Component - Initialization</title>
        <published>2021-01-26T00:00:00+00:00</published>
        <updated>2021-01-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/the-life-of-a-web-component/"/>
        <id>https://hugodaniel.com/posts/the-life-of-a-web-component/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/the-life-of-a-web-component/">&lt;p&gt;I&#x27;ve been playing around with Web Components lately. They are quite an exciting thing with a vast range of use cases and possibilities. Web Components provide a very flexible API to explore non-standard approaches and Frankenstein contraptions. I know I will :)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Web_Components&quot;&gt;MDN has an excellent intro to Web Components&lt;&#x2F;a&gt;. It explains the three main parts of Web Components in some detail (custom tags, shadow root, and template slots). I recommend you start with MDN if you are looking to take your first steps into this tech.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;html5_components.png&quot; alt=&quot;Three HTML5 badges in a row. The first one has the normal orientation. The second one is upside down. The third one has a random orientation.&quot; title=&quot;They said it would be easy&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here is a quick explanation if, like me, you are coming from a text-book framework (react, vue, svelte, etc…) and have not done anything too serious with them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Web Components are JavaScript classes, and they work through Object-Oriented Programming by extending the known HTML tags (or more commonly the HTMLElement)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;You can define new HTML tags with Web Components by associating your component object class with a tag name. This happens by using the global &lt;code&gt;customElements.define(“blink-tag-never-dies”, class MakeItBlink extends HTMLElement {})&lt;&#x2F;code&gt; (creates the &lt;code&gt;&amp;lt;blink-tag-never-dies&amp;gt;&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;You can spray the HTML code with tags before they are defined. The browser is smart and can delay their display or progressively enhance them (if they extend a known element, like a button or something).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Web Components have their DOM root (called the &quot;shadow dom&quot;) that provides encapsulation for style and hierarchy.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Web Components can have multiple templates and multiple parts inside each template using the &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt; tag.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A class can only have a single tag associated with it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Their life-cycle methods are nuanced and happen at different stages than the common text-book frameworks typically present us with their components.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;just-being-alive&quot;&gt;Just being alive&lt;&#x2F;h2&gt;
&lt;p&gt;Here is a small subset of the life-cycle of a Web Component:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Component creation in memory.&lt;&#x2F;p&gt;
&lt;p&gt;The Web Component&#x27;s life starts here, where the &lt;code&gt;constructor()&lt;&#x2F;code&gt; of the class gets called. It happens once per instance&#x2F;tag occurrence and gets called instantly when a &lt;code&gt;document.createElement(&quot;&quot;)&lt;&#x2F;code&gt; is done for the custom tag defined for it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;An existing DOM element receives the component as a child.&lt;&#x2F;p&gt;
&lt;p&gt;Runs the Web Component &lt;code&gt;connectedCallback()&lt;&#x2F;code&gt; class method, which can occur multiple times during a Web Component life. Special attention is needed here because the &lt;code&gt;connectedCallback()&lt;&#x2F;code&gt; is triggered whenever &lt;code&gt;appendChild(myComponentInstance)&lt;&#x2F;code&gt; is called (even if it does not move the web component from its existing parent).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If the Web Component uses &lt;code&gt;&amp;lt;slot&amp;gt;&lt;&#x2F;code&gt; elements, they fire a &lt;code&gt;slotchange&lt;&#x2F;code&gt; event when they receive children or their hierarchy changes (which happens at least once after the &lt;code&gt;connectedCallback()&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;However, only hierarchy changes inside the slot trigger this event. Something more advanced is needed if you need a notification for changes on the textContent of a child.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After playing for a while with Web Components, here are some personal considerations about their initialization methods.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-super-constructor-does-nothing-at-all&quot;&gt;A super constructor does nothing at all.&lt;&#x2F;h2&gt;
&lt;p&gt;The Web Components spec is clear about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;html.spec.whatwg.org&#x2F;multipage&#x2F;custom-elements.html#custom-element-conformance&quot;&gt;what a &lt;code&gt;constructor()&lt;&#x2F;code&gt; can do&lt;&#x2F;a&gt;. The limitations are many and entirely optional. It is a guideline when they say, &lt;cite&gt;&quot;The element must not gain any attributes or children, as this violates the expectations of consumers who use the createElement or createElementNS methods.&quot;.&lt;&#x2F;cite&gt; It is entirely up to us to abide or not.&lt;&#x2F;p&gt;
&lt;p&gt;Since I&#x27;m not too fond of code and rules, I tend to skip adding a constructor in most of my Web Components. I ask myself: &quot;do I need an event listener? Can it be delegated elsewhere? Do I need shadow root encapsulation? What am I going to cook for dinner? If food were Web Components would it need to be constructed?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, delegating logic to the caller&#x2F;parent is the long-honored approach of the lazy dev. Moving some logic to the component or code above usually makes things easier to remove while keeping it more uncomplicated down the hierarchy.&lt;&#x2F;p&gt;
&lt;p&gt;In this regard, the basic Web Component creation template would be something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; ImAWebComponent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; no constructor()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s it, no constructor. No need to keep up with the Web Components spec rules and the browser will use the &lt;code&gt;HTMLElement&lt;&#x2F;code&gt; standard constructor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;all-these-notifications-keep-distracting-me&quot;&gt;All these notifications keep distracting me.&lt;&#x2F;h2&gt;
&lt;p&gt;Like the constructor approach above, it is better to keep the Web Component disconnected. That means that it is preferable to avoid using the &lt;code&gt;connectedCallback()&lt;&#x2F;code&gt; method when possible.&lt;&#x2F;p&gt;
&lt;p&gt;Why? Because this particular method can be called multiple times throughout the life of a Web Component. Should it be responsible for the initialization of the Web Component? What happens if the components move around after being already initialized? Can the component code handle being &quot;initialized&quot; multiple times on top of each other? Why is this Web Component alive? (why are we all?) Will it have fun during its life-time? Will this Web Component spend its life under its parent&#x27;s home?&lt;&#x2F;p&gt;
&lt;p&gt;For most autonomous Web Components I find it better to design them with no DOM attachment flow in mind. That means that the simple Web Component template remains the same:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; ImAWebComponent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; no constructor()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; no connectedCallback()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then use a life flow that I am more comfortable with, say something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; ImAWebComponent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; no constructor()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; no connectedCallback()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; some initialization logic here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;update&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; refresh stuff and keep things revised&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The idea here is to use whatever suits you better as the life-cycle-flow of your components. Web Components have a somewhat low-level API that molds quickly to the kinkiest desires. You can make them work closer to how you like to decompose problems or instead go wild and be creative.&lt;&#x2F;p&gt;
&lt;p&gt;You can avoid classes altogether and use a pure-functional approach that ultimately nails down to the Web Component class like some IO trash-can. Or keep using Object-Oriented Programming and spawn a vast forest of hierarchical extensions. Or use another language, why stick to JavaScript if Web Components are just HTML that can be executed by your favorite language WebView in a declarative way? All good, everything is possible here.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;addEventListener&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;load&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;querySelectorAll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;my-tag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;forEach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tag&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; tag&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Calling the &lt;code&gt;initialize()&lt;&#x2F;code&gt; or &lt;code&gt;update()&lt;&#x2F;code&gt; functions can then happen at any moment, controllable by the app. In a &lt;code&gt;render()&lt;&#x2F;code&gt; function? Once at the &quot;load&quot; event? How to use it will largely depend on what kind of component this is and its context.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;web-components-can-use-other-web-components&quot;&gt;Web Components can use other Web Components.&lt;&#x2F;h2&gt;
&lt;p&gt;As expected, a Web Component can use another Web Component. However, the browser is not always smart enough to delay its creation until the &lt;code&gt;customElements&lt;&#x2F;code&gt; global registry defines the tag for the Web Component that it depends.&lt;&#x2F;p&gt;
&lt;p&gt;A common approach is to use the &lt;code&gt;customElements.whenDefined(&quot;my-tag&quot;)&lt;&#x2F;code&gt;, which returns a Promise when the tag is defined. Put a bunch of these in a &lt;code&gt;Promise.all&lt;&#x2F;code&gt; array if the Web Component uses other Web Component tags inside it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; MyComponent&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  whenLoaded&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; Promise&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;whenDefined&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;dom-loop&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;whenDefined&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;redux-for-blink-tags&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  initialize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;whenLoaded&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Runs after the `whenLoaded` promise resolves&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above pattern guarantees that the &quot;dom-loop&quot; and &quot;redux-for-blink-tags&quot; are availabe inside the initialization promise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I am having fun playing with Web Components and believe that they provide a fertile ground for experimentation. This post is just a quick intro to a subset of their life-cycle methods and the provided functionality included in browsers that don&#x27;t need extra JS to exist. I will write about my further investigations with Web Components in the following days.&lt;&#x2F;p&gt;
&lt;hr&gt;
&lt;p&gt;This post is Part 1 of a series I am writting called &lt;cite&gt;&quot;The Life of a Web Component&quot;&lt;&#x2F;cite&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The other parts are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-as-var&#x2F;&quot;&gt;Part 2 - As a variable bucket&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-reverse-shadow-dom&#x2F;&quot;&gt;Part 3 - Reversing the Shadow DOM&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-state-in-shadow&#x2F;&quot;&gt;Part 4 - Declarative State&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;the-life-of-a-web-component-tests&#x2F;&quot;&gt;Part 5 - Get Tested&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introducing the &lt;deno&gt; tag</title>
        <published>2021-01-06T00:00:00+00:00</published>
        <updated>2021-01-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/introducing-deno-tag/"/>
        <id>https://hugodaniel.com/posts/introducing-deno-tag/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/introducing-deno-tag/">&lt;p&gt;Deno is gaining traction. A TypeScript runtime based on the Rust language and the V8 engine commonly associated with Node.js, or seen as the &quot;new Node.js&quot;. After trying it out, I feel that Deno is much more than that.&lt;&#x2F;p&gt;
&lt;p&gt;Deno is a new thing. A new thing that gets it right and manages to improve even the few parts that were already top-notch in Node.js&#x2F;JS.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;deno_deal_with_it.png&quot; alt=&quot;Deno with the pixel sunglasses from the &amp;quot;Deal With It&amp;quot; meme&quot; title=&quot;Deal with it&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-cool-is-deno&quot;&gt;How cool is Deno?&lt;&#x2F;h2&gt;
&lt;p&gt;Technicalities apart, the heart of Deno resides in the URL. It is how modules get referenced, and your work gets exposed to the world—giving you the flexibility to distribute it as you please (in your super-private VPN org, maybe?).&lt;&#x2F;p&gt;
&lt;p&gt;Having the URL as the core is a driving force for a few base design decisions.
Naming things as closely as possible to what they are is a very nice improvement to the already great JavaScript module system. No more extension assumptions when importing modules.&lt;&#x2F;p&gt;
&lt;p&gt;This means that &lt;code&gt;import Rabbit from &quot;magic&quot;&lt;&#x2F;code&gt; no longer works: where is &quot;magic&quot; located? is it a &lt;code&gt;.js&lt;&#x2F;code&gt; ? a &lt;code&gt;.ts&lt;&#x2F;code&gt;? a folder with a default &lt;code&gt;index.js&lt;&#x2F;code&gt; export? Some 3rd party &quot;package&quot; in your packages cache? Which version? or is it any other kind of file that your chosen bundler decides to import for you?&lt;&#x2F;p&gt;
&lt;p&gt;Deno also carefully shares a set of API&#x27;s with the browser, allowing lazy devs like me to compound the knowledge of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deno.land&#x2F;manual&#x2F;runtime&#x2F;web_platform_apis&quot;&gt;standard JavaScript browser API&#x27;s&lt;&#x2F;a&gt;, bringing it to places outside the browser.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deno.land&#x2F;manual@v1.6.3&#x2F;runtime&#x2F;permission_apis#permission-descriptors&quot;&gt;security model&lt;&#x2F;a&gt; granularity resembles the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;man.openbsd.org&#x2F;man2&#x2F;pledge.2&quot;&gt;OpenBSD pledge&lt;&#x2F;a&gt; approach. It forces the module execution into a restricted-service operating mode set by each permission specific flag and allowances. If your module tries to do something that was not whitelisted, it will throw an exception.&lt;&#x2F;p&gt;
&lt;p&gt;The Deno &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deno.land&#x2F;manual&#x2F;contributing&#x2F;style_guide&quot;&gt;style guide for contributors&lt;&#x2F;a&gt; is a great read and can serve as a base for the code style guide in companies that lack it. The included linter rules (&lt;code&gt;deno lint&lt;&#x2F;code&gt;) already do a great job at enforcing a part of these guidelines.&lt;&#x2F;p&gt;
&lt;p&gt;If you are now starting a new project or trying to refresh some old codebase, then Deno might give you that fresh edge that your project needs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deno-as-a-preprocessor-of-html&quot;&gt;Deno as a preprocessor of HTML&lt;&#x2F;h2&gt;
&lt;p&gt;One of the things that attracted me initially to Deno was that it includes with its single binary &lt;code&gt;deno&lt;&#x2F;code&gt; the ability to bundle dependencies and run tests. No more Webpack. No more Jest. Think of it as TypeScript with batteries included - btw, why doesn&#x27;t &lt;code&gt;tsc&lt;&#x2F;code&gt; resolve imports and outputs bundles? Because it&#x27;s a &quot;compiler&quot; and not a &quot;linker&quot;... yeah, whatever.&lt;&#x2F;p&gt;
&lt;p&gt;With Deno, I get in its single binary, a simple API, and a set of tools to use from the Command Line Interface.&lt;&#x2F;p&gt;
&lt;p&gt;Now, what if it would be possible to run Deno from within an HTML file?&lt;&#x2F;p&gt;
&lt;p&gt;Yes, like PHP but with Deno munching TypeScript.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;deno_spectrum.png&quot; alt=&quot;Deno logo next to the PHP logo with a rainbow heart in between&quot; title=&quot;Its a spectrum...&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nevermind-the-php-here-s-the-deno-tag&quot;&gt;Nevermind the &lt;code&gt;&amp;lt;?php&amp;gt;&lt;&#x2F;code&gt; here&#x27;s the &lt;code&gt;&amp;lt;deno&amp;gt;&lt;&#x2F;code&gt; tag&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;deno_tag&#x2F;&quot;&gt;deno_tag&lt;&#x2F;a&gt; is my first Deno module. I have been using it in the simple drawing web app I am building (Shape The Pixel).&lt;&#x2F;p&gt;
&lt;p&gt;The idea is that you can include a &lt;code&gt;&amp;lt;deno&amp;gt;&lt;&#x2F;code&gt; tag in your project&#x27;s HTML files and then preprocess them into regular HTML files.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;What does this new tag do?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It runs the &lt;code&gt;deno&lt;&#x2F;code&gt; command on the specified file and replaces the &lt;code&gt;&amp;lt;deno&amp;gt;&lt;&#x2F;code&gt; tag with its output.&lt;&#x2F;p&gt;
&lt;p&gt;Here is an example, suppose you have this file called &lt;code&gt;advanced_logic.ts&lt;&#x2F;code&gt; with this content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;typescript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;PHP is the best computer language ever invented!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just an example. The &lt;code&gt;&amp;lt;deno&amp;gt;&lt;&#x2F;code&gt; tag would transform something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Super Advanced Concepts Inc. Like Alien Magic Actually.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#DC322F, #DC322F);&quot;&gt;deno&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; run&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;advanced_logic.ts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Into this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Super Advanced Concepts Inc. Like Alien Magic Actually.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;PHP is the best computer language ever invented!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It runs something similar to &lt;code&gt;deno run advanced_logic.ts&lt;&#x2F;code&gt; and pipes the execution&#x27;s output directly into the location of the &lt;code&gt;&amp;lt;deno&amp;gt;&lt;&#x2F;code&gt; tags.&lt;&#x2F;p&gt;
&lt;p&gt;The tag can handle other attributes besides &lt;code&gt;run&lt;&#x2F;code&gt;. It can also bundle your modules with &lt;code&gt;&amp;lt;deno bundle=&quot;my_app.ts&quot; &#x2F;&amp;gt;&lt;&#x2F;code&gt;. Perfect for including within &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; tags and having the HTML file include a bundle of your code and its imports.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Super Advanced Concepts Inc. Like Alien Magic Actually.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deno&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; bundle&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;my_app.ts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just call the &lt;code&gt;deno_tag&lt;&#x2F;code&gt; CLI on your build scripts or release playbooks to have the HTML files ready to go.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-possibilities-are-endless&quot;&gt;The possibilities are endless&lt;&#x2F;h3&gt;
&lt;p&gt;Preprocess your static assets?
Bundle the SVG&#x27;s into a single string?
Call mom?
Ping the coffee machine?&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;deno&amp;gt;&lt;&#x2F;code&gt; tag is here for the rescue!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Why not use PHP?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I love PHP and use it whenever appropriate. It is my favorite backend language for the web. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.php.net&#x2F;manual&#x2F;en&#x2F;function.include.php&quot;&gt;PHP &quot;include&quot;&lt;&#x2F;a&gt; logic is great and resembles this somehow (&lt;code&gt;&amp;lt;?PHP include &quot;something.php&quot;; ?&amp;gt;&lt;&#x2F;code&gt;). However, I tend to like to work closer to front-end development, and keeping these HTML&#x2F;Web parts in TypeScript is the wave to surf these days 🏄‍♂️.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Why not use &#x2F;bin&#x2F;sh?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know why 🤷‍♂️.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;deno_tag&#x2F;&quot;&gt;&lt;code&gt;README.md&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; file in the deno_tag repository includes a couple more examples and a more detailed description of its parts. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;deno_tag&#x2F;&quot;&gt;Check it out&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is also available as a &lt;em&gt;deno.land&#x2F;x&lt;&#x2F;em&gt; third-party module &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deno.land&#x2F;x&#x2F;deno_tag&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;deno_tag_logo.png&quot; alt=&quot;Deno logo between two angle brackets&quot; title=&quot;deno_tag ftw!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Meet Evil Cliddy</title>
        <published>2020-12-21T00:00:00+00:00</published>
        <updated>2020-12-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/meet-evil-cliddy/"/>
        <id>https://hugodaniel.com/posts/meet-evil-cliddy/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/meet-evil-cliddy/">&lt;p&gt;Creating Cliddy has been a significant driver of my motivations and ideas. This simple character that will serve as the base for my next drawing app has been a source of fun in recent days.&lt;&#x2F;p&gt;
&lt;p&gt;It is a throwback to the days where virtual assistants were displayed with an avatar without &quot;skills&quot; or &quot;actions&quot; or whatever Siri now has. An agent to be used as a narrative controller of a story that I am not sure where will lead me.&lt;&#x2F;p&gt;
&lt;p&gt;The more I work on it, the more the idea of making &quot;products&quot; on top of real characters grows in me, up to the point where I am starting to believe that Cliddy can not only be the main central point of the whole UI, but also the focus and target of the entire project.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;clippy.png&quot; alt=&quot;Microsoft Clippy Assistant&quot; title=&quot;The pain.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Like Clippy, the old Microsoft Office assistant, my Cliddy is initially intended to be helpful, communicative, and an enhancer of what can be done with the tool being presented to the user. A natural bridge from the product owner&#x27;s mind into the product user interactions and intentions. Except &lt;a href=&quot;&#x2F;posts&#x2F;from-gridgenerator-to-shape-the-pixel&#x2F;&quot;&gt;&quot;Shape the Pixel&quot;&lt;&#x2F;a&gt; is not a product. It is meant to be tool with personality, a daydream of sorts with all its degrees of madness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-large-spectrum&quot;&gt;A large spectrum&lt;&#x2F;h2&gt;
&lt;p&gt;All app assistants are typically well-intended. Some are even sugar-coated to the extreme (&lt;em&gt;Hey Siri, how&#x27;s it going?&lt;&#x2F;em&gt;). Some are not that sugar-coated and prefer a more dehydrated, linter type list of suggestions that show up in some modal or sidebar to help or guide you. Regardless of the style of virtual-assistant, the well-intended part is a common assumption.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;what-if.png&quot; alt=&quot;A speech bubble with the text &amp;quot;What if?&amp;quot;&quot; title=&quot;What if?&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;But what if it isn&#x27;t? What if, in my case, Cliddy is instead an arrogant, pretentious prick? A real gem of an asshole? (like me, aha) What if Cliddy could be a nagging evil character that is just there to purposefully annoy and alienate you? Would you still use a product or a tool with such an agent? How would it &quot;assist&quot; if it is actively fighting against the user? (an assistant with a marked personality, like the Star Wars robots - yes, I am watching The Mandalorian).&lt;&#x2F;p&gt;
&lt;p&gt;Maybe when centering the UI of a tool around a character&#x2F;assistant, it can be possible to detach it from its attitude. What if the benefits of having an assistant are not so much about it being helpful but more about having an intermediary human-like presence in the UI? (an anthropomorphized UI element - even if it happens to be symbolically evil). Will the active presence of some agent on the UI by itself outweigh its direct helpfulness? Will it make the app more engaging and fun to use?
I don&#x27;t know the answers to these questions. I also don&#x27;t propose answering them formally, but I will explore them and create stuff that might serve as propositions to these hypotheses. Or not Ahah :D&lt;&#x2F;p&gt;
&lt;h2 id=&quot;meet-cliddy-evil-brother&quot;&gt;Meet Cliddy Evil Brother&lt;&#x2F;h2&gt;
&lt;p&gt;The eyes are slightly cut, and it can now speak (maybe in the future it will tell &quot;Yo Momma&quot; jokes 😂)&lt;&#x2F;p&gt;
&lt;div style=&quot;width: 100%; height: 350px; display: flex; justify-content: start;&quot;&gt;
    &lt;cliddy-mascot
      face=&quot;&gt;:)&quot;
      touched-face=&quot;&gt;:(&quot;
      data-body-color=&quot;#E31919&quot;
      data-shadow-color=&quot;#EDC741&quot;
    &gt;
      &lt;p slot=&quot;right&quot; style=&quot;font-weight: 500; font-family: -apple-system, BlinkMacSystemFont, sans-serif; font-size: 4rem; height: 128px; padding: 0; margin:0; margin-bottom: -19px;&quot;&gt;
        💩
      &lt;&#x2F;p&gt;
    &lt;&#x2F;cliddy-mascot&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;related-articles&quot;&gt;Related articles&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;posts&#x2F;from-gridgenerator-to-shape-the-pixel&#x2F;&quot;&gt;From Grid Generator to Shape The Pixel&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;127.0.0.1:1111&#x2F;posts&#x2F;cleaning-up-for-shape-the-pixel&#x2F;&quot;&gt;Cleaning up for Shape The Pixel&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Zen of index.html</title>
        <published>2020-12-15T00:00:00+00:00</published>
        <updated>2020-12-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/using-just-an-index-to-develop-a-web-app/"/>
        <id>https://hugodaniel.com/posts/using-just-an-index-to-develop-a-web-app/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/using-just-an-index-to-develop-a-web-app/">&lt;p&gt;Using an &lt;code&gt;index.html&lt;&#x2F;code&gt; as the single management file for the app.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;html5-hammer.png&quot; alt=&quot;HTML5 badge with a hammer, ready to do some damage&quot; title=&quot;That is one big hammer!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;It might work for small things, but I wouldn&#x27;t use it for something big.&quot;&lt;&#x2F;em&gt;
Said someone about something.&lt;&#x2F;p&gt;
&lt;p&gt;These are some of the things that an &lt;code&gt;index.html&lt;&#x2F;code&gt; typically does:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sets the title for the current page&lt;&#x2F;li&gt;
&lt;li&gt;Defines the content and assets&lt;&#x2F;li&gt;
&lt;li&gt;Defines content to be used as a template&lt;&#x2F;li&gt;
&lt;li&gt;Loads styles&lt;&#x2F;li&gt;
&lt;li&gt;Runs scripts and resolves modules dependencies&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Which are already quite good, but there are many more goodies to be found among the things that a simple &lt;code&gt;index.html&lt;&#x2F;code&gt; allows to do such as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Set a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;Manifest&quot;&gt;manifest file&lt;&#x2F;a&gt; for offline usage of the page items&lt;&#x2F;li&gt;
&lt;li&gt;Using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&quot;&gt;Web API&lt;&#x2F;a&gt;&#x27;s on the scripts (navigation, web components, 3d, audio, network access, etc...)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTML&#x2F;Preloading_content&quot;&gt;Preload&lt;&#x2F;a&gt; content and assets&lt;&#x2F;li&gt;
&lt;li&gt;Content &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Web_syndication&quot;&gt;syndication&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Social networks &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ogp.me&quot;&gt;meta information&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In fact, everything that any modern complex Web App does can be fit into a single &lt;code&gt;index.html&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;p&gt;It is mostly a matter of managing the complexity and growth of files, assets, components, etc...&lt;&#x2F;p&gt;
&lt;p&gt;We have developed a wide range of very complex tools to help us with that. Front-end development has become so complex that it is hard for any single person to master it.&lt;&#x2F;p&gt;
&lt;p&gt;How much harder would life be if a single &lt;code&gt;index.html&lt;&#x2F;code&gt; was used to drive all of the development instead of all those Create-React-App&#x2F;Babel&#x2F;WebPack&#x2F;npm&#x2F;yarn&#x2F;d&#x2F;sass&#x2F;styled-components&#x2F;optimizers?&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know how to answer this but will try to shed some light on a simpler, more &quot;naked&quot; approach for web app development.&lt;&#x2F;p&gt;
&lt;p&gt;To start &lt;strong&gt;there are at least two problems&lt;&#x2F;strong&gt; with using a single &lt;code&gt;index.html&lt;&#x2F;code&gt; as the only management file for the app:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No TypeScript support (or any other transpiler language, only JS, GLSL, and WebASM supported)&lt;&#x2F;li&gt;
&lt;li&gt;No way to easily manage 3rd party dependencies dependencies (dependencies)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These two will be the subject of my next post. For now, I am going to lay the ground for a simple &lt;code&gt;index.html&lt;&#x2F;code&gt;-only approach.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-common-structure-for-most-apps&quot;&gt;A common structure for most apps&lt;&#x2F;h2&gt;
&lt;p&gt;The common structure I plan to follow is something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Page meta &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;lt;link&amp;gt;&amp;#39;s go here after the meta stuff &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;lt;script type=&amp;quot;module&amp;quot;&amp;gt;&amp;#39;s go here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Feature flags as class strings in body &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Modals go here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; The content being shown goes here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;lt;template&amp;gt;&amp;#39;s go here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;lt;script&amp;gt;&amp;#39;s go here at the end &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This structure makes some compromises but overall is enough for most complex apps. It is not that different from a normal HTML page 🧐.&lt;&#x2F;p&gt;
&lt;p&gt;JavaScript modules are being loaded at the &lt;code&gt;&amp;lt;head&amp;gt;&lt;&#x2F;code&gt;, which is ok because module scripts are deferred by default and do not block the parsing of the rest of the document. They could go anywhere, I prefer to keep the &lt;code&gt;&amp;lt;body&amp;gt;&lt;&#x2F;code&gt; for the main logic and more immediate scripts.&lt;&#x2F;p&gt;
&lt;p&gt;With this in mind, here are 3 common things to a web app that can be done in such a simple structure without much effort:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Global loading state (full-screen loading)&lt;&#x2F;li&gt;
&lt;li&gt;Routing (what to show according to the URL being rendered)&lt;&#x2F;li&gt;
&lt;li&gt;Place common HTML parts&#x2F;assets without repeating them (templating&#x2F;components)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;global-loading-page&quot;&gt;Global Loading page&lt;&#x2F;h2&gt;
&lt;p&gt;A loading page that fills the whole screen is something that most web apps have, some even distract us with cool animations while loading.&lt;&#x2F;p&gt;
&lt;p&gt;In the above structure, the loading page goes into the modal area. Right before the &lt;code&gt;&amp;lt;main&amp;gt;&lt;&#x2F;code&gt; content. This allows heavy content like &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;img&amp;gt;&lt;&#x2F;code&gt; to be placed as &lt;code&gt;&amp;lt;main&amp;gt;&lt;&#x2F;code&gt; children and fully load (shaders, image data, etc) behind it, before clearing the loading state and showing them to our friends.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;loading&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Loading&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The whole visible space gets covered with that loading &lt;code&gt;&amp;lt;div&amp;gt;&lt;&#x2F;code&gt; which is then removed when all the things that the app needs for a good first run are ready.&lt;&#x2F;p&gt;
&lt;p&gt;Having the loading upfront on the &lt;code&gt;index.html&lt;&#x2F;code&gt; without needing any JS to first show it also helps our karma score in the bots&amp;amp;spiders purgatory that purge the web we all love into useful cinder blocks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;routing&quot;&gt;Routing&lt;&#x2F;h2&gt;
&lt;p&gt;No lib is going to be used for routing. Routing is going to consist of simple manipulations of the browser history with &lt;code&gt;popstate&lt;&#x2F;code&gt; and &lt;code&gt;pushstate&lt;&#x2F;code&gt;. The basic approach is:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Read the current route from the window location&lt;&#x2F;li&gt;
&lt;li&gt;Clone its corresponding &lt;code&gt;&amp;lt;template&amp;gt;&lt;&#x2F;code&gt; into the &lt;code&gt;&amp;lt;main&amp;gt;&lt;&#x2F;code&gt; tag&lt;&#x2F;li&gt;
&lt;li&gt;Inside it adjust the relevant &lt;code&gt;&amp;lt;a&amp;gt;&lt;&#x2F;code&gt;&#x27;s and other link navigation tags to perform a &lt;code&gt;pushState&lt;&#x2F;code&gt; instead of their default behavior
&lt;ul&gt;
&lt;li&gt;Filters can be applied to only consider &lt;code&gt;&amp;lt;a&amp;gt;&lt;&#x2F;code&gt;&#x27;s that have relative paths, or that do not have the &lt;code&gt;rel=nofollow&lt;&#x2F;code&gt; attribute&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;onpopstate&lt;&#x2F;code&gt; clone the correspnoding &lt;code&gt;&amp;lt;template&amp;gt;&lt;&#x2F;code&gt; into the &lt;code&gt;&amp;lt;main&amp;gt;&lt;&#x2F;code&gt; tag&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is intended only for web apps as an effort to reduce the amount of JS and leverage the features already at hand. For anything similar to regular pages the browser behavior is more than good enough, no need for JS there.&lt;&#x2F;p&gt;
&lt;p&gt;This approach should work well if the web app uses less than 20 or 15 possible routing patterns. Most web apps likely average at some number under 10. This simple approach should be more than enough. There is no need in my foreseeable use cases to use anything more complex like the DOM or any big library to manage routes.&lt;&#x2F;p&gt;
&lt;p&gt;I will evolve this into a very simple routing&#x2F;templating library to be announced soon(ish). For reference, here is some code that I did for a template engine in one of the many Grid iterations: &lt;a href=&quot;&#x2F;scripts&#x2F;meander.js&quot;&gt;old routing code&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I appreciate the browser&#x27;s approach of associating page state with history, however, for a web app I find it simpler and more manageable to keep these two things separate:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Routing seen as pure functions of navigation only transformations&lt;&#x2F;li&gt;
&lt;li&gt;App state in its own separate tarpit.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;html-templating&quot;&gt;HTML Templating&lt;&#x2F;h2&gt;
&lt;p&gt;Stamping and repeating a common HTML structure in a couple of places is a frequent routine that most web apps do. Be it for menu entries, list items, or even whole parts like sidebars or modal and toast elements. Finding a common HTML structure and repeat it when needed with small adjustments is a stapled practice.&lt;&#x2F;p&gt;
&lt;p&gt;HTML templating has many technicalities and possibilities. Most JS frameworks commonly solve it in their own way with different degrees of justifiable complexity.&lt;&#x2F;p&gt;
&lt;p&gt;Web browsers already provide a very flexible and complex way to do templating through the Web Components suite of technologies. For most of my cases plain HTML will be prefered and written directly at that &lt;code&gt;index.html&lt;&#x2F;code&gt;. For the other cases where DRY speaks louder a simple static &quot;copy&#x2F;paste&quot; tag will suffice, a small prototype of this could be something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;customElements&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;template-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; class&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#6C71C4, #6C71C4);&quot;&gt; HTMLElement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;  constructor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    super&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;attachShadow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; mode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;open&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;appendChild&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;            this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getAttribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;from-id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          )&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cloneNode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This small code defines a new WebComponent tag &lt;code&gt;&amp;lt;template-content&amp;gt;&lt;&#x2F;code&gt;, this tag reads an element id from its &lt;code&gt;from-id&lt;&#x2F;code&gt; attribute, then gets the corresponding element on the DOM for that id, clones it, and replaces itself with it.&lt;&#x2F;p&gt;
&lt;p&gt;This is useful because it provides a quick way to stamp HTML&#x2F;SVG content on the document. Helpful to replicate SVG elements, lists, and node sub-trees on the client-side.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nav&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; onclick&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;undo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; from-id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tools-button-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; from-id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tools-undo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; onclick&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tool&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;draw&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; from-id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tools-button-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;		&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; from-id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tools-draw&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;	&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nav&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tools-button-content&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Some complex content here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tools-draw&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Some other complex content here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;template&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Keeping a single &lt;code&gt;index.html&lt;&#x2F;code&gt; might be just enough for a simpler naked approach to app development. If there is no need for big dependencies, versioning tracking files, transpilers, and all that, this could very well be good enough. It works directly on top of what browsers already provide and hints at a simpler, leaner, style of development.&lt;&#x2F;p&gt;
&lt;p&gt;It does not have TypeScript support and it also does not automatically resolve dependencies and bundles them.&lt;&#x2F;p&gt;
&lt;p&gt;These are two open problems with this approach that I plan to show a possible solution that is on par in simplicity with this one. That will be the subject of my next technical post (likely to come out next week). Stay tuned.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Cleaning up for Shape The Pixel</title>
        <published>2020-12-11T00:00:00+00:00</published>
        <updated>2020-12-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/cleaning-up-for-shape-the-pixel/"/>
        <id>https://hugodaniel.com/posts/cleaning-up-for-shape-the-pixel/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/cleaning-up-for-shape-the-pixel/">&lt;p&gt;Moving from Grid Generator into the first version of &lt;em&gt;Shape The Pixel&lt;&#x2F;em&gt; is going to involve the effort of cleaning and pruning the parts that are slightly outside of its intended focus of drawing shapes.&lt;&#x2F;p&gt;
&lt;p&gt;This implies product changes that will propagate into technical decisions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-going-away&quot;&gt;What is going away?&lt;&#x2F;h2&gt;
&lt;p&gt;Things that were done in Grid Generator and that are going to be removed in &lt;em&gt;Shape The Pixel&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Login&#x2F;Register (Login with e-mail and social networks)&lt;&#x2F;li&gt;
&lt;li&gt;Payments (Payment logic and Braintree integration)&lt;&#x2F;li&gt;
&lt;li&gt;Business Logic (&quot;when to allow a customer to do what?&quot; - in &lt;em&gt;Shape The Pixel&lt;&#x2F;em&gt; there are no customers, the app always does everything)&lt;&#x2F;li&gt;
&lt;li&gt;Billing (Invoices and Chargebee integration)&lt;&#x2F;li&gt;
&lt;li&gt;Most UI components (all JSX is going away and it is going to be done with plain HTML and Web Components)&lt;&#x2F;li&gt;
&lt;li&gt;Developer dependencies (the Grid Generator frontend code only had two dependencies, both are going away: inferno and xxhashjs - others might come in)&lt;&#x2F;li&gt;
&lt;li&gt;Split repositories (db code, auth server code, video generator, and frontend code)&lt;&#x2F;li&gt;
&lt;li&gt;Most WebWorkers are going to be removed for the sake of simplicity&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-is-going-to-be-new&quot;&gt;What is going to be new?&lt;&#x2F;h2&gt;
&lt;p&gt;Things that are going to be new in &lt;em&gt;Shape The Pixel&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Cliddy (an assistant)&lt;&#x2F;li&gt;
&lt;li&gt;UI (redone and centered on Cliddy)&lt;&#x2F;li&gt;
&lt;li&gt;Shape&#x2F;Grid drawing mode (new UI with a new logic that sits closer to the creative process)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-more-things-change&quot;&gt;The more things change...&lt;&#x2F;h2&gt;
&lt;p&gt;Most things will remain the same, which means these will still work or will only carry small changes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Infinite grid&lt;&#x2F;li&gt;
&lt;li&gt;Shape - the customizable &quot;pixels&quot; editor&lt;&#x2F;li&gt;
&lt;li&gt;Replay your work&lt;&#x2F;li&gt;
&lt;li&gt;MP4 export&lt;&#x2F;li&gt;
&lt;li&gt;Share your work with a link&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;one-more-thing&quot;&gt;One more thing&lt;&#x2F;h2&gt;
&lt;p&gt;Also, expect a couple of surprises on top of these to be announced here on this blog. Alongside a couple of posts detailing some of these points a bit more.&lt;&#x2F;p&gt;
&lt;div style=&quot;width: 100%; display: flex; justify-content: center;&quot;&gt;
&lt;cliddy-mascot face=&quot;8)&quot; touched-face=&quot;8D&quot;&gt;&lt;&#x2F;cliddy-mascot&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This is part of a new approach to a drawing tool that is going to be called &lt;em&gt;Shape The Pixel&lt;&#x2F;em&gt;. Read more about its initial creation ideas &lt;a href=&quot;&#x2F;posts&#x2F;from-gridgenerator-to-shape-the-pixel&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;. Send me an e-mail if you liked what you read or have any questions&#x2F;suggestions 🤓&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>From Grid Generator to Shape The Pixel</title>
        <published>2020-12-04T00:00:00+00:00</published>
        <updated>2020-12-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/from-gridgenerator-to-shape-the-pixel/"/>
        <id>https://hugodaniel.com/posts/from-gridgenerator-to-shape-the-pixel/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/from-gridgenerator-to-shape-the-pixel/">&lt;p&gt;More than two years ago I was releasing my bootstrapped drawing application into the world, the &quot;Grid Generator&quot; web app. It was the labor of love and the search for a creative project where I could eventually dedicate a big part of my future life. However, a trip to the Web Summit in 2017 and countless books of lean&#x2F;market-first approaches were not enough to save it from its fate. It was not a product or service that the market wanted. This did not surprised me, but yet it still consumed a lot of my energy and was a point stronger than my personal project vision for the most part.&lt;&#x2F;p&gt;
&lt;p&gt;Circumstances have taken me to a path where I can work on the drawing app again. Now I am going to give it a twist and turn it into something different. Just for fun.&lt;&#x2F;p&gt;
&lt;p&gt;The main idea will be the same: a geometric drawing tool. The objective and approach however will be very different. This time the driver points for the app development are going to be:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Making something just for fun&lt;&#x2F;li&gt;
&lt;li&gt;No client, no customer, no target audience&lt;&#x2F;li&gt;
&lt;li&gt;Assume nobody will use it, make it just for the pleasure of making it&lt;&#x2F;li&gt;
&lt;li&gt;No pricing or market analysis - the purpose is to be fun&lt;&#x2F;li&gt;
&lt;li&gt;Has to be cool&lt;&#x2F;li&gt;
&lt;li&gt;Focus on a creative approach to a common problem&lt;&#x2F;li&gt;
&lt;li&gt;Do it for the love of the craft&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To top it the development is going to be done around a &lt;em&gt;mascot character&lt;&#x2F;em&gt;. This character will ultimately fulfill the role of an assistant (like Clippy but with personality). The app development and story are going to happen through it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;meet-cliddy&quot;&gt;Meet Cliddy&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Cliddy is a simple &lt;a href=&quot;&#x2F;scripts&#x2F;modules&#x2F;cliddy.mjs&quot;&gt;Web Component&lt;&#x2F;a&gt; made with:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cliddy-mascot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; face&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; touched-face&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div style=&quot;width: 100%; display: flex; justify-content: center;&quot;&gt;
&lt;cliddy-mascot face=&quot;:)&quot; touched-face=&quot;:D&quot;&gt;&lt;&#x2F;cliddy-mascot&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;It is time to Shape The Pixel.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>From Rust to Svelte, what tech stack will I use</title>
        <published>2020-06-07T00:00:00+00:00</published>
        <updated>2020-06-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/browser-tech-stack-2020/"/>
        <id>https://hugodaniel.com/posts/browser-tech-stack-2020/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/browser-tech-stack-2020/">&lt;p&gt;&lt;strong&gt;TL;DR&lt;&#x2F;strong&gt; Here is a template for your new web app project: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;svelte-template&quot;&gt;Svelte + TypeScript + Parcel + Rust&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The web is a big open platform that keeps evolving with the URL at its core.&lt;&#x2F;p&gt;
&lt;p&gt;We have a lot of tech and frameworks at our disposal to chose when starting a new web app in 2020.&lt;&#x2F;p&gt;
&lt;p&gt;There certainly is a lot of mud to crawl into, from an all-in vanilla JS approach up until an all-out React with a 100+ dependencies approach.&lt;&#x2F;p&gt;
&lt;p&gt;Among these there are a few cool things that strike my attention:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;svelte&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;svelte.dev&quot;&gt;Svelte&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Their component approach and state handling is fresh.&lt;&#x2F;p&gt;
&lt;p&gt;They lean towards using standards like CSS Variables and JS imports in an HTML first compiled approach.&lt;&#x2F;p&gt;
&lt;p&gt;The Svelte compiler outputs very lean JS code. Which comes in stark contrast with the current frontend bundle trends.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps in the future browsers will provide us higher-level components that can pack together HTML+JS+CSS in a way that is at least as elegant as Svelte does.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parcel&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;parceljs.org&quot;&gt;Parcel&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Most bundlers configuration is typically write-once and write-only. It is a pain to maintain and properly configure a bundle.&lt;&#x2F;p&gt;
&lt;p&gt;Parcel does it right by providing sane defaults that don&#x27;t need configuration upfront. (A bit like the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fishshell.com&#x2F;docs&#x2F;current&#x2F;design.html&quot;&gt;fish shell&lt;&#x2F;a&gt; )&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why is a bundler needed if Svelte already has a compiler ?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A bundler like Parcel provides the extra goodies of allowing us to import strange files directly in our &lt;code&gt;.svelte&lt;&#x2F;code&gt; components.&lt;&#x2F;p&gt;
&lt;p&gt;Stuff like TypeScript and even Rust become a breeze to work with.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps in the future bundlers won&#x27;t be needed. Perhaps even text files won&#x27;t be needed to code. Unfortunately we need them in our current state of things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;typescript&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&quot;&gt;TypeScript&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This language has been evolving fast. For now types are the way to go and TypeScript does a great job at typifying JavaScript and preventing those nasty null errors where you least expect(ed) them.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps in the future startups will again push towards dynamic languages as a way to bring faster products to market and the &quot;Move fast, break things&quot; will make sense again. But for now static is the way to go.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&quot;&gt;Rust&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Rust has a lot of good things. It appeals the front-end crowd as much as the backend people and the language is leveraging those windows of opportunity much better than any other language or community.&lt;&#x2F;p&gt;
&lt;p&gt;Wasm bindgen is a bliss of fresh air, it even works very well with TypeScript.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;webassembly&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webassembly.org&quot;&gt;WebAssembly&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is a total game changer for the next years. As a compile target it will allow near native performance and open the door for a lot of programming languages to be used on the web.&lt;&#x2F;p&gt;
&lt;p&gt;A new era of web apps is coming thanks to Web Assembly. It is hard to forsee what exactly will this be.&lt;&#x2F;p&gt;
&lt;p&gt;There are nevertheless a few cool extensions already being worked on for it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;WASI&quot;&gt;WASI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;simd&quot;&gt;128-bit SIMD&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;threads&quot;&gt;Threads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;reference-types&quot;&gt;Ref. Types&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;multi-value&quot;&gt;Multiple value returns and block parameters&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;webassembly&#x2F;bulk-memory-operations&quot;&gt;Bulk Memory Operations&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;nontrapping-float-to-int-conversions&quot;&gt;Non-trapping float-to-int convertions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;sign-extension-ops&quot;&gt;Sign-extension ops&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;exception-handling&quot;&gt;Exception handling&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;extended-name-section&quot;&gt;Extended name section&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;multi-memory&quot;&gt;Multi-memory&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WebAssembly&#x2F;gc&quot;&gt;Garbage Collection&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Web development is going to be a very different beast in a few moments in time. Lets enjoy the ride.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I have fetched some ideas from a few repos and forked them into a ready to use template you can start your projects with.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;svelte-template&quot;&gt;Check it out.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Keeping track of memory allocations in JS</title>
        <published>2018-07-06T00:00:00+00:00</published>
        <updated>2018-07-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/drafts/keeping-track-of-memory-allocations-in-js/"/>
        <id>https://hugodaniel.com/drafts/keeping-track-of-memory-allocations-in-js/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/drafts/keeping-track-of-memory-allocations-in-js/">&lt;p&gt;Memory is cheap. It is not uncommon for smartphones to carry 2GB or more to play around.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interact-to-allocate-new-memory&quot;&gt;Interact to allocate new memory&lt;&#x2F;h2&gt;
&lt;h2 id=&quot;animate-memory-allocations&quot;&gt;Animate memory allocations&lt;&#x2F;h2&gt;
&lt;h2 id=&quot;&quot;&gt;&lt;&#x2F;h2&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introducing Grid Generator Version 0</title>
        <published>2018-07-05T00:00:00+00:00</published>
        <updated>2018-07-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/grid-generator-v0/"/>
        <id>https://hugodaniel.com/posts/grid-generator-v0/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/grid-generator-v0/">&lt;p&gt;The purpose of this post is to introduce my personal project: Grid Generator. This is the first post about it since it went online on the 1st of July 2018.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-problem-does-it-solve&quot;&gt;What problem does it solve?&lt;&#x2F;h2&gt;
&lt;p&gt;I have always struggled with design tools. In particular those that came to see the light of the day during the 90&#x27;s (Adobe I am looking at you).&lt;&#x2F;p&gt;
&lt;p&gt;These design tools are clearly targeted at &quot;pros&quot; and &quot;specialists&quot; (like most of the computer &quot;stuff&quot; from&#x2F;during the 90&#x27;s). You are not expected to be able to work with them if you are not a specialist or if you did not take at least a course on these tools.&lt;&#x2F;p&gt;
&lt;p&gt;Being trained in software development made me look at the works produced by designers with wonder and amazement. I want to be able to at least produce geometric clean shapes that fit well together.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately making even simple shapes in the current design software offer is a daunting task for me.&lt;&#x2F;p&gt;
&lt;p&gt;That was my motivation behind Grid Generator: Create simple shapes, easily pick colors, and paint them in a grid, making patterns or more complex shapes.&lt;&#x2F;p&gt;
&lt;p&gt;I also wanted to bring time into play. Time is an important factor to consider and to work with in Grid Generator.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-to-expect&quot;&gt;What to expect?&lt;&#x2F;h2&gt;
&lt;p&gt;A square grid. In this version, and in the upcoming near versions, Grid Generator only supports a base square grid.&lt;&#x2F;p&gt;
&lt;p&gt;Think of it as pixel art with configurable pixels. Where your moves are being recorded.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;grid1.png&quot; alt=&quot;Simple house with squares, triangles, and a rounded square&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;grid2.png&quot; alt=&quot;The same with the grid hidden&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;shape-editor&quot;&gt;Shape editor&lt;&#x2F;h3&gt;
&lt;p&gt;In a square grid the base shape is the square. If you click on the &#x27;+&#x27; button bellow left, it opens the &quot;Shape Editor&quot;. Here you are presented with a grid made of lines and circles. This is where you customize your square. The intersections are automatically calculated to help you create your shapes. You as an artist&#x2F;designer only need to connect the dots and build your shape.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;shape_editor.png&quot; alt=&quot;Just connect the dots&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can pile many shapes on top of each other and change their colors.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;shape_editor_pile.png&quot; alt=&quot;Several sub-shapes on the same shape&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Time is an important aspect, you can go back to any previous state of your shapes and re-edit them from there.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;shape_editor_travel.png&quot; alt=&quot;Several sub-shapes on the same shape&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After your shape is created you can start painting with it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;shape_editor_paint.png&quot; alt=&quot;Paint your new shape on the main grid&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Or create other color variations of it on the &#x27;+&#x27; button to the right.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;shape_editor_colors.png&quot; alt=&quot;Create several color variations for your shape&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tile-patterns&quot;&gt;Tile Patterns&lt;&#x2F;h3&gt;
&lt;p&gt;I have asked in reddit about software to create tile patterns. A few answers came up but none quite filled my taste. I used this as a motivation to implement automatic tile patterns in Grid Generator.&lt;&#x2F;p&gt;
&lt;p&gt;In the menu just click on the &quot;pattern&quot; icon, and then on the &quot;grid&quot;. A blue frame shows up where you can paint inside and everything gets repeated outside.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;grid_pattern.png&quot; alt=&quot;The pattern frame&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can drag the corners of the blue frame to adjust your pattern to your drawing and create different patterns with white spaces.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;grid_pattern_tri.png&quot; alt=&quot;A triangular pattern&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;replay-your-art&quot;&gt;Replay your art&lt;&#x2F;h3&gt;
&lt;p&gt;After having created something cool you can publish it to share with your friends. Publishing an artwork makes it publicly available in its own page.&lt;&#x2F;p&gt;
&lt;p&gt;In there you will see a big &quot;play&quot; button that will replay your creative process until the final state is reached.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&#x2F;p&#x2F;13&quot;&gt;Check it out.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;remix-it&quot;&gt;Remix it&lt;&#x2F;h3&gt;
&lt;p&gt;You can pick any state of the art being replayed and remix your own version from there on. You can easily create your variations by clicking on the remix button (&quot;Change It&quot; on the bottom).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;remix_grid.png&quot; alt=&quot;Remix other works and create variations&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;export&quot;&gt;Export&lt;&#x2F;h3&gt;
&lt;p&gt;Exporting is currently the only paid feature of Grid Generator. My logic to make this a paid feature was that you can support the further development of this app if you are producing anything of value with it.&lt;&#x2F;p&gt;
&lt;p&gt;In the future I am planning to make this a free feature by adding other sources of revenue like instant product creations with your art (bags, t-shirts, etc...) and even selling packs of specially crafted grids.&lt;&#x2F;p&gt;
&lt;p&gt;After paying you can export your work as SVG. SVG is a vector format that is very prone to rounding errors and aliasing, so I also implemented exporting your works as high-res PNG&#x27;s that solve these issues.&lt;&#x2F;p&gt;
&lt;p&gt;Another possibility you have is to export your creative process as GIF or MP4, saving you the hard work of screen recording and editing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;upcoming-features&quot;&gt;Upcoming features&lt;&#x2F;h2&gt;
&lt;p&gt;The next version (v1) will mostly see UI&#x2F;UX improvements (imo those are critically needed) and some small features with these, like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Possibility to clear your shapes in the shape editor&lt;&#x2F;li&gt;
&lt;li&gt;Rough onboarding&lt;&#x2F;li&gt;
&lt;li&gt;Slightly better menus and pages&lt;&#x2F;li&gt;
&lt;li&gt;Facebook login&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After these I am planning some major stuff like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Stroke support in shapes&lt;&#x2F;li&gt;
&lt;li&gt;Background images in shapes&lt;&#x2F;li&gt;
&lt;li&gt;Layers&lt;&#x2F;li&gt;
&lt;li&gt;Color picker enhancements&lt;&#x2F;li&gt;
&lt;li&gt;Triangular grids and shapes&lt;&#x2F;li&gt;
&lt;li&gt;Custom base grid editor (create any kind of base grid)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Try it and if you feel inspired tell me which features you would like to see most.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;https:&#x2F;&#x2F;gridgenerator.com&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;In its current state Grid Generator is very raw. I did a lot of compromises to get here but the idea is very close to its initial inception in my head from a couple of years ago. Along the way I had the help and feedback of amazing people. I have some upcoming posts planned on them. They helped a lot of this feel way less lonely and in some points I think they believed more in it than me :)&lt;&#x2F;p&gt;
&lt;p&gt;Alas &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;gridgenerator&quot;&gt;everything is open source&lt;&#x2F;a&gt; and I am going to start using GitHub bells and whistles in its further development.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Eviction and Debt</title>
        <published>2018-07-04T00:00:00+00:00</published>
        <updated>2018-07-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/eviction-and-debt/"/>
        <id>https://hugodaniel.com/posts/eviction-and-debt/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/eviction-and-debt/">&lt;p&gt;The last 6 months?&lt;&#x2F;p&gt;
&lt;p&gt;Rents rising, IRS, grants and the version 0 of my personal project&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-lisbon-story-part-i-eviction&quot;&gt;A Lisbon Story (part I - eviction)&lt;&#x2F;h2&gt;
&lt;p&gt;Renting cycles have always happened. In certain cities you can even map whole migrations as they trend and landlords surf the wave of higher rent prices for at least the same level of preocupations.&lt;&#x2F;p&gt;
&lt;p&gt;Roughly 18 years ago I moved to Lisbon to study. For me it represented moving away from my village into the unknown. More than going to a big school where I did not know anyone. It was the city that drove my fears and desire to explore and know more. To wander and find new neighborhoods with different cultures and habits than mine.&lt;&#x2F;p&gt;
&lt;p&gt;Nowadays these neighborhoods still exist, but their inhabitants have mostly been evicted and moved to the outskirts. We branded this as &quot;gentrification&quot;. Gentlemen move to the place where you were previously living (notice that you are excluded from the gentlemen group by definition).&lt;&#x2F;p&gt;
&lt;p&gt;In Lisbon this did not happen softly. Most of my friends are now evicted. The red flags are everywhere.&lt;&#x2F;p&gt;
&lt;p&gt;My landlord sent me an SMS the other day. He said he wanted to speak to me about some important matters. I cannot think of anything good coming from a conversation with a landlord. He evicted me. Why charge &#x27;n&#x27; to normal people when you can charge gentlemen &#x27;n&#x27;*4? No problem, time for a change anyway.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-lisbon-story-part-ii-debt&quot;&gt;A Lisbon Story (part II - debt)&lt;&#x2F;h2&gt;
&lt;p&gt;The city has been a major part of my lifestyle for the last 18 years. I managed to reduce my cost of living to under €700&#x2F;month and still save a little. This was in no small part due to my rent. It might seem crazy but some neighbors of mine even manage to spend less through heroic frugal tactics.&lt;&#x2F;p&gt;
&lt;p&gt;With this I decided to collect my savings from the bank and dedicate full-time to develop a painting application that could help me and eventually others to do shapes and patterns like the ones from tiles.&lt;&#x2F;p&gt;
&lt;p&gt;Grid Generator has been a central part of my life since then.&lt;&#x2F;p&gt;
&lt;p&gt;Somewhere on my journey I managed to get a grant to work on it. With the obligation to build a company shortly after it finished. It has ended in May.&lt;&#x2F;p&gt;
&lt;p&gt;In an unrelated event to the eviction I got contacted by the IRS roughly on the same week that I got evicted. Because I was using my savings before I am old and&#x2F;or dying from a terminal disease it seems that I now have to pay them a cumulative 10% of some amount for each year that I saved.&lt;&#x2F;p&gt;
&lt;p&gt;After some calculations the IRS lady told me that the total I needed to pay them was more money than I had in my account. Fuck. I mean: FUCK. It is said that in Portugal you can owe money to a lot of people. Rich people. Banks. Mafia. Drug dealers. But you simply cannot owe money to the IRS. Ever. Dark stories are told about people who once owed them money.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Fortunately&quot; the Portuguese IRS shady tactics are so common that they allow you to pay in small parts and through some other weird mechanics that delay your entry into their shitlist.&lt;&#x2F;p&gt;
&lt;p&gt;The words of a friend that is into cryptocurrencies echoed in my mind: &lt;em&gt;&quot;The current economic system was not made to help you save money&quot;&lt;&#x2F;em&gt;. How I wish he was wrong.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;forward-momentum&quot;&gt;Forward momentum&lt;&#x2F;h2&gt;
&lt;p&gt;Grid Generator has been my testbed for a lot of strange experimentations and ideas. Not only in the approach to solve the problems it intends (shape editor, color picker, etc...) but specially in the code.&lt;&#x2F;p&gt;
&lt;p&gt;I have rewritten it completely from scratch some 4 times with varying degrees of (in)success. In its current state it is done with typescript and infernojs. While in its previous incarnations used react, vanilla js, immutable js and even did a quick stroll through purescript. It currently runs on top of DragonflyBSD.&lt;&#x2F;p&gt;
&lt;p&gt;The project is online and ready to use at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;https:&#x2F;&#x2F;gridgenerator.com&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I call it &quot;version 0&quot; as it lacks a lot of features (like onboarding) and has all that coder design&#x2F;UX that you hate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;To sum it up, I now have four major problems to solve:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Get money to pay the debt&lt;&#x2F;li&gt;
&lt;li&gt;Get a house to live&lt;&#x2F;li&gt;
&lt;li&gt;Build a company (with what money?)&lt;&#x2F;li&gt;
&lt;li&gt;Continue improving Grid Generator and start talking about it&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I am shifting some of the energy away from Grid Generator to focus it on the first two of these problems and see how it goes.&lt;&#x2F;p&gt;
&lt;p&gt;I am also going to invest into propaganda now and try to walk the thin line of project promotion and SPAM.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;PATTERN.png&quot; alt=&quot;A Pattern made with Grid Generator&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>WebSummit opening night. Sharing the stage with Paddy Cosgrave</title>
        <published>2017-11-06T00:00:00+00:00</published>
        <updated>2017-11-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/websummit-opening-night/"/>
        <id>https://hugodaniel.com/posts/websummit-opening-night/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/websummit-opening-night/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;abertura02.jpg&quot; alt=&quot;Paddy Cosgrave taking a selfie on the Center Stage during the opening night&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;WebSummit first day came with a mix of up and downs sprinkled with the duality of having the desire to scream with euphoria versus admiting that the event is nothing special to avoid stressing about it.&lt;&#x2F;p&gt;
&lt;p&gt;This week I was contacted by their team to go up on the main stage with some of the startups that were present in last week event with the President Marcelo Rebelo de Sousa. That gave me cold sweats even though I knew it was nothing special. The idea was just to go on stage when they called for us and be there representing our startup scene.&lt;&#x2F;p&gt;
&lt;p&gt;Early in the morning, I went to the venue with high hopes of doing my registration and never think about WebSummit until the main stage opening night thing. Unfortunately they told me that registration would only happen after 12h, which made me go back home to spend the rest of the day printing and cutting flyers and cards to hopefully distribute to people at the event.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;abertura05.jpg&quot; alt=&quot;Entrepreneurs in the opening night, on the left I didn&amp;#39;t get the contact, on the right is Dinara Rakhimbaeva of ExpoChat&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Later at night, I had the meeting point with the WebSummit team nearby the pavillion where the opening night was going to happen. They routed all of us through a tunnel that gave access to the spectators area of the pavillion. From the speakers that attended I really enjoyed Margrethe Vestager, the european comissioner for competition, she spoke about markets and taxes to tech companies. I also liked a lot of the speech that António Guterres gave, the former prime-minister of Portugal and now secretary-general of the United Nations who spoke about the biggest difficulty of our generation: climate change.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;abertura04.jpg&quot; alt=&quot;António Costa waiting to press the button&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The cerimony was closed with the current prime-minister of Portugal, António Costa, and the mayor of Lisbon, Fernando Medina, who both pressed in a button that made a lot of confettis cannons explode. Before that they invited the portuguese startups the stage, where I was included. I used the chance to take a few pictures and wave at Guterres and Margrethe when by chance they looked at me.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;abertura03.jpg&quot; alt=&quot;WebSummit starting&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Grid Generator First Stand</title>
        <published>2017-11-03T00:00:00+00:00</published>
        <updated>2017-11-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/gridgenerator-first-stand/"/>
        <id>https://hugodaniel.com/posts/gridgenerator-first-stand/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/gridgenerator-first-stand/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;beato1.jpg&quot; alt=&quot;Beato Creative Hub&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;About a month ago I was planning my WebSummit approach when I realized that I had never been to such an event. Much less have a stand of my project there.&lt;&#x2F;p&gt;
&lt;p&gt;That was when I started searching for opportunities to be at events. To train and prepare for the WebSummit.&lt;&#x2F;p&gt;
&lt;p&gt;Back then I got an invitation to participate in the first aniversary of StartUp Portugal, the portuguese state entity that acts upon the development of our entrepreneurial ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;My immediate decision was to say &quot;yes&quot; and use this oportunity to train the speach&#x2F;pitch&#x2F;posture in a faire stand.
The event took place in the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.startuplisboa.com&#x2F;hcb&quot;&gt;&quot;beato creative hub&quot;&lt;&#x2F;a&gt;, an old military industrial area that was abandoned for years until they decided to turn it into the next big thing in Lisbon.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;beato2.jpg&quot; alt=&quot;The bag reads &amp;quot;Military Maintenance&amp;quot;, as this was an old factory related to the portuguese military&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Access wise it is near the river, and although it has a nearby bike path, the entrance is on the inner side, making it difficult to get there on bike or on foot (cars tend to speed and the sidewalks are narrow in that area of the city). The surrounding neighborhood used to be neglected and poor, but now it is thriving with Lisboners looking for different places to hangout due to the tourist pressure present in past common areas of the city (bairro alto, cais do sodré, etc...).&lt;&#x2F;p&gt;
&lt;p&gt;That day (4th of October) I arrived a bit earlier than expected to setup my stand and after it I drank a beer to chill out while making my first contacts with the other stands as they arrived.&lt;&#x2F;p&gt;
&lt;p&gt;The whole thing was novelty to me, I was there with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;Grid Generator&lt;&#x2F;a&gt;, the bootstrapped project I&#x27;ve been working on, and things proceeded in three waves during the day:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wave-1-lots-of-people-in-suits&quot;&gt;Wave 1: Lots of people in suits&lt;&#x2F;h2&gt;
&lt;p&gt;After a while lots of people in suits showed up. Most of these were just walking around while keeping a safe distance from the stands. Enough not to get approached by any of us there standing.
Since I was there to take the most of it, I grabed a few flyers and actively went to them to talk about my amazing project.&lt;&#x2F;p&gt;
&lt;p&gt;To my shock they were not interested in listening to what I had to say. This was not even a problem with my pitch because they turned me down right after I showed up with a smile and said &quot;Hello, can I talk to you about my project ?&quot;. Maybe it is a problem with my face.&lt;&#x2F;p&gt;
&lt;p&gt;If they were not there for the startups and the people working on them then what were they there for ?&lt;&#x2F;p&gt;
&lt;p&gt;I decided to deal with it and move along. I guess negative reactions should be expected when going to these events with an active posture (seeking people to speak, instead of waiting for them to speak with you).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;me_beato.jpg&quot; alt=&quot;Me in my stand&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wave-2-nobody&quot;&gt;Wave 2: Nobody&lt;&#x2F;h2&gt;
&lt;p&gt;The event then had some talks. Unfortunately they were scheduled to happen in a different building than the one we were in. So suddenly everybody left and disappeared from sight. A few important politicians showed up to talk (I saw them at a glimpse) and we were left alone: should I leave my stand unattended ? I decided to stay and hold my ground just in case somebody showed up.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;talks_beato.jpg&quot; alt=&quot;Talks happening in another pavillion&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;During this time my motivation was going down and approaching a local minimum for that day. &lt;em&gt;&quot;I see... this is mostly a political event.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That was when I met Pedro from &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;othersigns.pt&#x2F;&quot;&gt;othersigns.pt&lt;&#x2F;a&gt;. He had decided to check out the projects while we were mostly empty. I pitched him when he interrupted and decided to criticise me about my pitch approach:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;Why are you talking about your project like it is targeted for the design industry ? I can clearly see it is not, yet you talk about it like it is&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We talked. One hour later he had convinced me to look at it from a different angle and try to push the real innovative things about my project and sell it as a design tool for non-designers. Something targeted for the creative crowd that needs to do some design but don&#x27;t know&#x2F;want to work with complex pro tools like the ones professional designers use.&lt;&#x2F;p&gt;
&lt;p&gt;Lots of different possibilities and approaches for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;Grid Generator&lt;&#x2F;a&gt; came into conversation. It was fun and made the event worthwhile.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wave-3-some-important-people&quot;&gt;Wave 3: Some important people&lt;&#x2F;h2&gt;
&lt;p&gt;After the talks ended in the other pavillion a hoard of scouts in suits approached our stands and told the people next to me, in an important tone, that they would have to speak with the secretary of state for the industry.
It happenened. She talked to them, took some photos, and promptly decided to ignore most of us in the other stands, talking only to a select few. The other politicians didn&#x27;t bother to show up.&lt;&#x2F;p&gt;
&lt;p&gt;Startups were apparently the boring part in this startup event. &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;meeting-the-president&#x2F;&quot;&gt;Marcelo Rebelo de Sousa, yesterday,&lt;&#x2F;a&gt; was kind enough to give voice to anyone who wanted to speak.&lt;&#x2F;p&gt;
&lt;p&gt;After this I went out. Grabbed a slice of the aniversary cake that they were eating outside (even the cake was outside the stands area), and had another beer while meditating on what had happened. After this I left to dance &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9DYElqcREXc&quot;&gt;Kizomba&lt;&#x2F;a&gt; in another part of the city.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I decided to participate in this event in order to train for our WebSummit stand. Overall it was a fun experience albeit the first of its kind I had. I am not sure I would want to repeat it again if given the chance.&lt;&#x2F;p&gt;
&lt;p&gt;It definetely helped me learn a few things about being in a stand and craft a more prepared approach for the bigger event that is the WebSummit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;aniv1.jpg&quot; alt=&quot;Me at the first aniversay of StarUp Portugal, shortly after the event ended&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here is a quick list of things this helped me learn about being in a stand, some of these are pretty obvious but still worth to keep in mind:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Take an active approach (approach and talk to people). I talked to more people than any of the other stands there.&lt;&#x2F;li&gt;
&lt;li&gt;Don&#x27;t grudge if people don&#x27;t want to talk to you (it is normal)&lt;&#x2F;li&gt;
&lt;li&gt;Your product demo is not the most important part. People will not get to it if your pitch is not convincing.&lt;&#x2F;li&gt;
&lt;li&gt;Don&#x27;t focus on pitching features. Pitch a story instead. It grabs attention better.&lt;&#x2F;li&gt;
&lt;li&gt;Keep a log of e-mails and reach them a few days later (ask people for their e-mails and not the other way around: don&#x27;t give your e-mail expecting to be contacted: you won&#x27;t be).&lt;&#x2F;li&gt;
&lt;li&gt;Eye-candy is important, the stands with the better visual looks got most of the attention.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Hope this helps and see you at the WebSummit next week &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;lisbon-as-an-inspiration-for-my-project&#x2F;&quot;&gt;in Lisbon&lt;&#x2F;a&gt;, also take a look at some cool &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;where-do-local-hackers-eat-in-lisbon&#x2F;&quot;&gt;places to eat in the touristic area of Lisbon&lt;&#x2F;a&gt; :)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Meeting the President</title>
        <published>2017-11-02T00:00:00+00:00</published>
        <updated>2017-11-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/meeting-the-president/"/>
        <id>https://hugodaniel.com/posts/meeting-the-president/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/meeting-the-president/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;inside_coches2.jpg&quot; alt=&quot;He talked to us in the old coach museum&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A few days ago I got an e-mail from the presidency inviting me to go to an event with the president of Portugal, Marcelo Rebelo de Sousa. This came within the WebSummit context, he wanted to be personally with some of the portuguese startups that are going to attend the WebSummit next week.&lt;&#x2F;p&gt;
&lt;p&gt;This event would take place in the old National Coach Museum in the near future: today.&lt;&#x2F;p&gt;
&lt;p&gt;I guess that I got it because of my participation on the &quot;Road2WebSummit&quot; series of events that I was selected to be part of. Road2WebSummit is focused in coaching (pun intended) startups so they can be well prepared for the WebSummit. It tries to fill the gap of our lack of an official &quot;entrepreneur&quot; culture, although we do have a lot of background at being unofficially entrepreneurs as it comes attached to being a poor country in a rich continent. Now we just need to know how to capitalize on that and channel it through proper &quot;startupian&quot; gymnastics.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;coches.jpg&quot; alt=&quot;The entrance&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The invitation added that the dresscode was a &quot;dark suit&quot;. That was a problem for me since I don&#x27;t have any suits and did not intend to buy or loan one. I decided to dress somewhat nicely with what I had around without leaning too much towards informality.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;suits.jpg&quot; alt=&quot;Suits everywhere&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Almost everyone suited-up for the event, which let me feeling a bit out of place initially, but that all went away once inside.&lt;&#x2F;p&gt;
&lt;p&gt;The museum is amazing! I had never been there and kind of regret it since they moved to the new &quot;modern&quot; place next door and closed this one (now labeled the &quot;old&quot; one).&lt;&#x2F;p&gt;
&lt;p&gt;There was still some old coaches around and the ceiling decoration is still beautiful as people always told me it was. At the end they placed chairs for everyone to sit for the speech.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;inside_coches.jpg&quot; alt=&quot;The entrance&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The president arrived after a few minutes. He talked for a small bit, introduced the economy minister and the websummit people. He is known for his improvisation skills and for the hability to charismatically make quick decisions. After all the personalities had spoken he then passed the word to the startups. Whoever wanted to speak could introduce themselves and their company&#x2F;ideia to everyone else.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the video of his speech (he translates from portuguese to english as he goes).&lt;&#x2F;p&gt;
&lt;video src=&quot;http:&#x2F;&#x2F;media.presidencia.pt&#x2F;videos&#x2F;mrs2017&#x2F;PRMRS_171102_V01_FHD.mp4&quot; width=&quot;100%&quot; controls &#x2F;&gt;
&lt;p&gt;About 90 people talked. That was the number they said, personally I did not count and unfortunately after a while my brain was not able to process any more &quot;ideas&quot; or startup names. I was spilling buzzwords through my ears. I think the winner buzzwords were &quot;AI&quot;, &quot;Machine Learning&quot;, &quot;Disruptive&quot;, &quot;App&quot;, &quot;Intelligent&quot;, &quot;Deep learning&quot;, &quot;3D Printer&quot; and some others I can&#x27;t recall.&lt;&#x2F;p&gt;
&lt;p&gt;Near the end we took a group picture, and before everyone left they gave some drinks and &lt;em&gt;pasteis de belém&lt;&#x2F;em&gt; while Marcelo was being invaded by people taking selfies with him.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;marcelo2.png&quot; alt=&quot;Me, the guy with no suit near the camers, with a blue circle. Marcelo, the president, at front with a red circle&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Overall it was a fun event I even met an ex-teacher from my university that is now trying to work out an idea to increase bike usage in Lisbon.&lt;&#x2F;p&gt;
&lt;p&gt;I hope another opportunity like this happens soon, maybe then I can also take a selfie with the Prez. :D&lt;&#x2F;p&gt;
&lt;p&gt;Meanwhile checkout how &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;first-funding-as-a-bootstrapper-in-portugal&#x2F;&quot;&gt;I got to participate&lt;&#x2F;a&gt; in the StartUp Portugal events. If you are here for the WebSummit don&#x27;t be fooled and &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;where-do-local-hackers-eat-in-lisbon&#x2F;&quot;&gt;read my recommendations for places to eat&lt;&#x2F;a&gt; in the touristic area.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Where do local hackers eat in Lisbon</title>
        <published>2017-11-01T00:00:00+00:00</published>
        <updated>2017-11-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/where-do-local-hackers-eat-in-lisbon/"/>
        <id>https://hugodaniel.com/posts/where-do-local-hackers-eat-in-lisbon/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/where-do-local-hackers-eat-in-lisbon/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;kid.jpg&quot; alt=&quot;Picture of a kid in the dark looking for a friend to pass the ball while playing football&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t know where hackers (as in infosec wizards) eat in Lisbon. We do have a strong background of using things beyond their intended purpose (we call it &quot;desenrascanço&quot; and it is a basic trait of being born in the culture that has sprung here for centuries).&lt;&#x2F;p&gt;
&lt;p&gt;As is this post is intended for tourists looking for a typical experience.&lt;&#x2F;p&gt;
&lt;p&gt;If you are visiting Lisbon chances are that you will spend your time around the most touristic areas of the city. In this post I want to share with you some places and dishes that we love and are generally ignored by tourists. I don&#x27;t pretend to be Anthony Bourdain or any of those youtubers that don&#x27;t respect what they are eating and only go to fancy restaurants to say in the end that it is cheap and good.
Don&#x27;t fall for that. Be a proper tourist and avoid the &quot;Torre de Belem snowball&quot; at all costs. I have only seen snow 2 times in my life and it was not in Lisbon :D&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;belem_snowball.jpg&quot; alt=&quot;Snowing in Lisbon?&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In Portugal we always seat to have lunch and dinner. We don&#x27;t eat walking. Traditionally everyone takes at least an hour to have lunch. It is kind of a big deal. People here are very proud of their food. There are many categories of places to eat but locals range them between &quot;fancy restaurant&quot; and &quot;fast-food joint&quot;. Somewhere between these two lies our honorable &lt;em&gt;&quot;tasca&quot;&lt;&#x2F;em&gt; (tavern &amp;lt;= &lt;em&gt;tasca&lt;&#x2F;em&gt; &amp;lt;= simple restaurant). A glorified tavern with a very peculiar set of skills, namely: very good and inexpensive local food.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-to-expect&quot;&gt;What to expect&lt;&#x2F;h2&gt;
&lt;p&gt;In a &lt;em&gt;tasca&lt;&#x2F;em&gt; you can expect at least the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No cameras looking over you, the balcony or the employers * Never trust a business that tracks you and&#x2F;or doesn&#x27;t trust their own people&lt;&#x2F;li&gt;
&lt;li&gt;Open kitchen * Take a peek through the open window inside the kitchen and say hi to the cook&lt;&#x2F;li&gt;
&lt;li&gt;Freshly peeled hand-cut fried potatos * For your pleasure&lt;&#x2F;li&gt;
&lt;li&gt;Pressured wine * We split wine into two major groups: white&#x2F;red and then inside this group mature&#x2F;green (or is it the other way around?). Try them all! :)&lt;&#x2F;li&gt;
&lt;li&gt;A balcony if you are just warming your stomach * Yes, we sometimes eat standing at the balcony if it is something really fast&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;in-the-heart-of-lisbon&quot;&gt;In the heart of Lisbon&lt;&#x2F;h2&gt;
&lt;p&gt;Here are 4 &lt;em&gt;tascas&lt;&#x2F;em&gt; that I can think from the top of my head and which I recommend in the touristic area of the city. Don&#x27;t expect to see &quot;hackers&quot; as in computer wizards in them but typical portuguese folks eating. Chose the one near you when you get hungry.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.google.pt&#x2F;maps&#x2F;place&#x2F;Casa+Das+Bifanas&#x2F;@38.7141819,-9.1400812,17z&#x2F;data=!3m1!4b1!4m5!3m4!1s0xd1933877a14a101:0x58658df29b0791b0!8m2!3d38.7141769!4d-9.1378849&quot;&gt;&quot;Casa das Bifanas&quot; in Rossio&lt;&#x2F;a&gt; - &lt;img src=&quot;&#x2F;images&#x2F;bifanas.jpg&quot; alt=&quot;Formely known as &amp;quot;The king of Bifanas&amp;quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.google.pt&#x2F;maps&#x2F;place&#x2F;Popular+Do+Capelo&#x2F;@38.7098328,-9.1408684,20z&#x2F;data=!4m12!1m6!3m5!1s0xd1933877a14a101:0x58658df29b0791b0!2sCasa+Das+Bifanas!8m2!3d38.7141769!4d-9.1378849!3m4!1s0xd19347ecf1cf809:0xb3685b3298796599!8m2!3d38.7097915!4d-9.1406129&quot;&gt;&quot;Popular do Capelo&quot; in Chiado&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.google.pt&#x2F;maps&#x2F;place&#x2F;O+Trevo&#x2F;@38.7116017,-9.1461413,17z&#x2F;data=!4m5!3m4!1s0xd19347fa8fe09bd:0xd6fe73efee2fb6fc!8m2!3d38.710865!4d-9.1430943&quot;&gt;&quot;O Trevo&quot; in Pc. Camoes&lt;&#x2F;a&gt; - &lt;img src=&quot;&#x2F;images&#x2F;otrevo1.jpg&quot; alt=&quot;O trevo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.google.pt&#x2F;maps&#x2F;place&#x2F;A+Parreirinha+Do+Rato&#x2F;@38.719569,-9.154936,19z&#x2F;data=!4m12!1m6!3m5!1s0xd19347fa8fe09bd:0xd6fe73efee2fb6fc!2sO+Trevo!8m2!3d38.710865!4d-9.1430943!3m4!1s0xd19337b1c2560f7:0x10c06dc141131fd5!8m2!3d38.7196609!4d-9.1548474&quot;&gt;&quot;A Parreirinha do Rato&quot; in Rato&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;things-to-keep-in-mind&quot;&gt;Things to keep in mind&lt;&#x2F;h3&gt;
&lt;p&gt;The main reason you step inside a &lt;em&gt;tasca&lt;&#x2F;em&gt; is the food. The second main reason is also the food. The list of reasons is long and every item of the list is food.
At the end of the list, down in the footer in a small font are lots of little details that you happen to notice when you are a regular client. These details are infinite and a new one pops out every time you step inside a &lt;em&gt;tasca&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;During lunch hour these are very busy places. The waiters are typically running and rushing while being seriously professional. They are in a no-bullshit mode, they know you want to eat and they know you will love the food.&lt;&#x2F;p&gt;
&lt;p&gt;The kitchen can close outside of eating hours and only small meals are served.&lt;&#x2F;p&gt;
&lt;p&gt;They are somewhat noisy and you can expect to see people screaming if there is a football match going on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-to-eat&quot;&gt;What to eat&lt;&#x2F;h3&gt;
&lt;p&gt;Dishes are more or less the same in most &lt;em&gt;tascas&lt;&#x2F;em&gt;. Try these.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Starter&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Croquete (meat roll)&lt;&#x2F;li&gt;
&lt;li&gt;Chamuça (triangle with curry chicken)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Soup&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Caldo Verde (kale soup)&lt;&#x2F;li&gt;
&lt;li&gt;Sopa de legumes (vegetables soup)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Fish&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Polvo à lagareiro (octopus with olive oil)&lt;&#x2F;li&gt;
&lt;li&gt;Peixe espada (swordfish)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Meat&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Secretos de porco (pork)&lt;&#x2F;li&gt;
&lt;li&gt;Bife à casa (steak)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Drink&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Beer&lt;&#x2F;li&gt;
&lt;li&gt;Jar of wine (ask for the pressured white wine if you want the full experience)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Dessert&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Arroz doce (sweet rice)&lt;&#x2F;li&gt;
&lt;li&gt;Café (ask for an extra &lt;em&gt;bagaço&lt;&#x2F;em&gt; if you want the full experience) * &lt;img src=&quot;&#x2F;images&#x2F;bagaco.jpg&quot; alt=&quot;Café and bagaço&quot; &#x2F;&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you just want a snack or something other than a full-meal, then try out our &quot;Bifana&quot;. A steak sandwich. Goes well with beer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;intro-to-portuguese-pastery&quot;&gt;Intro to Portuguese pastery&lt;&#x2F;h2&gt;
&lt;p&gt;Our pastery is a bit different from the european cakes (because we never saw ourselves as a part of europe until +-40 years ago).
We have mostly french influences and also things from all over the world but to keep it short you can generally find fresh original cakes mostly made with sweet egg yolk. We put egg yolk in most of our cake recipes. I have heard several explanations for this, the most convincing one for me is that in convents nuns used the egg light to iron and starch the church clothes, then to avoid wasting the yolk they invented all of these different cakes that you can see in most cafes.&lt;&#x2F;p&gt;
&lt;p&gt;Our pastery shifts radically in some seasons, we have a whole range of cakes and snacks that are only done in christmas and some in easter.&lt;&#x2F;p&gt;
&lt;p&gt;You can find some brazillian pastery, which are heavy in condensed milk (sugar + milk cooked under pressure) and some variations of these with our traditional egg yolk. Just try whatever pops your eye :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Explore Lisbon, it has many secrets and hidden gems. Our ways might seem a bit strange, clumsy and hard to get into at first, but peeking through the sweet spots can reveal a humble, seasoned and balanced culture (with earned scars of fighting hard against slavery, discrimination, inequality and dictatorship&#x2F;power surges). If you are here next week for the WebSummit lets hang out and have a drink :) &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;about&#x2F;&quot;&gt;Here is my contact at the bottom&lt;&#x2F;a&gt;. Take a look at why I think &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;lisbon-as-an-inspiration-for-my-project&#x2F;&quot;&gt;Lisbon is an inspiration&lt;&#x2F;a&gt; for my project.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My first funding as a bootstrapper in Portugal</title>
        <published>2017-10-31T00:00:00+00:00</published>
        <updated>2017-10-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/first-funding-as-a-bootstrapper-in-portugal/"/>
        <id>https://hugodaniel.com/posts/first-funding-as-a-bootstrapper-in-portugal/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/first-funding-as-a-bootstrapper-in-portugal/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;startupvoucher.jpg&quot; alt=&quot;StartUp Voucher ad, it reads: &amp;quot;What if your idea could turn into a company ?&amp;quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In April 2016 I quit from the startup I was working to finally do a personal project. Back then the questions everyone asked me were mostly about money &lt;em&gt;&quot;How are you going to live ?&quot;&lt;&#x2F;em&gt;.
Even though rent prices in Lisbon have been skyrocketing due to tourism increase and the coming of WebSummit I always had a frugal economical lifestyle. I don&#x27;t have loans, I don&#x27;t have &quot;luxuries&quot; and I can keep my monthly spendings to what some people view as an heroically low value.
Looking back it was somewhat natural that when a set of conditions met I thought: &quot;it&#x27;s now or never&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;I spent some months wondering about what kind of project to do. I knew I wanted something ambitious but I got easily lost in the objectives and purpose of the project. With time I realized that the money I had saved was not going to allow me to survive long enough to do a first version of the product and release it in the market.
That made me start looking around for investment, preferably some that did not imply selling part of the company (lost fund). That was when I found about StartUp Voucher.&lt;&#x2F;p&gt;
&lt;p&gt;Very briefly, StartUp Voucher is a community fund from the European Union that is run by the Portuguese Gov. with the purpose of helping out companies in &quot;idea stage&quot;. Pragmatically this means I get 690EUR&#x2F;month for 12 months plus the help of an incubator and a mentor.&lt;&#x2F;p&gt;
&lt;p&gt;This funding is particularly targeted for ideas outside of the most developed areas of the country. In spite of currently living in Lisbon I was born and raised in Alenquer, where my family still resides. To apply for this fund I made the headquarters of my project there, a place I love and visit on a weekly basis.&lt;&#x2F;p&gt;
&lt;p&gt;To further enhance my application I read through the whole 100 page &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.portugal2020.pt&#x2F;Portal2020&#x2F;Media&#x2F;Default&#x2F;Docs&#x2F;EstrategiasEInteligente&#x2F;EREI%20Centro.pdf&quot;&gt;&quot;Research and Innovation Strategies for Smart Specialisation&quot; report (RIS3)&lt;&#x2F;a&gt; for my region. That report made me notice that a software tool for grid based drawings could have a lot of impact in several practical applications for the exporting industries in the Center of Portugal. Like ceramics, textiles and creative industries.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gridgenerator.com&#x2F;img&#x2F;logo&#x2F;grid_generator_logo.png&quot; alt=&quot;The logo&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When Lisbon was boiling with WebSummit 2016 I was working full-time to apply to this fund. It took me a few weeks and in December I finally finished the application and sent it. After a some months I got the news that my project was one of the 245 chosen to be on the StartUp Voucher. Since around May 2017 that I have been getting 690EUR each month and working in full force on this project.&lt;&#x2F;p&gt;
&lt;p&gt;During this time I have been using their support to fine-tune the project in many ways and prepare myself for the first steps on the market. WebSummit is also being promoted by the StartUp Voucher who encourages all tech startups to try to attend.&lt;&#x2F;p&gt;
&lt;p&gt;Right now I have a working demo that have been using with some friends and potential users and I am planning to start looking for partnerships in early 2018.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;why-i-decided-to-go-to-the-websummit&#x2F;&quot;&gt;In this link&lt;&#x2F;a&gt; I explain why I decided to go to the WebSummit this year.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How useful is the JavaScript Set</title>
        <published>2017-10-25T00:00:00+00:00</published>
        <updated>2017-10-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/how-useful-is-the-javascript-set/"/>
        <id>https://hugodaniel.com/posts/how-useful-is-the-javascript-set/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/how-useful-is-the-javascript-set/">&lt;p&gt;In most languages Set&#x27;s have a clear strong use case: fast union, intersection and difference operations; unfortunately in JavaScript these operations are not readily defined so as an exercise I am going to raise some questions and try to answer them in this post.&lt;&#x2F;p&gt;
&lt;p&gt;All code is run on Firefox Developer Edition 57.0b11 (64-bit) in macOS.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;initialization&quot;&gt;Initialization&lt;&#x2F;h2&gt;
&lt;p&gt;Most of this post will be used to compare &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Set&quot;&gt;Set()&lt;&#x2F;a&gt; with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Array&quot;&gt;Array()&lt;&#x2F;a&gt; for some common operations. To initialize a Set() I will be constructing it with an Array.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; set1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;has&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Set [ 1, 2, 3, 4, 5, 6 ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;uniqueness&quot;&gt;Uniqueness&lt;&#x2F;h2&gt;
&lt;p&gt;Without the common set operations defined the JavaScript Set() can be seen as a glorified container that only stores unique elements. When you put a repeated element it actually replaces the existing one.&lt;&#x2F;p&gt;
&lt;p&gt;This is quite useful for primitive values.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Set [ 1, 2, 3, 4, 5, 6 ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unlike Arrays the value will not be repeated when you add it to a Set.&lt;&#x2F;p&gt;
&lt;p&gt;For object values this is not that simple as Set uses references for those values;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; set2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; obj1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;obj1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Set [{ value: 1}, { value: 2}, { value: 2 }]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The reference is used as the key in the Set, if we change &lt;code&gt;obj1.value&lt;&#x2F;code&gt; above to something else and add it to the Set, JavaScript will see it as a repeated element and replace the existing reference in the Set.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;obj1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;foo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;obj1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; obj1 is already in the set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Set [{ value: 1}, { value: 2}, { value: &amp;quot;foo&amp;quot; }]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now just to compare with Arrays, here is a naive implementation to create an array with n values and then filter the unique values in it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 100000&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; create an array with &amp;#39;n&amp;#39; random numbers:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; initialArray&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;	const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;round&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;random&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	initialArray&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;number&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; naively filter the unique values into a new array&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; uniqueArray&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueArrayBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; initialArray&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;length&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;	const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; initialArray&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uniqueArray&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;indexOf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;		uniqueArray&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueArrayAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;uniqueArray&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueArrayBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueArrayAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; arrayTotalTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;uniqueArray&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;arrayTotalTime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; uniqueArray&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;length&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 171.08500000000004 63235&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It takes 171 milliseconds to filter ~64k unique values in a 100k elments array. Not bad.&lt;&#x2F;p&gt;
&lt;p&gt;Now lets compare this naive implementation to just using Set():&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueSetBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; uniqueSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;initialArray&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; easy!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueSetAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;uniqueSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueSetBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UniqueSetAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setTotalTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;uniqueSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setTotalTime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; uniqueSet&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 0.8699999999998909 63235&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is FAST! ~0.9ms with the same initial 100k array. The good part is that Set does not get worse with the number of elements in it.&lt;&#x2F;p&gt;
&lt;p&gt;This is basic JS and the killer feature of Set()&#x27;s. Use them when you need a container of unique elements and&#x2F;or to filter unique elements in any iterable container.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;presence&quot;&gt;Presence&lt;&#x2F;h2&gt;
&lt;p&gt;Checking if an element is present is also easy in a Set and arguably an operation quite common for containers like these.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;has&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;has&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1337&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Arrays also have a presence function called &lt;code&gt;indexOf&lt;&#x2F;code&gt;: it returns the index of the element or -1 if it is not present.&lt;&#x2F;p&gt;
&lt;p&gt;To compare &lt;code&gt;Array.indexOf()&lt;&#x2F;code&gt; to &lt;code&gt;Set.has()&lt;&#x2F;code&gt; here is a quick test that runs 10000 indexOf&#x27;s (in array) and has&#x27;s (in Set) for an Array and Set of 100 elements:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; size&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; the Array and Set size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; size&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	a&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;round&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;random&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ops&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 10000&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; indexAll&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array Before&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ops&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	indexAll&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;indexOf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;round&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;random&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ just to do some operation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array After&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.indexOf()&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array Before&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array After&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; arrayTotalTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.indexOf()&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set Before&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ops&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	setValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;has&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;round&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;random&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ same as above just to do some operation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set After&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set.has()&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set Before&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set After&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setTotalTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set.has()&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setValue&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; indexAll&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SET: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setTotalTime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ARRAY: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; arrayTotalTime&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; SET:  17.68499999999767 ARRAY:  20.924999999995634&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A slight difference. Multiple executions give values that are coherent with these (not an outlier).
&lt;code&gt;Set.has()&lt;&#x2F;code&gt; is faster than the &lt;code&gt;Array.indexOf()&lt;&#x2F;code&gt; even for small Arrays.&lt;&#x2F;p&gt;
&lt;p&gt;The difference of execution just gets bigger as the size of the containers increase.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; size = 1000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; SET:  21.014999999999418 ARRAY:  54.00500000000102&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; size = 10000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; SET:  17.44499999999971 ARRAY:  398.505000000001&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; size = 100000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; SET:  19.770000000004075 ARRAY:  3779.524999999994&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Set.has()&lt;&#x2F;code&gt; execution time doesn&#x27;t seem to differ with the set size. The JS spec tells us why:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;Set objects must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements in the collection.&quot;&lt;&#x2F;em&gt; &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.ecma-international.org&#x2F;ecma-262&#x2F;6.0&#x2F;#sec-set-objects&quot;&gt;[*]&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It does not even bother heating your CPU as my browser probably implements this to be O(shiznit(n)) for a large enough n (I will not go into detail here so I will leave the measurement as an exercise for you as it is always important&#x2F;necessary to measure Big-O behaviours).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;insertion-speed&quot;&gt;Insertion speed&lt;&#x2F;h2&gt;
&lt;p&gt;Right now Sets seem really cool, how about we check how fast is the add() method in comparison to an array push(), like we did in the &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;in-loving-memory-of-immutable&#x2F;&quot;&gt;Immutable.List vs Array article&lt;&#x2F;a&gt; ?&lt;&#x2F;p&gt;
&lt;p&gt;The code is simple, two loops, one for Array.push() and another for Set.add().&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ammount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 100000&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ammount&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	a&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.push&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ammount&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set.add&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; arrayTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.push&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set.add&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.push in &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;arrayTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ms; Set.add in &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ms;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.push in 4.054999999993015ms; Set.add in 20.915000000037253ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ah! Arrays are much faster (5x) in insertion than Sets. If you are an experience developer this is not really surprising at all, but still it is nice to check.
Be aware that insertion speed grows linearly in Arrays and non-linearly in Sets:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ammount = 100000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.push in 4.054999999993015ms; Set.add in 20.915000000037253ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ammount = 1000000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.push in 17.175000000046566ms; Set.add in 417.03999999992084ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ ~4x more than prev.               ^ ~20x more than prev.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ammount = 10000000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.push in 349.8299999999581ms; Set.add in 3902.625ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ^ ~20x more than prev.             ^ ~10x more than prev.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could continue, but JavaScript numbers are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Double-precision_floating-point_format&quot;&gt;64 bit double precision floating point values&lt;&#x2F;a&gt;. Which means that for integer values they will use 52bits of storage for the significand. Which in turn means that for the next ammount (100000000) I would need 650MB of memory just to store the numbers + the overhead of the Array and Set data structures.&lt;&#x2F;p&gt;
&lt;p&gt;Another exercise for the reader :D&lt;&#x2F;p&gt;
&lt;p&gt;If you are doing a cheap fast logger, then Array is a better choice than Set since it inserts much faster. Set add() is probably implemented to have a better &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Big_O_notation&quot;&gt;O(some BS here)&lt;&#x2F;a&gt; than the Array push() and it will likely not be much slower than 10x the previous running order. But their measured absolute value is way slower and this is what really matters, always measure your code if you care about performance because overhead can creep in the most unexpected places (I am not sure if this is the case, but still...).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iteration-speed&quot;&gt;Iteration speed&lt;&#x2F;h2&gt;
&lt;p&gt;If you are wondering how Set performs in the need to iterate through its elements, wonder no further.&lt;&#x2F;p&gt;
&lt;p&gt;Again the two cycles, this time using for..of to go through the Set items.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ammount&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 100000&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ammount&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	a&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;length&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ArrayAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ammount&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; item&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; of&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;lt;- here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; item&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;measure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set.for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetBefore&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;SetAfter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; arrayTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; setTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; performance&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getEntriesByName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Set.for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Array.for in &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;arrayTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ms; Set.for in &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;${&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setTime&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ms;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.for in 4.44999999999709ms; Set.for in 9.239999999997963ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No surprises here. Array sequential values are faster to iterate than Set values (which iterates in insertion order).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ammount = 100000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.for in 4.44999999999709ms; Set.for in 9.239999999997963ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ammount = 1000000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.for in 9.044999999998254ms; Set.for in 55.14499999998952ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ammount = 10000000;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Array.for in 74.47000000000116ms; Set.for in 180.13999999999942ms;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Arrays are faster for sequential iteration of lots of data.
Converting the Set to an Array is not going to help here because &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Array&#x2F;from&quot;&gt;&lt;code&gt;Array.from&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; iterates through the argument to perform the convertion.&lt;&#x2F;p&gt;
&lt;p&gt;Just deal with it :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;set-operations&quot;&gt;Set operations&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;paulo_coding.jpg&quot; alt=&quot;A pic I took more than a decade ago. Paulo, one of the best hackers I have met. Nikon FM2 50mm1.2f, Kodak E100G film, double exposure.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We saw that Set construction and presence checking are extremely fast operations when compared to their Array counterparts. With this in mind the set operations can be easily and naively done.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;union&quot;&gt;Union&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; union&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Creates a new set with the &lt;em&gt;unique&lt;&#x2F;em&gt; values on set1 and set2 (no repeated values). If you don&#x27;t care about uniqueness then just use Arrays and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Array&#x2F;concat&quot;&gt;&lt;code&gt;concat()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;difference&quot;&gt;Difference&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; diff&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; !&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;has&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;intersection&quot;&gt;Intersection&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; intersected&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; set2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;has&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Simple as long as you remember that for objects they work with references instead of values.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Use Set() when unique values matter&lt;&#x2F;li&gt;
&lt;li&gt;Set.has() is much faster than Array.indexOf()&lt;&#x2F;li&gt;
&lt;li&gt;Array.push() is much faster than Set.add()&lt;&#x2F;li&gt;
&lt;li&gt;Arrays are faster to iterate sequentially&lt;&#x2F;li&gt;
&lt;li&gt;Union, Difference, Intersection are easy to implement with Set&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Set&#x27;s are a big part of my project &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;Grid Generator&lt;&#x2F;a&gt;. Keeping these small concepts close to the heart can help you leverage Sets to achieve very good performance even in mobile devices.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this post was valuable in any way to you. If you are interested &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;mastering-console-log&#x2F;&quot;&gt;here is my take on console.log()&lt;&#x2F;a&gt; and also a &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;in-loving-memory-of-immutable&#x2F;&quot;&gt;look into Immutable&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Lisbon as an inspiration for my project</title>
        <published>2017-10-25T00:00:00+00:00</published>
        <updated>2017-10-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/lisbon-as-an-inspiration-for-my-project/"/>
        <id>https://hugodaniel.com/posts/lisbon-as-an-inspiration-for-my-project/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/lisbon-as-an-inspiration-for-my-project/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;Lisbon_gridgenerator1.jpg&quot; alt=&quot;Diptych of Lisbon graffitti in portuguese tiles together with the downtown Lisbon ground&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Recently I was somewhat &quot;forced&quot; to think about the story behind the idea I am working on. If you go to these startup and entrepreneurship events you will see that most projects have some kind of a story behind them.
Either they start up in a garage (Apple), or they decided to improve their hobbyist girl discrimination app (facebook), or they just somehow were blessed by some mystical event that got their idea and team together to disrupt the universe.&lt;&#x2F;p&gt;
&lt;p&gt;When my reality clashed with that one I realized that I did not have a special motivation to do a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;pattern and shapes app&lt;&#x2F;a&gt; besides my desire to make a cool project come to life.
So I decided to do what it seemed like the best approach to move forward: I lead myself into a spiral of paranoia and depression for not taking in consideration the necessary planets alignment.&lt;&#x2F;p&gt;
&lt;p&gt;Afterall, why am I doing what I am doing ? Why drawing ? Why shapes and patterns ? What is my story ? How do I sell my idea ? What drives my &quot;pitch&quot; ?
All entrepreneurs seem to have the answers for these questions well sorted out as they always come up with some amazing tale of fortune and success.&lt;&#x2F;p&gt;
&lt;p&gt;Me?
I am just a person who worked in the public sector for 6 years. Quit out of frustration. Worked 2 months for a consulting company. Quit out of more frustration. Worked less than a year in a startup and quit to avoid medical insanity.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;Lisbon_gridgenerator2.jpg&quot; alt=&quot;A random person walking downwards with a building frontage covered in tiles in the background&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Since college that I am full of myself with photography. I really think that I am the last Coca-Cola in the desert in regards to photography.
Instead of studying for the exams I would spend hours roaming around Lisbon and taking pictures of every little bit of this city. I would then proceed to use them to produce poems that were even more pretentious than the pictures.
Which inevitably led me to fail a lot of years in university. I have pictures to show for it :)&lt;&#x2F;p&gt;
&lt;p&gt;Lucky for me Lisbon is one of the most beautiful cities in the world, so some pictures turned out ok in spite of my lack of talent for photography. The ones that were good were mostly about:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Tagus scenery (hard to miss)&lt;&#x2F;li&gt;
&lt;li&gt;Buildings frontages&lt;&#x2F;li&gt;
&lt;li&gt;Portuguese sidewalks&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;Lisbon_gridgenerator3.jpg&quot; alt=&quot;A building in Lisbon&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The ammount of patterns and small details in Lisbon is impressive. Be it on the walls, or on the ground, or inside or outside of buildings. I guess this is the only explanation I can think of for my interest in shapes and geometric patterns.&lt;&#x2F;p&gt;
&lt;p&gt;In a few days Lisbon will be full of people from different culture(s) who are coming in for the WebSummit. If you are visiting don&#x27;t forget to look at the floors and walls.
They are a source of inspiration.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;Lisbon_gridgenerator4.jpg&quot; alt=&quot;Diptych of a messed up sidewalk diagonal grid and the door detail of a church in &amp;quot;Martim Moniz&amp;quot; where the frontage is entirely rendered on the ground sidewalk&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you liked this post &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;check out my project&lt;&#x2F;a&gt; and the reason why &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;why-i-decided-to-go-to-the-websummit&#x2F;&quot;&gt;I am going to the WebSummit&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why I decided to go to the WebSummit?</title>
        <published>2017-10-24T00:00:00+00:00</published>
        <updated>2017-10-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/why-i-decided-to-go-to-the-websummit/"/>
        <id>https://hugodaniel.com/posts/why-i-decided-to-go-to-the-websummit/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/why-i-decided-to-go-to-the-websummit/">&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;websummit1_tagusriver.jpg&quot; alt=&quot;Tagus river by sunset in Lisbon, with a background bridge that shares some similarities with the Golden Gate in San Francisco&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Personally I find it impossible to answer this question. I feel that it was not me who actually took the decision to go to the WebSummit. Even though I did.&lt;&#x2F;p&gt;
&lt;p&gt;It all hapened through a sequence of chained events that led me to have to decide to buy a discounted alpha ticket to go there.&lt;&#x2F;p&gt;
&lt;p&gt;At first the WebSummit has two big &quot;no&quot;&#x27;s: the price and if you can actually get something useful from it. I can argue that there is some pressure to go when you have the whole city talking about this conference and you know quite a few people that are going there. How can you miss the even where supposedly everything is hapenning ?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;websummit1_me.jpg&quot; alt=&quot;Me in Lisbon at the top of the arc in Rua Augusta enjoying a sunny day&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gridgenerator.com&quot;&gt;My project is a web app to help people work their graphical ideas&lt;&#x2F;a&gt; without having to learn pro software so that they can use these ideas in their daily lives. Technically it is a grid where each element has itself a customized grid inside. Besides this it also has a cool way to help select colors that match and work well with each other.
I have not yet released it, so I don&#x27;t have any market data to show off. I am not looking for investment for two main reasons: I want to bootstrap it and it currently is in an early stage (almost fully developed but still before market).&lt;&#x2F;p&gt;
&lt;p&gt;I talked beforehand to some people that went to the 2016 edition, and they said that it&#x27;s a big event, so big that it is confusing to be there. Also most people that go are looking for investment. All these people that I talked to work for some company that paid their tickets, so I had to keep that in mind when considering their opinion (myself being a bootstrapper).&lt;&#x2F;p&gt;
&lt;p&gt;Because of this initially I had decided not to go. Then I talked to my mentor and he insisted that I considered the pros and cons of going and not going.
I then changed my mind into going to the WebSummit because he convinced me that the potential to expand my contact network and talk to people that might be interested in the project was something that at this stage would be very good overall.&lt;&#x2F;p&gt;
&lt;p&gt;Hence the decision to give WebSummit a chance. I applied to their &quot;alpha ticket&quot;, got selected after a quick interview and they sold me a ~520EUR pass available. This was &lt;em&gt;a lot&lt;&#x2F;em&gt; for me to pay. Even considering that I would be getting 3 tickets and a stand there for my project during one day. But I bit the bullet considering that I am living in Lisbon and that I would have no further big expenses.&lt;&#x2F;p&gt;
&lt;p&gt;That was three months ago, meanwhile I have already considered and reconsidered my previous decision, and my current status is still a bit doubtful about the WebSummit as a worthwhile experience for a bootstrapper. I am certainly not going to look for an investment (like most people apparently go) and the real benefits that I think I will obtain are not easily tangible (personal development and enrichment, maybe some hope of having inspirational talks with different minded people).&lt;&#x2F;p&gt;
&lt;p&gt;Maybe in WebSummit I will meet people that can open my mind to other different kinds of funding. Maybe in the future I will do a kickstarter campaign or some other kind of funding project.
Right now I know that at least I get the chance to be in the same place as Al Gore and other great thinkers...&lt;&#x2F;p&gt;
&lt;p&gt;If you liked this post check out &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;lisbon-as-an-inspiration-for-my-project&#x2F;&quot;&gt;Lisbon as an inspiration for my project&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>In loving memory of Immutable.js</title>
        <published>2017-10-03T00:00:00+00:00</published>
        <updated>2017-10-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/in-loving-memory-of-immutable/"/>
        <id>https://hugodaniel.com/posts/in-loving-memory-of-immutable/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/in-loving-memory-of-immutable/">&lt;p&gt;Any JavaScript spaghetti worth its salt won&#x27;t keep track of its objects references or their updates.
These are things that happen between the mind of a chef and the ether of a planned portion with lots of defensive copying.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;immutable-js&#x2F;&quot;&gt;Immutable.js&lt;&#x2F;a&gt; aims to reduce these portion sizes to match the ones in fancy restaurants while avoiding ingredients like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;JSON.parse(JSON.stringify(obj))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To try out this new pepper lets open the developer tools in a new tab and sharpen our sour-sweet tooth.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;devtools.png&quot; alt=&quot;Screenshot of the Firefox developer tools in console mode.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-many-calories-has-the-appetizer&quot;&gt;How many calories has the appetizer ?&lt;&#x2F;h2&gt;
&lt;p&gt;In order to measure the amount of memory that Immutable.js uses by itself lets marinate it in a quick and dirty formula:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Open the devtools&lt;&#x2F;li&gt;
&lt;li&gt;Define a simple array with a single item in it and print it to the console
&lt;ul&gt;
&lt;li&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; let test1 = [1337];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; console.log(test1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Measure the memory usage (memory tab of the dev tools)&lt;&#x2F;li&gt;
&lt;li&gt;Load Immutable.js directly into the console (copy pasting its minified source directly into the console)&lt;&#x2F;li&gt;
&lt;li&gt;Define a simple list with a single item in it and print it to the console
&lt;ul&gt;
&lt;li&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; let test2 = Immutable.List.of(1337);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; console.log(test2);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Measure the memory usage again&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The key points are 3. and 6. so lets do it and take a look into the memory info. For these measures I am using Firefox Developer Edition 53.0a2 (2017-03-05) (64-bit) in OSX Sierra.&lt;&#x2F;p&gt;
&lt;p&gt;After point 3. I have 2.11MB of used memory with the following layout:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;scripts&lt;&#x2F;em&gt;: 37KiB (347 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;strings&lt;&#x2F;em&gt;: 362KiB (9685 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;objects&lt;&#x2F;em&gt;: 813KiB (11325 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;other&lt;&#x2F;em&gt;: 849KiB (18365 objects)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is for nothing but an empty tab with devtools opened after point 3. in the magic formula.&lt;&#x2F;p&gt;
&lt;p&gt;Now lets load &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;facebook&#x2F;immutable-js&#x2F;master&#x2F;dist&#x2F;immutable.min.js&quot;&gt;Immutable.js raw minification&lt;&#x2F;a&gt; and run the rest of the steps.&lt;&#x2F;p&gt;
&lt;p&gt;After point 6.  I have 2.53MB of used memory with the following layout:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;scripts&lt;&#x2F;em&gt;: 248KiB (1717 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;strings&lt;&#x2F;em&gt;: 384KiB (10252 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;objects&lt;&#x2F;em&gt;: 904KiB (12618 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;other&lt;&#x2F;em&gt;: 933KiB (19984 objects)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Immutable.js makes the memory usage go up from 2.1MB to about 2.5MB.&lt;&#x2F;strong&gt; That&#x27;s around 0.4MB just to load the minified Immutable.js in memory.&lt;&#x2F;p&gt;
&lt;p&gt;Lets keep this value as a reference in further tests. I am keeping these memory snapshots also for further reference.&lt;&#x2F;p&gt;
&lt;p&gt;How can we leverage the juice from these 0.4MB into our secret sauce ?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-list-of-many-secrets&quot;&gt;A list of many secrets&lt;&#x2F;h2&gt;
&lt;p&gt;Immutable allows the discerning chef to cook with well defined ingredients. You can define your own data types and use them as immutable everywhere you want to. To do that the Immutable.Record is their provided interface.&lt;&#x2F;p&gt;
&lt;p&gt;The following code uses it to define a data type for a 2D point, with X and Y coordinates, and then create some points with it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const Pt = Immutable.Record( { x: 0, y: 0} );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const pt1 = new Pt(); &#x2F;&#x2F; uses x: 0, y: 0 by default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const pt2 = new Pt({ y: 123 }); &#x2F;&#x2F; uses x: 0 by default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const pt3 = new Pt({ x: 123, y: 321 }); &#x2F;&#x2F; uses your provided values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fast-food junkies could do the same in straight JS with the simpler approach:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function PtJS(x = 0, y = 0) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	this.x = x;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	this.y = y;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let jspt1 = new PtJS();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let jspt2 = new PtJS(0, 123);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let jspt3 = new PtJS(123, 321);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some might even argue that they are not wasting the memory that Immutable is. Master chefs are always looking for opportunities to learn, to study and to teach.&lt;&#x2F;p&gt;
&lt;p&gt;Now for a simple test, create a list with 10000 of those 2D points and compare memory readings of the Immutable approach with the plain JS approach.&lt;&#x2F;p&gt;
&lt;p&gt;First the plain JS approach (lets assume the constructor is already created as above).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let testArray = [];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;for(let i = 0; i &amp;lt; 10000; i++) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  testArray.push(new PtJS());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After measuring this in the Memory tab we get 2.92MB in this layout:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;scripts&lt;&#x2F;em&gt;: 228KiB (1692 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;strings&lt;&#x2F;em&gt;: 384KiB (10251 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;objects&lt;&#x2F;em&gt;: 1MiB (22688 objects)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;other&lt;&#x2F;em&gt;: 888KiB (19990 objects)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That seems fair, we get an increase of about 390KiB in comparison to our previous measurement. That should be enough motivation to roll our Chefs Knives suitecase of Persistency and do it in Immutable style to measure it on top of this 2.92MB already in use.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const defaultPt = new Pt();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const testLst = Immutable.Repeat(defaultPt, 10000);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After measuring this in the Memory tab we get 2.91MB. This is a decrease of about 10KiB from our previous memory usage. How is this possible ? Is the data even there ?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;testLst.first().x;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; returns 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;testLst.size();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; returns 10000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yep, it&#x27;s all there. Immutable.js allows you to take good care of your memory, but as with all sharp knifes you need to know how to avoid hurting yourself. Lets dive a bit further to understand what is going on and how to master these data structures.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;master-chef-mystery-boxes&quot;&gt;Master Chef Mystery Boxes&lt;&#x2F;h2&gt;
&lt;p&gt;One common misconception about immutable data structures is that there is a lot of useless copying being done. In fact this is so common that there are even &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rtfeldman&#x2F;seamless-immutable&quot;&gt;JS libraries based on it&lt;&#x2F;a&gt;. Playing with the flavour of common things note the most typical data structure in functional languages.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-single-linked-list&quot;&gt;The single linked list.&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable-list1.gif&quot; alt=&quot;A single linked list with 3 values&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Supposed that this is a immutable list. It is not possible to add, remove or change its values without returning a new version of it.&lt;&#x2F;p&gt;
&lt;p&gt;Does this mean that we need to copy all of it when we need to put a new value in it ? Not necessarily. We can just create the new list item and make sure its pointer is targeting the beginning of the original list.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable-list2.png&quot; alt=&quot;Placing a new value in the previous list&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This works because the list is immutable, we know for sure that the original list won&#x27;t change so &lt;strong&gt;it is possible to reuse its values&lt;&#x2F;strong&gt;, no copying is involved in this.&lt;&#x2F;p&gt;
&lt;p&gt;As before, our new immutable list is again defined by its first value, which in this new case is our new value.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;master-the-simple-cuts-first&quot;&gt;Master the simple cuts first&lt;&#x2F;h3&gt;
&lt;p&gt;Many operations are possible on our immutable single linked list that leverage the fact that it is an immutable list.&lt;&#x2F;p&gt;
&lt;p&gt;Operations like &lt;em&gt;head&lt;&#x2F;em&gt; (return the first value in the list) and &lt;em&gt;tail&lt;&#x2F;em&gt; (return all the items in the list except for the first) are almost instantaneous to implement. For &lt;em&gt;head&lt;&#x2F;em&gt; we just return the value of the first item and for &lt;em&gt;tail&lt;&#x2F;em&gt; we just return the first item pointer value (which is an immutable single linked list, in this case, our original 3 value list).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;concat&quot;&gt;Concat&lt;&#x2F;h4&gt;
&lt;p&gt;Joining two lists is one of those simple operations that is worth your time and attention in order to understand it. If we have 2 different immutable lists that we want to join we need to go to the first list and adjust the last pointer of the last item to point to the first item of the second list.&lt;&#x2F;p&gt;
&lt;p&gt;Here it is in pictures:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_two_lists.png&quot; alt=&quot;Joining these two lists&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_two_lists_2.png&quot; alt=&quot;We need to make the last item point to the first item of the second list&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_two_lists_3.png&quot; alt=&quot;A copy of this element is necessary because we can&amp;#39;t just change it to point to the first item of lst2&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_two_lists_4.png&quot; alt=&quot;But now we need to make the previous item point to the newly created copy. So a copy of it will also be necessary.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_two_lists_final.png&quot; alt=&quot;That is why to concat two lists a new list is made with a copy of the elements in the first list&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Concat is a heavy operation, it mostly depends on the size of the first list. There are a few tricks to make it faster.&lt;&#x2F;p&gt;
&lt;p&gt;To keep it simple I am not going to go much more into this and move to the point.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-best-recipe-is-made-of-many-subrecipes&quot;&gt;The best recipe is made of many subrecipes&lt;&#x2F;h2&gt;
&lt;p&gt;The list holds data. That&#x27;s why it&#x27;s called a &lt;em&gt;data&lt;&#x2F;em&gt; structure. Now what if instead of directly putting our data in each list item we could instead just point to the data ? Like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_lazy1.png&quot; alt=&quot;List doesn&amp;#39;t directly hold the data anymore&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The list effectively now holds &lt;strong&gt;a way to reach&lt;&#x2F;strong&gt; each value instead of the real values. We can get more generic and greatly simplify it by saying that in each list item there is a recipe to reach each value. In the above picture this &lt;em&gt;recipe&lt;&#x2F;em&gt; generalization is represented by the red arrows.&lt;&#x2F;p&gt;
&lt;p&gt;Let me try to simplify it with the hope that it might stand out the intended purpose.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_lazy2.png&quot; alt=&quot;A list of recipes can be a list of values&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The term &lt;em&gt;recipe&lt;&#x2F;em&gt; is not chosen by chance: it represents something that must be done to produce the value that the list item holds.&lt;&#x2F;p&gt;
&lt;p&gt;If we follow the &lt;em&gt;recipe&lt;&#x2F;em&gt; in each item we can get to the intended values. For instance, suppose that this is a list of JS Number&#x27;s, a good recipe to produce the value would be to just call Number() on the data. If it was a list of String&#x27;s, a good recipe would be to call String() on the data. This also holds for very complex values, say this is a list of balanced tree&#x27;s, or your favourite custom complex data type, &lt;strong&gt;a recipe is the way to construct the value&lt;&#x2F;strong&gt;, could just be following a pointer but perhaps that would not be a very useful constructor due to being too general.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lazy-concat&quot;&gt;Lazy concat&lt;&#x2F;h3&gt;
&lt;p&gt;In our previous look into &lt;em&gt;concat&lt;&#x2F;em&gt; we noticed that it was a heavy operation, requiring a full copy of the first list that we want to join. When working with immutable data there are only a few of these &quot;heavy&quot; operations that do need a full copy.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we are taking quality steps as chefs how about we use a &lt;em&gt;recipe&lt;&#x2F;em&gt; for concat ?&lt;&#x2F;p&gt;
&lt;p&gt;Instead of doing a full copy of the first list, just copy the first element and make it point to a recipe. That way, no matter the size of the lists, concat would be done in a single operation (the first item). Here it is in a picture:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immutable_concat_lazy.png&quot; alt=&quot;Why copy the whole first list if we don&amp;#39;t know if it will be needed ?&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now if we need the second element of the list the recipe will be followed to get it.&lt;&#x2F;p&gt;
&lt;p&gt;That is a simple recipe:
copy the first list up to the needed value, if the copying is done but the intended value is not yet reached then start going through the second list values (without copying them). In the case we want the 2nd value of a concat&#x27;ed list a single copy will happen because we already copied the first item when concat was called. This is a case where the recipe is itself the whole concat operation, meaning that it will only copy until the end of the first list and after it will use the reference of the second list.&lt;&#x2F;p&gt;
&lt;p&gt;This &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Thunk&quot;&gt;&lt;em&gt;recipe&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; approach is usually known as laziness and typically enhanced with a cache of results to avoid copying and constructing the same values over again (this caching approach is known as &quot;memoization&quot;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cuisine-du-monde&quot;&gt;Cuisine du monde&lt;&#x2F;h2&gt;
&lt;p&gt;Immutable.js makes good use of these techniques to avoid doing work when necessary and unnecessary copies. Their approach is lean and well thought, clearly separating the values from the way they are traversed.&lt;&#x2F;p&gt;
&lt;p&gt;Lets look at our Immutable approach again:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const defaultPt = new Pt();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const testLst = Immutable.Repeat(defaultPt, 10000);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;testLst.first().x;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A few things stand out:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We are always using the same reference &lt;em&gt;defaultPt&lt;&#x2F;em&gt; instead of creating a new value in each item.
&lt;ul&gt;
&lt;li&gt;This is possible thanks to immutability, if we change it we are effectively creating a new value and a new list.&lt;&#x2F;li&gt;
&lt;li&gt;Immutability encourages reutilization and is typically a GC friendly approach.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Repeat just returns a &lt;em&gt;recipe&lt;&#x2F;em&gt; (thunk)
&lt;ul&gt;
&lt;li&gt;No heavy work is actually done, it just returns a way to access and construct the values&lt;&#x2F;li&gt;
&lt;li&gt;We used 10000 but could have used infinite with no performance or memory hit&lt;&#x2F;li&gt;
&lt;li&gt;Work is only done when values are being requested and only up until them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Immutable.js also uses a few other tricks to speed up common operations. For instance their List approach uses deques, which means that it keeps your list split in two, so [1,2,3,4,5,6] is kept by Immutable as [1,2,3] and [6,5,4] (reversed rest). This is a very simplified explanation of it, but in practice it allows for very fast insertions in the beginning and end of the list (&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;blog.klipse.tech&#x2F;javascript&#x2F;2016&#x2F;06&#x2F;23&#x2F;immutable-perf.html&quot;&gt;faster than JS arrays&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Immutable is certainly a different way of doing JS. Given the normal tendency JS coders have to lean more towards object oriented concepts, immutable feels like the schrodinger&#x27;s immigrant in a foreign land.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;immigrant.jpeg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I hope this post was in any way useful to you. Immutable sure is a fun library to get to know and work with.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>vi is not vim</title>
        <published>2017-08-12T00:00:00+00:00</published>
        <updated>2017-08-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/vi-is-not-vim/"/>
        <id>https://hugodaniel.com/posts/vi-is-not-vim/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/vi-is-not-vim/">&lt;p&gt;When dinossaurs ruled the earth there was a young kid that had just installed Red Hat Linux 5 on his computer.&lt;br&#x2F;&gt;
Fascinated with the &quot;OS for the elite&quot; he was about to experience a devouring frustration.
The kind that gives rise to dark divinities that come to haunt you in your sleep for years to come:&lt;&#x2F;p&gt;
&lt;p&gt;Trying to exit vim.&lt;&#x2F;p&gt;
&lt;p&gt;After a few unsuccessful atempts the computer &lt;em&gt;power switch&lt;&#x2F;em&gt; was the only option left. Like that the dream of a promising carreer in elite-land was shattered for that young boy.&lt;&#x2F;p&gt;
&lt;p&gt;That young boy was me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;high-tech-editor-low-tech-coder&quot;&gt;High tech editor, low tech coder&lt;&#x2F;h2&gt;
&lt;p&gt;My stubbornness always took the best part of my reason and vim was my editor for years to come. Since rough starts are the perfect driver for a good love story I then ditched it to take a stroll in netbeans land. &lt;br&#x2F;&gt;After a while a pardon was due and got back to it again. Then I ditched it again for Visual Studio. &lt;br&#x2F;&gt;Got back to it again. And so on.&lt;&#x2F;p&gt;
&lt;p&gt;Code editors today try to do everything and a pair of boots. Even vim, known for its minimalist looks, is very prone to config-pr0n worthy of the most wild and nasty fantasies.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-ll-show-you-mine-if-you-show-me-yours&quot;&gt;I&#x27;ll show you mine if you show me yours&lt;&#x2F;h2&gt;
&lt;p&gt;At one point I got myself in the middle of a config discussion between developers. They were arguing about good .vimrc config options and plugins for vim.&lt;&#x2F;p&gt;
&lt;p&gt;I decided to participate and show my ~60 lines .vimrc file. They laughed. It was so small. Almost useless.&lt;&#x2F;p&gt;
&lt;p&gt;That got me thinking:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What do i &lt;em&gt;really&lt;&#x2F;em&gt; need in a code editor ?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After giving a hard thought on my usage&#x2F;preferences and some possible optimizations I took a look into the market of code editors and decided to &lt;strong&gt;upgrade from vim to vi&lt;&#x2F;strong&gt; (by vi I mean &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;repo.or.cz&#x2F;nvi.git&quot;&gt;nvi 1.81.6, still maintained and developed here&lt;&#x2F;a&gt; ).&lt;&#x2F;p&gt;
&lt;p&gt;The rest of this blog post is about some nvi parts (vi, not vim), in particular some parts that are percieved as limitations. I will run through them and try to provide arguments that favor them and reasons to use them. Have your salt and pepper at hand before reading further.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;minimal-config-file-exrc&quot;&gt;Minimal config file (.exrc)&lt;&#x2F;h2&gt;
&lt;p&gt;The nvi config file is named .exrc, here is my current setup:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set showmode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set showmatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set ruler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set shiftwidth=2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set tabstop=2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set verbose&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set leftright&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set cedit=\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set filec=\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;9 lines only. No maintenance. No BS.&lt;&#x2F;p&gt;
&lt;p&gt;These options are mostly similar to those in .vimrc, a special note for cedit and filec, these have a =\&amp;lt;TAB&amp;gt; (the &amp;lt;TAB&amp;gt; is the actual tab character there after the \).
The &lt;strong&gt;cedit&lt;&#x2F;strong&gt; property sets the character to trigger command expansion in the vi command colon mode. The &lt;strong&gt;filec&lt;&#x2F;strong&gt; sets the the character for file name expansion (auto-complete) when opening a new file inside vi (e.g. with :e).&lt;&#x2F;p&gt;
&lt;p&gt;All of these are well documented in the man page.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ man nvi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;no-unicode-support&quot;&gt;No unicode support&lt;&#x2F;h2&gt;
&lt;p&gt;There are some vi implementations that support multibyte characters like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lichray&#x2F;nvi2&quot;&gt;nvi2&lt;&#x2F;a&gt;. But for this blog post I am assuming your vi is plain &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sites.google.com&#x2F;a&#x2F;bostic.com&#x2F;keithbostic&#x2F;vi&#x2F;&quot;&gt;nvi&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;No multibyte, wide-char, wtf-8, extended codepoints. Although those are very important to learn and master I do prefer to keep code in plain strict single-byte ASCII (UTF-8 supersedes it).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why ?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It keeps the language coherent with the programming reserved words (more than logic constructs, &lt;em&gt;while&lt;&#x2F;em&gt;, &lt;em&gt;for&lt;&#x2F;em&gt;, &lt;em&gt;if&lt;&#x2F;em&gt;, are english words).&lt;&#x2F;p&gt;
&lt;p&gt;It makes it perfectly visible when an accidental wide-char is inserted (particularly helpful if you are using a keyboard layout that does not use the US key-mapping). This is good to make sure your code is available to read on every system, regardless of locale (it even works if someone opens the code you wrote in an editor that is set to default to UTF-8 encoding).&lt;&#x2F;p&gt;
&lt;p&gt;Another good thing is that it works with a wider variety of fonts. Some monospace terminal fonts can&#x27;t correctly display all UTF-8 characters.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;But I sometimes need to write documents with strange characters&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That is one of the scenarios where I would use another text editor. nvi is strictly a code&#x2F;config editor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-syntax-highlighting&quot;&gt;No syntax highlighting&lt;&#x2F;h2&gt;
&lt;p&gt;This is another personal preference. It has been a long time since I had to worry about syntax when producing code. If you still struggle with syntax then please use syntax highlighting, it will help those special words stand out.
Otherwise why not give it a try without syntax highlighting for a while (a few weeks to be slightly above the habituation threshold) and measure how you perform ?&lt;&#x2F;p&gt;
&lt;p&gt;It does help to keep your functions small and easy to read.&lt;&#x2F;p&gt;
&lt;p&gt;Comments are shown with their true weight and your commented code is promoted to the same importance as your production code.&lt;&#x2F;p&gt;
&lt;p&gt;Your focus will be in semantics and it is easier to get into it without the syntax aggressively jumping at your face.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fast-undo&quot;&gt;Fast undo&lt;&#x2F;h2&gt;
&lt;p&gt;Like in vim the undo in vi is very convenient but has a slightly different way of operating. Instead of pressing &lt;em&gt;u&lt;&#x2F;em&gt; multiple times to go through the various undo levels and then ctrl-r to redo, in vi you do it by pressing &lt;em&gt;u&lt;&#x2F;em&gt; once to undo and the &#x27;&lt;strong&gt;.&lt;&#x2F;strong&gt;&#x27; to go through the various undo levels.&lt;&#x2F;p&gt;
&lt;p&gt;To redo you press &lt;em&gt;u&lt;&#x2F;em&gt; twice (undo the undo) and then &#x27;&lt;strong&gt;.&lt;&#x2F;strong&gt;&#x27; to go through the multiple redo levels.&lt;&#x2F;p&gt;
&lt;p&gt;I think this is slightly more coherent and it also makes use of the &#x27;&lt;strong&gt;.&lt;&#x2F;strong&gt;&#x27; (repeat action) operator in an arguably more logical way.&lt;&#x2F;p&gt;
&lt;p&gt;Like in vim, you can use the &lt;em&gt;U&lt;&#x2F;em&gt; command to restore a line to the state it was before the cursor was placed on top of it (undoing all the chances since that time).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-visual-mode&quot;&gt;No visual mode&lt;&#x2F;h2&gt;
&lt;p&gt;There is no visual mode in vi (visual mode as in pressing the &lt;em&gt;v&lt;&#x2F;em&gt; command and using your movement keys to select an area of text).&lt;&#x2F;p&gt;
&lt;p&gt;At first this might seem like a big handicap, but vi shares a few commands with vim that once mastered can make you more productive than using the visual mode.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Marks &lt;em&gt;m&amp;lt;insert letter here&amp;gt;&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can setup marks in text, if you type &lt;em&gt;mx&lt;&#x2F;em&gt; it will define the mark x at the current cursor position. Typically these are used to move quickly through the file and go to certain marked positions. For that the &#x27; command is used followed by the mark character name (moves to the line) or with the ` command (moves to the exact cursor position of the mark). To move to mark x do &#x27;x (assuming you did &lt;em&gt;mx&lt;&#x2F;em&gt; in some place before).&lt;&#x2F;p&gt;
&lt;p&gt;Marks can also be used with other common commands like yank, delete, etc..., so instead of using the visual mode you can yank or delete to a a mark set at some position.&lt;br&#x2F;&gt;
To do that use the &lt;em&gt;t&lt;&#x2F;em&gt; or &lt;em&gt;f&lt;&#x2F;em&gt; commands, like ytx (I read it as: &lt;em&gt;y&lt;&#x2F;em&gt;ank &lt;em&gt;t&lt;&#x2F;em&gt;o &lt;em&gt;x&lt;&#x2F;em&gt;), it will yank all lines up to (but not including) the line at mark x. To include it use the &lt;em&gt;f&lt;&#x2F;em&gt; as in yfx.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-tabs&quot;&gt;No tabs&lt;&#x2F;h2&gt;
&lt;p&gt;Tabs was a feature that I used a lot in vim, unfortunately they only work with vim, so if you want to run a shell command or have a terminal to read compiler output you will need to use them with some other kind of tab system.&lt;&#x2F;p&gt;
&lt;p&gt;On my journey to the limits of usefulness I found myself using vim tabs together with tmux tabs and terminal (osx) tabs.&lt;&#x2F;p&gt;
&lt;p&gt;After those crazy days (months ?) I finally decided to ditch all tabs and stick to a single tool for that purpose, one that is versatile enough to cover my use cases for tabs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Do one thing and do it well&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tmux&#x2F;tmux&#x2F;wiki&quot;&gt;Tmux&lt;&#x2F;a&gt; is my current tool of choice, nowadays I don&#x27;t use terminal tabs or text editor tabs. I leave that work for tmux, an amazing productivity tool that allows me to work fullscreen in zen mode with the code.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Panes in vi&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Like in vim you can split your window with panes, these are useful to use another section of code as a quick reference or to do some quick yank&#x2F;past in vi between files&#x2F;sections.&lt;&#x2F;p&gt;
&lt;p&gt;The pane system in vi works slightly different from vim. To vertically split the window you can also use the :vs, but to horizontally split the window :sp won&#x27;t work. In vi the command to horizontally split a window is the :E, as in Edit (the same as :e but horizontally split).&lt;&#x2F;p&gt;
&lt;p&gt;To switch between panes ctrl-w will immediately move your cursor to the next window pane. Instead of pressing twice like vim you only need to press it once. This is hard to get used to at first but it is also hard to live without once used to it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;nvi_tmux_macos.png&quot; alt=&quot;My nvi with tmux on macos&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-macros&quot;&gt;No macros&lt;&#x2F;h2&gt;
&lt;p&gt;One feature that I consistently used in vim was macros (vim &lt;em&gt;q&lt;&#x2F;em&gt; command). It was easy to create bundles of commands and run them to do your repeated text tasks or grunt work. Very useful when replicating huge data files or setting up a &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;mastering-console-log&#x2F;&quot;&gt;big JSON test file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In vi you can also use the power of macros through buffers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Buff it up&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Buffers are easy to use, you can prefix your common text manipulation commands (dd, yy, etc...) to a named buffer. To do that start the command with &quot;&amp;lt;buffer name&amp;gt; where &amp;lt;buffer name&amp;gt; is any letter from a-z.&lt;&#x2F;p&gt;
&lt;p&gt;Here are some examples:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;To delete 4 lines and place them into buffer a&lt;&#x2F;strong&gt; &quot;a4dd&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;To paste buffer &lt;em&gt;a&lt;&#x2F;em&gt; to the current cursor position&lt;&#x2F;strong&gt; &quot;ap&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;To view all your buffers go to ex mode (:) and do&lt;&#x2F;strong&gt; :di b&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Who needs macros when you have buffers&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Write a few commands to be executed in your file, place then in a buffer and tell vi that you want to execute the buffer:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4dd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;G&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Line by line:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;move two lines down&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;delete 4 lines&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;go to the end of the file&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Put these into a buffer named &lt;em&gt;c&lt;&#x2F;em&gt; with &lt;i&gt;&quot;c3yy&lt;&#x2F;i&gt; (yank 3 lines into buffer &lt;em&gt;c&lt;&#x2F;em&gt;), and whenever you want to run it just do &lt;em&gt;@ c&lt;&#x2F;em&gt;. Undo &lt;em&gt;u&lt;&#x2F;em&gt; also works nicely with buffered commands.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;upgrading-from-vim-to-vi&quot;&gt;Upgrading from vim to vi&lt;&#x2F;h2&gt;
&lt;p&gt;There are some cool benefits in using vi like how fast it is and how it handles huge files without a problem.&lt;&#x2F;p&gt;
&lt;p&gt;nvi also performs well in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jhallen&#x2F;joes-sandbox&#x2F;blob&#x2F;master&#x2F;editor-perf&#x2F;readme.md&quot;&gt;this benchmark of editors&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The case for vi is like any other editor: a matter of getting used to it and keep perfecting your skills through it for what it really matters: writting great code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Use what you are more confortable with. There are tradeoffs in every editor (even the mighty visual studio code does not allow you to work without syntax highlighting on...) and today nvi fits nicely with my way of working and approach.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this post to be used as a initial reference and motivation to those that are looking for a more minimalistic way of doing things. I don&#x27;t intend it to start flame wars.&lt;&#x2F;p&gt;
&lt;p&gt;You know all of these are just my opinions :)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mastering console.log()</title>
        <published>2017-08-11T00:00:00+00:00</published>
        <updated>2017-08-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/mastering-console-log/"/>
        <id>https://hugodaniel.com/posts/mastering-console-log/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/mastering-console-log/">&lt;p&gt;Using &lt;code&gt;console.log()&lt;&#x2F;code&gt; to debug JavaScript, a dynamic weakly-typed interpreted language, feels like drinking beers on a lazy summer sunday afternoon.&lt;&#x2F;p&gt;
&lt;p&gt;It is easy and you do it without thinking too much on how you could probably be more productive doing something else.&lt;&#x2F;p&gt;
&lt;p&gt;Truth is that in all the other days of the week you don&#x27;t avoid spraying your code with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Statements&#x2F;debugger&quot;&gt;&lt;code&gt;debugger&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; keyword and let the developer tools stop and show you the execution context at that exact location.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function yourCodeThatCouldBeWorking() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const x = 1337;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const y = parseInt(window.prompt(&amp;#39;Y value:&amp;#39;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  debugger; &#x2F;&#x2F; &amp;lt;- hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return (x &#x2F; y);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But lazy summer sunday afternoons are on to get us, and &lt;code&gt;console.log()&lt;&#x2F;code&gt; is our friend for the mood.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;console-log-basic-mode&quot;&gt;console.log() basic mode&lt;&#x2F;h2&gt;
&lt;p&gt;The most basic usage of &lt;code&gt;console.log&lt;&#x2F;code&gt; is to just pass it a string. You can step this up a bit by following the string with JS objects and&#x2F;or strings. Like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const v1 = { x: 123, y: 321 };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;console.log(&amp;quot;Vector v1: (&amp;quot;, v1.x, &amp;quot;,&amp;quot;, v1.y, &amp;quot;)&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; or just:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;console.log(&amp;quot;Vector v1:&amp;quot;, v1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Try it in your developer tools console (Ctrl Shift i, or in mac Cmd Shift i).&lt;&#x2F;p&gt;
&lt;p&gt;This is a particularly simple and helpful way to properly debug JavaScript. Specially if your code is creating code or functions in runtime, making it hard to setup breakpoints in the debugger window.&lt;&#x2F;p&gt;
&lt;p&gt;But who needs breakpoints when we have &lt;code&gt;console.log&lt;&#x2F;code&gt; ? :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;colorful-console-log-composer-mode&quot;&gt;Colorful console.log() composer mode&lt;&#x2F;h2&gt;
&lt;p&gt;Besides its simplicity, my next favourite thing in &lt;code&gt;console.log&lt;&#x2F;code&gt; is that it also allows you to pass a format string to be replaced with what you want:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const v1 = { x: 123, y: 321 };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;console.log(&amp;quot;v1 (%i, %i)&amp;quot;, v1.x, v1.y);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a handful of other &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;console#Using_string_substitutions&quot;&gt;string substitutions&lt;&#x2F;a&gt; you can use.&lt;&#x2F;p&gt;
&lt;p&gt;While apparently this is not a big improvement over the simplest mode, it can be used to do a few things that would not be so easy otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Colors in console.log&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can style your output with CSS through the %c substitution:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const v1 = { x: 123, y: 321 };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;console.log( &amp;quot;%c[Vector 1] %c(%i, %i)%c\nin object %o&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           , &amp;quot;background: #242; color: #bada55&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           , &amp;quot;background: #424; color: #c0ffee&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           , v1.x, v1.y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           , &amp;quot;&amp;quot; &#x2F;&#x2F;&amp;lt;- clears style&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           , v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Dynamically create your output&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can also compose the log format string with code and pass it the args as needed.
Suppose you are logging messages that can have a varying number of attributes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const someMsg =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  { type: &amp;quot;WORKER_ERROR&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , action: &amp;quot;division&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , args: [123, 0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function logMessage(msg) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let logFmt = &amp;quot;%c[%s]%c - %c%s%c&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let logArgs =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [ &amp;quot;background: #242; color: #bada55&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    , msg.type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    , &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    , &amp;quot;background: #424; color: #c0ffee&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    , msg.action&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    , &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if (msg.action === &amp;quot;division&amp;quot;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    logFmt += &amp;quot;: %i &#x2F; %i&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    logArgs.push(msg.args[0]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    logArgs.push(msg.args[1]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  } else {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    logFmt += &amp;quot; with args %o&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    logArgs.push(msg.args);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; finally print it:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  console.log(logFmt, ...logArgs);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logMessage(someMsg);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;measuring-console-log&quot;&gt;Measuring console.log()&lt;&#x2F;h2&gt;
&lt;p&gt;Another thing to keep in mind when using &lt;code&gt;console.log&lt;&#x2F;code&gt; is that it is not free. It does come with a performance hit, how much exactly ? Lets measure it like we did for &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;how-fast-is-nothing&#x2F;&quot;&gt;requestAnimationFrame()&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;For this test I am going to print just 32 simple console.log messages. I know that this is not a lot, it actually is nothing when compared to using console.log on mousemove events or any other fast firing event, but it should be enough to test.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;performance.mark(&amp;quot;Before&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; print 32 lines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;for(let i = 0; i &amp;lt; 32; i++)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  console.log(&amp;quot;One of the simplest console.log() possible&amp;quot;, i);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;performance.mark(&amp;quot;After&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;performance.measure(&amp;quot;console.log&amp;quot;, &amp;quot;Before&amp;quot;, &amp;quot;After&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const totalTime = performance.getEntriesByType(&amp;quot;measure&amp;quot;)[0].duration;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;console.log(&amp;quot;console.log() in %ims&amp;quot;, totalTime);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;performance.clearMarks();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;performance.clearMeasures();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my Firefox Developer Edition (56.0b1) console it prints&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;console.log() in 15ms&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;15 milliseconds is &lt;em&gt;a lot&lt;&#x2F;em&gt; of time in a computer perspective, specially since we are just printing 32 messages, it is about 0.45ms per message.&lt;&#x2F;p&gt;
&lt;p&gt;To keep it in perspective here is the time it takes to parse a huge 128KB JSON string:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function jsonParseAndMeasure(jsonStr) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.mark(&amp;quot;jsonStart&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const json = JSON.parse(jsonStr);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.mark(&amp;quot;jsonEnd&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.measure(&amp;quot;JSON.parse&amp;quot;, &amp;quot;jsonStart&amp;quot;, &amp;quot;jsonEnd&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const totalTime = performance.getEntriesByType(&amp;quot;measure&amp;quot;)[0].duration;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  console.log(&amp;quot;JSON.parse in %ims&amp;quot;, totalTime);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.clearMarks();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.clearMeasures();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;jsonParseAndMeasure(&amp;quot;HUGE JSON STRING HERE&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For a 128KB JSON string it prints:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;JSON.parse in 0ms&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hmm... maybe that is not enough, lets increase it to a 2MB JSON string:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;JSON.parse in 0ms&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok... what about a 50MB JSON string ?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;JSON.parse in 17ms&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thats more like it. About the same time it took console.log to print 32 simple messages. There are a few attenuating factors for this in production, but it is good to keep this in mind when leaving those debugging messages in your production code ;)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;buffering-console-log&quot;&gt;Buffering console.log()&lt;&#x2F;h2&gt;
&lt;p&gt;There is an alternative if you have your reasons to use &lt;code&gt;console.log&lt;&#x2F;code&gt; in production code: buffering.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of printing each message as it comes, lets place them in an array and dump it in a single &lt;code&gt;console.log&lt;&#x2F;code&gt; call every second or so.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let buffer = [];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; use a log function instead of directly calling console.log:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function log(str, args) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  buffer.push({ str, args });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function printBuffer() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; start by copying the buffer and clearing it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const buf = buffer.slice(0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  buffer = [];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; dump the buffer in a single console.log call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if (buf.length &amp;gt; 0) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    let logStr = &amp;quot;&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    let logArgs = [];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buf.map(msg =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      logStr += &amp;quot;%s, %o\n&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      logArgs.push(msg.str);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      logArgs.push(msg.args);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    console.log(logStr, ...logArgs);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  setTimeout(printBuffer, 1000); &#x2F;&#x2F; run every 1000ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;printBuffer(); &#x2F;&#x2F; &amp;lt;- start it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That should save you some performance complaints. I hope it helps :)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bootstrapping rain</title>
        <published>2017-08-08T00:00:00+00:00</published>
        <updated>2017-08-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/bootstrapping-rain/"/>
        <id>https://hugodaniel.com/posts/bootstrapping-rain/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/bootstrapping-rain/">&lt;p&gt;It has passed a year and a couple of months since I started bootstrapping &quot;a painting web app&quot;. A lot has happened since that time, here is a quick TL;DR:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I am still living off my savings (with a bit of help explained bellow)&lt;&#x2F;li&gt;
&lt;li&gt;Increase in frequency and amplitude of the emotional roller-coaster highs and lows&lt;&#x2F;li&gt;
&lt;li&gt;I started learning how to dance &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=fbAbbodH7Dw&quot;&gt;kuduro&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=1VtDFi4m_PU&quot;&gt;kizomba and semba&lt;&#x2F;a&gt; to cope with 2&lt;&#x2F;li&gt;
&lt;li&gt;Had some unexpected expenses (teeth problems, car problems, general problems, problems problems, etc...)&lt;&#x2F;li&gt;
&lt;li&gt;Lots of noise&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Noise that I now take a careful distant look at and collide for you in this blog post by applying three different filters into it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-what-am-i-doing&quot;&gt;1. What am i doing ?&lt;&#x2F;h2&gt;
&lt;p&gt;Many signals exist in the noise, among these the strongest ones imply that I don&#x27;t have a clue about what I am doing. In life.&lt;&#x2F;p&gt;
&lt;p&gt;After all this time one of the hardest challenges I still have is explaining to a random person what the project is about. Come to think of it I haven&#x27;t even done it here, how could I avoid my personal blog ? that blog that I personaly chose to neglect. Wait no further, here it goes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&quot;A painting web app&quot;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is a really reducing way of explaining what the project is about. Specificity wise I put it right after of &lt;em&gt;&quot;It&#x27;s a programming project&quot;&lt;&#x2F;em&gt;, or &lt;em&gt;&quot;It&#x27;s a web page&quot;&lt;&#x2F;em&gt;. It doesn&#x27;t say much more than these and whenever I use it people stare at me with that awkward face that blends simpathy with honest disapointment.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Here is how it happened&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Back in the day I grew tired of my (many) wrong choices in life. This was particularly hard for me since I have always been a lover of what is wrong and bad. &quot;Wasting&quot; huge ammounts of time doing code for no reason&#x2F;purpose at all is not good and certainly not right. Investing years trying to produce CG code worthy of any unknown demoparty and their attendees acids. Realizing that I am not a good coder and still betting my life on the craft. Travelling through deserts only to hope &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.dailymotion.com&#x2F;video&#x2F;x67s70&quot;&gt;nobody sees my attempts at hoping to intoxicate with colors&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It is 5am.
Another cold winter morning in Lisbon enhanced by the summer optimized windows and walls of my 37m^2 home. The rain leaks through the windows and I move the small ikea table enough to protect the laptop from getting wet. I don&#x27;t know why I am forcing myself to wake up this early, perhaps knowing that the queue to heaven is shorter at this time of the day and that maybe god will allow my body and mind the grace of being numb for the rest of the working day.&lt;&#x2F;p&gt;
&lt;p&gt;I can see work blowing up somewhere later in the day, I can feel it devouring my brain. I need this time to breathe. The warm coffee smell keeps me awake, its scent rises above all the burn bruises my hands acquired in trying to make it half-awake. Maybe the blessing will rain down on me today.&lt;&#x2F;p&gt;
&lt;p&gt;I have been reading &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.redblobgames.com&#x2F;grids&#x2F;hexagons&#x2F;&quot;&gt;this article about hexagonal grids&lt;&#x2F;a&gt; for some time now. &lt;em&gt;Fuck! Why can&#x27;t I implement it right ? Why is programming so hard for me ?&lt;&#x2F;em&gt; I have been trying to do this for months now. I have no purpose in it besides avoiding the razors in my day.&lt;&#x2F;p&gt;
&lt;p&gt;Offset coordinates ? Cube coordinates ? &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dribbble.com&#x2F;search?q=grid&quot;&gt;If I was a designer what would I do ? What would I need ?&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Hmm....&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dribbble.com&#x2F;shots&#x2F;1483510-Mystery-Project-50&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;mystery_project.jpg&quot; alt=&quot;ZX Spectrum color palette&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It is 7am, my girlfriend will wake up at some point before 8. It is still dark outside, where did I leave the umbrella ? I go out to buy some hot bread to prepare our breakfast.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-holistic-approach&quot;&gt;2. Holistic approach&lt;&#x2F;h2&gt;
&lt;p&gt;Romance is a big part of bootstrapping.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-mentor&quot;&gt;3. Mentor&lt;&#x2F;h2&gt;
&lt;p&gt;In November 2016 the struggle to explain what the project is about led me to apply &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.iapmei.pt&#x2F;PRODUTOS-E-SERVICOS&#x2F;Empreendedorismo-Inovacao&#x2F;Empreendedorismo&#x2F;Startup-Voucher.aspx&quot;&gt;to a state sponsored funding&lt;&#x2F;a&gt;. In my mind I didn&#x27;t need the money since I was&#x2F;am living with low expenses on my savings, but they offered free access to a &quot;portuguese mentorship network&quot;. Mentorship that I knew that I could not afford and could not survive without. After answering their questions in a 22 page report I waited 5 months and got the response.&lt;&#x2F;p&gt;
&lt;p&gt;They liked the idea and decided to accept the project. I have been living the past 4 months with 690EUR&#x2F;month from them. This is enough to increase my life style, cover my expenses and still manage to save a bit each month.&lt;&#x2F;p&gt;
&lt;p&gt;The mentorship has been great. I was not expecting such a high quality work from the mentor that I chose from their huge list of available mentors.&lt;&#x2F;p&gt;
&lt;p&gt;I have since done the first prototype of the landing page for the graphic design web app &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.pixnit.com&quot;&gt;https:&#x2F;&#x2F;www.pixnit.com&lt;&#x2F;a&gt; and we have been focusing on applying this work on colors, grids and patterns on the ceramics industry (for a different, but related, product).&lt;&#x2F;p&gt;
&lt;p&gt;In september I will add a promotional video for the graphic design app and an open demo.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Palettes 0xF Fun</title>
        <published>2017-03-01T00:00:00+00:00</published>
        <updated>2017-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/16-palettes-of-fun/"/>
        <id>https://hugodaniel.com/posts/16-palettes-of-fun/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/16-palettes-of-fun/">&lt;p&gt;Like most of the country in the 80&#x27;s, Alenquer, the village where I was born, was trying to modernize itself in what can be considered an insurgence against its rural past.&lt;&#x2F;p&gt;
&lt;p&gt;The context of coming out from a strong harsh dictatorship and having recently joined the european comunity automatically made everyone who did not work a lazy person. Opportunities were everywhere. In fact this was so intense for the newer generations that working was not enough for them to avoid the &quot;lazy stigma&quot;. You had to explore, experiment, live and enjoy the &quot;new&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;I was 6 years old when my parents made their after dinner routine visit to a friends house with the usual purpose of drinking and talking about stuff that seemed to matter. What was supposed to be just another day in the company of friends changed my life forever.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&quot;I have finally bought the computer&quot;&lt;&#x2F;strong&gt;
he said, on the corridor table there was a box with a screen and keys to press.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&quot;It&#x27;s a schneider&quot;&lt;&#x2F;strong&gt;
He turned it on, typed some words on the keys and started a game. The first computer game I saw and got the chance to play.&lt;&#x2F;p&gt;
&lt;iframe width=&quot;280&quot; height=&quot;157&quot; src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;Q-y8dvsLYJM&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;p&gt;I had lots of questions in my mind after playing it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;How is it made ?&lt;&#x2F;li&gt;
&lt;li&gt;How does it move as i press the buttons ?&lt;&#x2F;li&gt;
&lt;li&gt;How are those colors drawn ?&lt;&#x2F;li&gt;
&lt;li&gt;How can i do it ?&lt;&#x2F;li&gt;
&lt;li&gt;Where can i get more of it ?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-world-is-dangerous&quot;&gt;The world is dangerous&lt;&#x2F;h2&gt;
&lt;p&gt;Slightly older kids were having a blast with the ZX spectrum.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;3&#x2F;33&#x2F;ZXSpectrum48k.jpg&quot; alt=&quot;ZX Spectrum computer&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It became quite famous in Portugal, companies were using it to ease some calculations, kids were pirating cassettes, and there were even local radio stations that used to broadcast entire games through the air (which you could then record in your cassette tape). Electronics done right.&lt;&#x2F;p&gt;
&lt;p&gt;The speccy sported an impressive 16 color palette (15 actually, the black is repeated).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;speccy_palette.png&quot; alt=&quot;ZX Spectrum color palette&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Apparently limited, these colors provided no limits to the fertile imagination of teens armed with a programming manual (the ZX Spectrum was sold with &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.worldofspectrum.org&#x2F;ZXBasicManual&#x2F;&quot;&gt;a programming manual&lt;&#x2F;a&gt; included and no ammount of words can be used to explain the social impact this had).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;paradise_cafe.png&quot; alt=&quot;Paradise Cafe - breaking portuguese cultural and legal concepts in the 80s&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Gravitating towards that tech and gaming oriented crowd made me later aware of a bunch of other computers that were also very important even though they were never famous here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;size-doesn-t-matter&quot;&gt;Size doesn&#x27;t matter&lt;&#x2F;h2&gt;
&lt;p&gt;The Amstrad CPC was a direct competitor of the Spectrum, it also had a base of 16 colors but expanded them into 27 in a &quot;high-resolution&quot; mode.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;cpc_spectrum.png&quot; alt=&quot;Amstrad vs Spectrum&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This was a clear upgrade in comparison to the 16-colors of Spectrum.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;strider.png&quot; alt=&quot;The game &amp;quot;Strider&amp;quot; in Spectrum(left) and in the Amstrad CPC(right)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In spite of having more colors this palette shies when put against the mother of all 8-bit computer 16 color palettes:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;C64-palette.png&quot; alt=&quot;The Commodore 64 color palette&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These 16 colors alone allow for an amazing expression (if you are into it &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;unusedino.de&#x2F;ec64&#x2F;technical&#x2F;misc&#x2F;vic656x&#x2F;colors&#x2F;&quot;&gt;here is a detailed article&lt;&#x2F;a&gt; on how to reproduce them in RGB).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;c64_cpc.png&quot; alt=&quot;C64 on the left, CPC on the right&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A kind soul used both color palettes (C64 and Amstrad CPC) to &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.indieretronews.com&#x2F;2016&#x2F;02&#x2F;is-c64-palette-far-superior-to-amstrad.html&quot;&gt;produce a set of comparison images&lt;&#x2F;a&gt;, the C64 images are more natural and its grays are better distributed which in turn allows for slightly more complex shadows.&lt;&#x2F;p&gt;
&lt;p&gt;All these color palettes were made to be reproduced in TV screens from the 80&#x27;s. Some even take in consideration B&amp;amp;W TV&#x27;s as full 24bit RGB was still a few years away from commodity hardware.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nowadays&quot;&gt;Nowadays&lt;&#x2F;h2&gt;
&lt;p&gt;Fast-forwarding for today, a &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;pixeljoint.com&#x2F;forum&#x2F;forum_posts.asp?TID=12795&quot;&gt;niche of people are still using 16 color palettes&lt;&#x2F;a&gt; and searching for possible combinations of colors that maximize expression. Most of these are related to &quot;pixel art&quot; communities and other minimalist art movements.&lt;&#x2F;p&gt;
&lt;p&gt;Truth is that there is a natural feeling in using colors in sets of 16 related elements. It gives you, the artist, a lot of paths to explore but not many enough to degrade the exploration experience into frustration.&lt;&#x2F;p&gt;
&lt;p&gt;As a final exercise I&#x27;ll leave three different loader screens for the same game. Try to see if you can guess which 8-bit computer is which.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;palette1.png&quot; alt=&quot;&quot; &#x2F;&gt;
&lt;img src=&quot;&#x2F;images&#x2F;palette2.png&quot; alt=&quot;&quot; &#x2F;&gt;
&lt;img src=&quot;&#x2F;images&#x2F;palette3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A new name to surf 2017</title>
        <published>2017-01-18T00:00:00+00:00</published>
        <updated>2017-01-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/surfing-2017/"/>
        <id>https://hugodaniel.com/posts/surfing-2017/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/surfing-2017/">&lt;p&gt;2016 was a year of change. I stopped working full-time as a programmer and decided to dedicate some of that time to personal projects. I made plans.
During the course of the year most of those plans got changed, a lot. My intention was to build &quot;paint.pt&quot;, a online painting tool, while supporting myself with some savings and with the money i could make by training people in programming skills.&lt;&#x2F;p&gt;
&lt;p&gt;I took teacher training and got a teacher certificate with the highest possible grade as i was full time on it.
Then got a few schools contacts that needed trainers for specific modules of some courses.&lt;&#x2F;p&gt;
&lt;p&gt;That was when I collided head-on with the portuguese reality of a fragile economy. I knew jobs were better here for programmers than for most other professions, so i was already somewhat mentally prepared to embrace a harsh reality.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-ll-pay-you-next-week&quot;&gt;&quot;I&#x27;ll pay you next week&quot;&lt;&#x2F;h2&gt;
&lt;p&gt;After a few courses money didn&#x27;t came. Excuses started to pile. It took a few months until the first bit of money appeared.&lt;&#x2F;p&gt;
&lt;p&gt;I ran to seek advice in a multitude of older, wiser people. What should i do ?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;Hugo all of this is normal, you have to understand that most companies are struggling economically.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;In portugal companies are trying to stay above water.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&quot;Don&#x27;t expect to be paid before 6 months.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I did try to extend my good will to parties that hire with the expectation of paying as late as possible.
The result of it was the realisation that ~10EUR&#x2F;hour isn&#x27;t enough for the time spent preparing the course, giving it and managing the debt until the employer decided to pay.&lt;&#x2F;p&gt;
&lt;p&gt;Time has come to scratch the initial plan and start fresh with a new strategy for 2017.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;change-of-name-change-of-plans&quot;&gt;Change of name, change of plans&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;What are you working on ?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;A painting application&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;Cool, whats it called ?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;paint.pt as in paint point&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;That already exists&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A new name for the project was needed, and that is how Pixnit showed up. Pixnit a simple name that reads as &quot;pixel knit&quot; which is exactly what i want the tool to do.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that people want to use custom shapes to create beautiful patterns and logos so that they can express themselves better and enhance current works, and that they will find value in it because trying to create logos, icons and patterns by using traditional software is hard and takes forever.&lt;&#x2F;p&gt;
&lt;p&gt;The domain was registered (pixnit.com) just in time for a complete change in strategy:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Take 1h each day to write in the blog;&lt;&#x2F;li&gt;
&lt;li&gt;Don&#x27;t work on anything else besides it and pixnit;&lt;&#x2F;li&gt;
&lt;li&gt;Push to release self contained small parts of pixnit as soon as possible;&lt;&#x2F;li&gt;
&lt;li&gt;Create a patreon;&lt;&#x2F;li&gt;
&lt;li&gt;Create a landing page;&lt;&#x2F;li&gt;
&lt;li&gt;Talk to people;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Lets see where this goes. So no more trainings, no more certifications, no more noise. Just pixnit.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How fast is nothing at all ?</title>
        <published>2016-09-23T00:00:00+00:00</published>
        <updated>2016-09-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/how-fast-is-nothing/"/>
        <id>https://hugodaniel.com/posts/how-fast-is-nothing/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/how-fast-is-nothing/">&lt;p&gt;One of the fastest functions that can be run inside &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;window&#x2F;requestAnimationFrame&quot;&gt;requestAnimationFrame&lt;&#x2F;a&gt; goes something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function fastest() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  window.requestAnimationFrame(fastest);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;window.requestAnimationFrame(fastest);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A simple no-op. It does nothing besides requesting to be called in another frame in order to do nothing besides requesting to be called in another frame, and so on.
A request for nothing that hopefully matches the speed of your monitor v-sync to hastily do just nothing.&lt;&#x2F;p&gt;
&lt;p&gt;Which gives us the perfect chance to use the most important skill we have in our life.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;giving-meaning-to-nothing&quot;&gt;Giving meaning to nothing&lt;&#x2F;h2&gt;
&lt;p&gt;Measuring the function can be done by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Performance&#x2F;mark&quot;&gt;placing marks&lt;&#x2F;a&gt; and then collecting them with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Performance&#x2F;measure&quot;&gt;performance.measure() function&lt;&#x2F;a&gt;. To avoid placing a mark every frame lets also count them and place it only once every 120 frames. My monitor updates at about 60Hz so this should place a mark every 2 seconds.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let count = 0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; ^ count each frame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function fastest() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  window.requestAnimationFrame(fastest);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  count += 1;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  if(count === 120) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    performance.mark(&amp;quot;120&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &#x2F;&#x2F; ^ place a mark in the 120th&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;performance.mark(&amp;quot;0&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; ^ place a mark before the first frame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;window.requestAnimationFrame(fastest);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;window.setTimeout(function() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; measure the duration between those two marks;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.measure(&amp;quot;120frames&amp;quot;, &amp;quot;0&amp;quot;, &amp;quot;120&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const measure = performance.getEntriesByType(&amp;quot;measure&amp;quot;)[0];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  console.log(&amp;quot;120 frames in: &amp;quot; + measure.duration);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}, 3000);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At 60fps we get around 16.7ms per frame, 120 frames should run in ~2000ms. Yet after 3 seconds this code prints &quot;120 frames in: 2148.415&quot; in the console.
This is 8% slower, making it closer to 55fps (18.2ms) than to 60fps(16.7ms).&lt;&#x2F;p&gt;
&lt;p&gt;If you thrive in the eccentricities of speed then those 1.5ms are simply unacceptable, lets try to understand what is happening by opening the &quot;Performance&quot; tab in the developer tools.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-eyes-are-the-window-of-the-soul-and-all-i-see-is-garbage&quot;&gt;The eyes are the window of the soul. And all i see is garbage.&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;measure1.png&quot; alt=&quot;Screenshot of the performance monitor of Firefox developer tools, it shows a maximum of 60 frames-per-second, a minimum 5.41 frames-per-second, and an average of 55.85 frames-per-second.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Those big drops in performance are related to the red dots of the Garbage Collector (from here on, just &quot;GC&quot;). They mark the time where GC woke up and run through the nursery of temporary objects to clean them.&lt;&#x2F;p&gt;
&lt;p&gt;These GC actions happen at the rate that the code fills the nursery heap with temporary objects. The browser then performs a small cleanup on the nursery heap and checks if some of those temporary objects can be promoted to the tenured heap.&lt;&#x2F;p&gt;
&lt;p&gt;The Tenured heap fills at a much lower rate than the Nursery and consequently the browser does not check it as often as the Nursery.&lt;&#x2F;p&gt;
&lt;p&gt;Lets try to promote all our short lived objects into something that might be selected to be tenured by the browser, thus reducing the time that the GC spends analyzing our running code and the nursery heap.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-execution-context-is-dead-long-live-the-execution-context&quot;&gt;The execution context is dead. Long live the execution context!&lt;&#x2F;h2&gt;
&lt;p&gt;My first approach is to remove the first invocation to the requestAnimationFrame() and place it inside a global closure in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Immediately-invoked_function_expression&quot;&gt;IIFE&lt;&#x2F;a&gt; style.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let count = 0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(function() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  function fastest() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    window.requestAnimationFrame(fastest);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count += 1;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if(count === 120) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      performance.mark(&amp;quot;120&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.mark(&amp;quot;0&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fastest();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ call the function directly for the first frame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; ^ IIFE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The idea here is to make the reference to the fastest() function explicitly last for the whole execution of the animation loop by wrapping it in a closure context that is immediatly called.&lt;&#x2F;p&gt;
&lt;p&gt;The next step is to remove all obvious objects allocations that happen inside our loop.
This means we need to remove all the strings (&quot;120&quot; is an object allocation) and all the numbers.&lt;&#x2F;p&gt;
&lt;p&gt;One of the great things about closures is that their execution context is available in their children, this means we can place the strings and numbers of our loop in vars in the long-lived closure context instead, making them live between our loop function calls.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(function () {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  let count = 0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const limit = 120;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const lastMark = &amp;quot;120&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const firstMark = &amp;quot;0&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ all vars go here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  function fastest() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    window.requestAnimationFrame(fastest);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count += 1;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if(count === limit) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      performance.mark(lastMark);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ when the fastest() context finishes there&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; are no obvious object allocations to free&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.mark(firstMark);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fastest();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; setTimeout remains the same, this is just for performance measure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;window.setTimeout(function() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  performance.measure(&amp;quot;120frames&amp;quot;, &amp;quot;0&amp;quot;, &amp;quot;120&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  const totalTime = performance.getEntriesByType(&amp;quot;measure&amp;quot;)[0].duration;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  console.log(&amp;quot;120 frames in: &amp;quot; + totalTime);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}, 3000);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;a-speed-freak-nighmare-is-a-control-junkie-best-dream&quot;&gt;A speed-freak nighmare is a control-junkie best dream&lt;&#x2F;h2&gt;
&lt;p&gt;That code above produces the string &quot;120 frames in: 1990.69&quot;. This is great, it says that our measures were taken before the 16.7ms frame time has passed.&lt;&#x2F;p&gt;
&lt;p&gt;Lets look at the performance tab:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;measure2.png&quot; alt=&quot;Screenshot of the performance monitor of Firefox developer tools, it shows a maximum of 60 frames-per-second, a minimum 38.98 frames-per-second, and an average of 57.66 frames-per-second.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Note that the Nursery is completely gone from our call-stack. There are still some red dots that mostly refer to the Cycle Collector (from here on, just &quot;CC&quot;) taking control of the code.&lt;&#x2F;p&gt;
&lt;p&gt;The CC does a simple job: it tracks cycles in the code.&lt;&#x2F;p&gt;
&lt;p&gt;A cycle happens when objects refer to each other in a way that their reference count never becomes zero. This can trick the GC to never collect them and forces the need to have a cycle counter running through the code once in a while.&lt;&#x2F;p&gt;
&lt;p&gt;The CC is a tricky beast, it does not allow anything else to run while it is running. Our JavaScript stops executing (you can validate this by increasing the zoom on the developer tools waterfall when a CC action occurs).&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately this is not hurting the performance that much and each frame gets rendered bellow their time by the browser. I was starting to have some chills with the idea of having to frame limit the render loop to ensure a constant frame rate.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully this Intel HD3000 is still good for Nothing at all :)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;intel.png&quot; alt=&quot;Screenshot of the chrome:&#x2F;&#x2F;gpu page list of problems. Currently chrome does not support WebGL in Intel HD3000 cards on OSX.&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Thanks &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;rqleve&quot;&gt;Raquel Foster&lt;&#x2F;a&gt; for reading this blog and motivating me to write this follow-up on &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;react-redux-canvas&#x2F;&quot;&gt;React-Redux-Canvas&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bootstrapping - getting some boots to strap</title>
        <published>2016-08-11T00:00:00+00:00</published>
        <updated>2016-08-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/bootstrapping4/"/>
        <id>https://hugodaniel.com/posts/bootstrapping4/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/bootstrapping4/">&lt;p&gt;A lot has happened since the last post on this series. Against all odds the portuguese football team won the Euro2016, their first international cup! Summer also hit us hard shortly after that, heavy migrations towards the south (algarve) and the &quot;fire season&quot; started, consuming the green portions of this rectangular land.&lt;&#x2F;p&gt;
&lt;p&gt;Amidst all of these events it became clear to me that i needed a backup plan in order to extend my window of development time for the paint.pt project.&lt;&#x2F;p&gt;
&lt;p&gt;So during the month of July i took a one month course in how to teach and give formation and got a &quot;certification of pedagogical competences&quot; (aka teaching certification). This was a great time, i learned a lot, practiced a lot and read a lot about teaching and group interactions.&lt;&#x2F;p&gt;
&lt;p&gt;Now i only need to start practicing it in a way that does not harm the time I have to work on paint.pt. Are you in need of some coding lessons ? :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;in-august&quot;&gt;In August&lt;&#x2F;h2&gt;
&lt;p&gt;August is a very special month in portuguese culture. Nothing happens in august. Everything stops and services work in half speed (which in most cases is a synonym to stop).&lt;&#x2F;p&gt;
&lt;p&gt;Not me, i&#x27;m not a big fan of crowded beaches and hope to take the time to restart coding on paint.pt (that almost stopped during july).&lt;&#x2F;p&gt;
&lt;p&gt;For this month of August my plan is to finish the menu system and start painting :D. I already finished the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.paint.pt&quot;&gt;logo and loading animation&lt;&#x2F;a&gt;. So stay tuned.&lt;&#x2F;p&gt;
&lt;p&gt;If you enjoy reading this please consider subscribing with your e-mail so we can stay in contact.&lt;&#x2F;p&gt;
&lt;p&gt;Check out the other &quot;bootstrapping&quot; posts: &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping1&#x2F;&quot;&gt;Bootstrapping 1&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping2&#x2F;&quot;&gt;Bootstrapping 2&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping3&#x2F;&quot;&gt;Bootstrapping 3&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bootstrapping - week 3</title>
        <published>2016-06-24T00:00:00+00:00</published>
        <updated>2016-06-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/bootstrapping3/"/>
        <id>https://hugodaniel.com/posts/bootstrapping3/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/bootstrapping3/">&lt;p&gt;This week was a blast! I took 3 days off and only worked thursday and friday.&lt;&#x2F;p&gt;
&lt;p&gt;This wasn&#x27;t entirely on purpose, my intention was not to have real &quot;vacations&quot;, but to enjoy the overall Lisbon party mood. Tuesday was also the first game of the portuguese football team in euro 2016.&lt;&#x2F;p&gt;
&lt;p&gt;Though i am not a football fan, i do like to watch the portuguese team play with the eventuality of seeing some magical moves by Cristiano Ronaldo.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;ronaldo.jpg&quot; alt=&quot;Cristiano Ronaldo 2012&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I know by experience that everything stops here in portugal when a big football match is going to happen. This is a strong motivator to go out drink some beers with friends in antecipation for the game.&lt;&#x2F;p&gt;
&lt;p&gt;It is important to note that a win by the home team is one of the best excuses to party hard. Unfortunately we did not win, it was a tie with Iceland, which meant no after party as a huge victory was expected.&lt;&#x2F;p&gt;
&lt;p&gt;Still it is better to enjoy the day than to stress with &quot;having something to do&quot;. Let the work be done on more appropriate days.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3rd-week&quot;&gt;3rd Week&lt;&#x2F;h2&gt;
&lt;p&gt;The two remaining work days i wrote the &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;react-redux-canvas&#x2F;&quot;&gt;introductory post&lt;&#x2F;a&gt; on &quot;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;redux-canvas&quot;&gt;redux-canvas&lt;&#x2F;a&gt; and release it on npm together with a simple usage example.&lt;&#x2F;p&gt;
&lt;p&gt;This is going to be the basis of the paint application as it allows canvas (which is crippled with side-effects) to be used directly in pure redux actions.&lt;&#x2F;p&gt;
&lt;p&gt;And it was it. If you enjoy reading this please consider subscribing with your e-mail so we can stay in contact (i will personally send you an e-mail).&lt;&#x2F;p&gt;
&lt;p&gt;Check out the other &quot;bootstrapping&quot; posts: &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping1&#x2F;&quot;&gt;Bootstrapping 1&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping2&#x2F;&quot;&gt;Bootstrapping 2&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping4&#x2F;&quot;&gt;Bootstrapping 4&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>React - Redux - Canvas</title>
        <published>2016-06-17T00:00:00+00:00</published>
        <updated>2016-06-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/react-redux-canvas/"/>
        <id>https://hugodaniel.com/posts/react-redux-canvas/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/react-redux-canvas/">&lt;p&gt;Painting stuff on a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;&#x2F;code&gt; is easy, call &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;HTMLCanvasElement&#x2F;getContext&quot;&gt;HTMLCanvasElement.getContext()&lt;&#x2F;a&gt; to get the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CanvasRenderingContext2D&quot;&gt;CanvasRenderingContext&lt;&#x2F;a&gt; and then use its functions to express yourself.&lt;&#x2F;p&gt;
&lt;p&gt;Doing an animation is also easy, call &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;window&#x2F;requestAnimationFrame&quot;&gt;window.requestAnimationFrame()&lt;&#x2F;a&gt; to tell the browser that you want to do an animation, and on it use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CanvasRenderingContext2D&quot;&gt;CanvasRenderingContext&lt;&#x2F;a&gt; to animate as you see fit (tipically clearing the part of the drawing that changed and painting the new version of it).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var canvasElem = document.getElementById(&amp;quot;canvas&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var w = window.innerWidth;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var h = window.innerHeight;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var rectSize = 256;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; set the canvas size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;canvasElem.setAttribute(&amp;quot;width&amp;quot;, w);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;canvasElem.setAttribute(&amp;quot;height&amp;quot;, h);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; get the context&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var ctx = canvasElem.getContext(&amp;quot;2d&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; the animation loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function animation(t) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  window.requestAnimationFrame(animation);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var time = t*0.001;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var cost = (Math.cos(time) + 1) &#x2F; 2;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var sint = (Math.sin(time) + 1) &#x2F; 2;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var rc = rectSize*cost;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var rs = rectSize*sint;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  var color = `rgb(${Math.round(cost*255)},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;               ${Math.round(sint*255)},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;               255)`;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ctx.fillStyle = color;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; a simple rectangle&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ctx.fillRect(rc, rs, rc, rs);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;window.requestAnimationFrame(animation);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;then-came-react&quot;&gt;Then came React&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;&quot;&gt;React&lt;&#x2F;a&gt; lets us use composable components of code and html elements to do our web apps of the future. To keep things running nicely it defines a common lifecycle for each component. The most simple version of it is that it &quot;mounts&quot; the component on the renderer and updates it when input changes.&lt;&#x2F;p&gt;
&lt;p&gt;The most used React DOM renderer is their official &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;react-dom&quot;&gt;&quot;react-dom&quot;&lt;&#x2F;a&gt;, it uses minimal stateless virtual DOM elements (called ReactElements) for your components and pushes them to the real DOM when appropriate.&lt;&#x2F;p&gt;
&lt;p&gt;A common approach of using only &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;&quot;&gt;React&lt;&#x2F;a&gt; to paint on a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;&#x2F;code&gt; is to render the element and fetch the context when it is mounted. Here is an example of a basic canvas component:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default class Canvas extends Component {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  componentDidMount() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    let canvas = findDOMNode(this.refs.canvas),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ctx = canvas.getContext(&amp;quot;2d&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    this.props.onContext(ctx);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  render() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const { width, height } = this.props;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const canvasCx = `Canvas ${this.props.className}`;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;canvas className={canvasCx} ref=&amp;quot;canvas&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              width={width + &amp;quot;px&amp;quot;} height={height + &amp;quot;px&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              style={ { display: &amp;quot;block&amp;quot; } }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Canvas.propTypes =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  { width:     PropTypes.number.isRequired&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , height:    PropTypes.number.isRequired&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , onContext: PropTypes.func.isRequired&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To increase reusability the context is passed to the parent component where it can be used by its developer sprawling moisture of creative juices.&lt;&#x2F;p&gt;
&lt;p&gt;Here is an example of a component that draws a simple grid using the Canvas component defined above.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import React, { Component, PropTypes } from &amp;quot;react&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import { findDOMNode }                 from &amp;quot;react-dom&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import Canvas                          from &amp;quot;.&#x2F;Canvas.jsx&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export default class GridCanvas extends Component {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  constructor(props, context) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    super(props, context);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    this.state = { ctx: null }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  _renderGrid() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const { color, lineWidth, squareSize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          , offsetX, offsetY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          , width, height&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          } = this.props;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const { ctx } = this.state;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &#x2F;&#x2F; adjust for vertical screens:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const limit = Math.max(width, height);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.beginPath();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.moveTo(0, 0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &#x2F;&#x2F; draw the horizontal lines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    for( let y = offsetY % squareSize; y &amp;lt; limit; y += squareSize) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ctx.moveTo(0, y);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ctx.lineTo(width, y);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &#x2F;&#x2F; draw the vertical lines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    for( var x = offsetX % squareSize; x &amp;lt; limit; x += squareSize) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ctx.moveTo(x, 0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ctx.lineTo(x, height);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.lineWidth = lineWidth;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.strokeStyle = color;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.stroke();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.closePath();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  render() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const { width, height, cursor, color } = this.props;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    const { ctx } = this.state;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if( ctx ) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &#x2F;&#x2F; canvas render commands go here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ctx.clearRect(0, 0, width, height);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      this._renderGrid();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;Canvas className={ `GridCanvas ${this.props.className}` }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              width={width} height={height}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              onContext={ ctx =&amp;gt; this.setState( { ctx } ) }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;GridCanvas.propTypes =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  { color:      PropTypes.string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ color for the stroke of the outline of the grid&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , lineWidth:  PropTypes.number&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ the width, in pixels, for the grid line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , offsetX:    PropTypes.number&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , offsetY:    PropTypes.number&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , cursor:     PropTypes.string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &#x2F;&#x2F; ^ the mouse cursor to use when mouse is over the grid&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , squareSize: PropTypes.number&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , width:      PropTypes.number.isRequired&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  , height:     PropTypes.number.isRequired&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;GridCanvas.defaultProps =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  { cursor: &amp;quot;default&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CanvasRenderingContext2D&quot;&gt;CanvasRenderingContext&lt;&#x2F;a&gt; is kept in the state and then used in render() to clear and draw the shapes. This way the code is run in sync with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;docs&#x2F;component-specs.html&quot;&gt;React DOM flow&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This works very well if you intend to draw single frame art, however since it is coping with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;docs&#x2F;component-specs.html&quot;&gt;React lifecycle flow&lt;&#x2F;a&gt; it might not be the best approach if you intend to have 60fps animations because the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;index.html&quot;&gt;React&lt;&#x2F;a&gt; logic will be running alongside your context drawing code in those precious 16ms of the frame.&lt;&#x2F;p&gt;
&lt;p&gt;You can try to optimize your &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;index.html&quot;&gt;React&lt;&#x2F;a&gt; UI with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;docs&#x2F;component-specs.html#updating-shouldcomponentupdate&quot;&gt;shouldComponentUpdate&lt;&#x2F;a&gt; and you should. But it is still going to contend when your UI hasn&#x27;t changed and all you want to do is to update the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;&#x2F;code&gt; with a master piece of an animation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;react-but-only-partially&quot;&gt;React, but only partially&lt;&#x2F;h2&gt;
&lt;p&gt;Luckily &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;index.html&quot;&gt;React&lt;&#x2F;a&gt; is not intrusive and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;package&#x2F;react-dom&quot;&gt;&quot;react-dom&quot;&lt;&#x2F;a&gt; is intended to be used along standard HTML&#x2F;JS code. This allows developers to only use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;index.html&quot;&gt;React&lt;&#x2F;a&gt; on certain parts of their website, the aspiring artist can then use it for most of the parts of the app and keep the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;&#x2F;code&gt; outside of its logic.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;doctype&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;React and Canvas&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;react-root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      &amp;lt;!--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; react goes here &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;div&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;canvas&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;animation&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;canvas&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#DC322F, #DC322F);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;https:&#x2F;&#x2F;fb.me&#x2F;react-15.0.1.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;https:&#x2F;&#x2F;fb.me&#x2F;react-dom-15.0.1.js&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;      var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; animNode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;animation&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;      var&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; animNode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getContext&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;2d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;      function&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; loop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        window&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;requestAnimationFrame&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; draw something on the canvas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      window&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;requestAnimationFrame&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; React renders on the &amp;quot;react-root&amp;quot; node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;      ReactDOM&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;render&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;MyApp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;react-root&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;html&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All is good if you don&#x27;t intend to make the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;&#x2F;code&gt; high-speed animation interact with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;index.html&quot;&gt;React&lt;&#x2F;a&gt; part of the code.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to communicate between the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;&#x2F;code&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;index.html&quot;&gt;React&lt;&#x2F;a&gt; then you will have to adopt some interaction strategy (e.g. passing a callback as a prop; using plain JS events; etc...).&lt;&#x2F;p&gt;
&lt;p&gt;However if you have been through the trenches, your battle proven developer experience is probably telling you that this is an optimization trade-off that will quickly grow into a pessimization.&lt;&#x2F;p&gt;
&lt;p&gt;State will most likely start to accumulate outside and inside of both parts as communication starts becoming more intricate and managing it will give you with many scars to heal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;redux-will-make-good-for-all-our-sins&quot;&gt;Redux will make good for all our sins&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;redux.js.org&#x2F;&quot;&gt;Redux&lt;&#x2F;a&gt; defines a unidirectional flow of data on your application. It uses a single store to hold the application state and allows it to be updated by a pure function that computes the next state based on the actions dispatched by the app. They call the pure function a &quot;reducer&quot; and you can have as many of them in your app as you want.&lt;&#x2F;p&gt;
&lt;p&gt;This is within the spirit of pure components: something that always produces the same output if fed with the same input. When used with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;facebook.github.io&#x2F;react&#x2F;index.html&quot;&gt;React&lt;&#x2F;a&gt; it opens the door to simpler optimized components with predictable state.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CanvasRenderingContext2D&quot;&gt;CanvasRenderingContext&lt;&#x2F;a&gt; is not pure, its functions rely on a bunch of inner state that can change outside of their scope. This makes it hard to master and to manage (on the other side it has sprawled a counteless number of JS libs to work with it).&lt;&#x2F;p&gt;
&lt;p&gt;It also makes it difficult to integrate with &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;redux.js.org&#x2F;&quot;&gt;Redux&lt;&#x2F;a&gt; which by design expects pure actions and state. It is useless to keep the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CanvasRenderingContext2D&quot;&gt;CanvasRenderingContext&lt;&#x2F;a&gt; in the store and update it with a reducer because its drawing functions will change it outside the pure flow of &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;redux.js.org&#x2F;&quot;&gt;Redux&lt;&#x2F;a&gt; actions.&lt;&#x2F;p&gt;
&lt;p&gt;To make things a bit worse, high-performance canvas applications &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;Canvas_API&#x2F;Tutorial&#x2F;Optimizing_canvas&quot;&gt;are encouraged&lt;&#x2F;a&gt; to follow a set of destructive&#x2F;impure practices which are hard to follow if using React&#x2F;Redux.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;introducing-redux-canvas&quot;&gt;Introducing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;redux-canvas&quot;&gt;redux-canvas&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;What if along with the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;redux.js.org&#x2F;&quot;&gt;Redux&lt;&#x2F;a&gt; actions that update an app pure state we could issue painting actions to be performed in the impure canvas context ?&lt;&#x2F;p&gt;
&lt;p&gt;This is what &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;redux-canvas&quot;&gt;redux-canvas&lt;&#x2F;a&gt; is meant to do. It allows you to keep your UI running purely with well defined components and their respective lifecycles, while giving you a shortcut to call functions on registered canvas contexts.&lt;&#x2F;p&gt;
&lt;p&gt;It is a &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;redux.js.org&#x2F;&quot;&gt;Redux&lt;&#x2F;a&gt; middleware that works by keeping a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Map&quot;&gt;Map()&lt;&#x2F;a&gt; of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;CanvasRenderingContext2D&quot;&gt;CanvasRenderingContext&lt;&#x2F;a&gt;&#x27;s that persist between redux actions, and then it passes the Map() to the functions you specify when dispatching the action.
These functions are called within a requestAnimationFrame().&lt;&#x2F;p&gt;
&lt;p&gt;This way your impure code will be playing together with the pure code without messing with it. You can keep your UI pure while playing with canvas as you see fit (perhaps even trying to keep it pure as well).&lt;&#x2F;p&gt;
&lt;p&gt;In the next post I will write some usage examples with animations and also create a few helper functions to ease the usage of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;redux-canvas&quot;&gt;redux-canvas&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Meanwhile checkout my take on &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;mastering-console-log&#x2F;&quot;&gt;console.log()&lt;&#x2F;a&gt;, a quick look into &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;in-loving-memory-of-immutable&#x2F;&quot;&gt;ImmutableJS&lt;&#x2F;a&gt; and my performance measurements on &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;how-useful-is-the-javascript-set&#x2F;&quot;&gt;JavaScript Set&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bootstrapping - week 2</title>
        <published>2016-06-16T00:00:00+00:00</published>
        <updated>2016-06-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/bootstrapping2/"/>
        <id>https://hugodaniel.com/posts/bootstrapping2/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/bootstrapping2/">&lt;p&gt;Lisbon is in party, this year the anual city holiday is happening in sync with a national holiday.&lt;&#x2F;p&gt;
&lt;p&gt;This means the common Lisbon worker will get 4 days of paid holiday for free :)&lt;&#x2F;p&gt;
&lt;p&gt;The Lisbon party actually lasts for 2 whole weeks, where you can dance and sing a blend of new-age cheesy pop music. Most of the fun happens during the night.&lt;&#x2F;p&gt;
&lt;p&gt;In order to carry 3 extra days of holidays for the next week (this way i would be able to recover from sunday night) i decided to work for 7 days on my 2nd week (through the weekend).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;sardinha.jpg&quot; alt=&quot;Lisbon party sardine 2016&quot; title=&quot;Uma sardinha das que se comem com os olhos&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2nd-week&quot;&gt;2nd Week&lt;&#x2F;h2&gt;
&lt;p&gt;In the beginning of the week i opened a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;paintpoint&#x2F;paintpt&#x2F;issues&#x2F;2&quot;&gt;ticket&lt;&#x2F;a&gt; to render a simple square grid on the canvas. This was supposed to be a simple task but it took me a bit to complete.&lt;&#x2F;p&gt;
&lt;p&gt;What would be a good way to render to canvas using react&#x2F;redux ?&lt;&#x2F;p&gt;
&lt;p&gt;What would be a good data type for the paint app ?&lt;&#x2F;p&gt;
&lt;p&gt;How would it interact with the canvas and the react&#x2F;redux logic ?&lt;&#x2F;p&gt;
&lt;p&gt;These questions made me start a new sub-project that i named &quot;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;HugoDaniel&#x2F;redux-canvas&quot;&gt;redux-canvas&lt;&#x2F;a&gt;&quot;. It is yet another way to draw on the canvas using react&#x2F;redux.&lt;&#x2F;p&gt;
&lt;p&gt;By the end of the week (sunday, 12) i did not yet had it finished or published, but stay tuned (subscribe please) because a more thorough blog post about all of this is on the way.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t forget to subscribe and checkout the other &quot;bootstrapping&quot; posts: &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping1&#x2F;&quot;&gt;Bootstrapping 1&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping3&#x2F;&quot;&gt;Boostrapping 3&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping4&#x2F;&quot;&gt;Bootstrapping 4&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bootstrapping - week 1</title>
        <published>2016-06-06T00:00:00+00:00</published>
        <updated>2016-06-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/bootstrapping1/"/>
        <id>https://hugodaniel.com/posts/bootstrapping1/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/bootstrapping1/">&lt;p&gt;Two months have passed since i quit my job with the plan of taking some time to develop a few ideas that have outgrown me enough to earn the respect of a full-time dedication.&lt;&#x2F;p&gt;
&lt;p&gt;This &quot;Bootstrapping&quot; post is the first in a series of posts about a quest to a sustainable monthly income.&lt;&#x2F;p&gt;
&lt;p&gt;To start i am going to do a painting web application. A simple web app to paint points in a canvas. I call it &quot;paint.pt&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1st-week&quot;&gt;1st Week&lt;&#x2F;h2&gt;
&lt;p&gt;The week went about fine, in the first days i learned a bit more about JavaScript in order to understand if a framework would be necessary for paint.pt.&lt;&#x2F;p&gt;
&lt;p&gt;After some thinking, a bit of research and some rough implementations of what i thought would be the corner cases of it, i decided to pass the oportunity to use pure JavaScript and use react instead.&lt;&#x2F;p&gt;
&lt;p&gt;By the time of this writing i am living in the year 2016. That means the rest of the week was spent configuring a react&#x2F;redux&#x2F;immutable&#x2F;webpack&#x2F;mocha&#x2F;selenium&#x2F;babel&#x2F;flow&#x2F;eslint boilerplate repository for it.&lt;&#x2F;p&gt;
&lt;p&gt;By the end of the week i realized that the sun was shining outside and so i went for a walk in Lisbon to read a few chapters of the git book.&lt;&#x2F;p&gt;
&lt;p&gt;That was it.&lt;&#x2F;p&gt;
&lt;p&gt;Check out the other &quot;bootstrapping&quot; posts: &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping2&#x2F;&quot;&gt;Bootstrapping 2&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping3&#x2F;&quot;&gt;Bootstrapping 3&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;hugodaniel.com&#x2F;posts&#x2F;bootstrapping4&#x2F;&quot;&gt;Bootstrapping 4&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>about me</title>
        <published>2016-04-09T00:00:00+00:00</published>
        <updated>2016-04-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hugodaniel.com/posts/about/"/>
        <id>https://hugodaniel.com/posts/about/</id>
        
        <content type="html" xml:base="https://hugodaniel.com/posts/about/">&lt;p&gt;Hi, I am Hugo, from the ancient end of the world.&lt;&#x2F;p&gt;
&lt;p&gt;Nowdays it is still the end of the world but everybody just calls it Portugal.&lt;&#x2F;p&gt;
&lt;p&gt;I was born in Alenquer, a village near Lisbon.&lt;&#x2F;p&gt;
&lt;p&gt;I love poetry and most likely this blog will turn to be a poetry blog about my ramblings.&lt;&#x2F;p&gt;
&lt;p&gt;I also like photography and I tend to avoid the fact that I am a terrible photographer.&lt;&#x2F;p&gt;
&lt;p&gt;But unfortunately I spend all my days programming, something that I love and hate at the same time.&lt;&#x2F;p&gt;
&lt;img class=&quot;image&quot; src=&quot;&#x2F;images&#x2F;alenquer.jpg&quot; alt=&quot;Imagem de alenquer a preto e branco&quot; &#x2F;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cenasdohugo.blogspot.com&quot;&gt;poesia&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.github.com&#x2F;HugoDaniel&quot;&gt;github&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.twitter.com&#x2F;mr_hugo&quot;&gt;twitter&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.hugodaniel.pt&#x2F;atom.xml&quot;&gt;rss&lt;&#x2F;a&gt;
e-mail: mail [[at]] hugodaniel.pt&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
