
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Casual Programming RSS Feed]]></title><description><![CDATA[Casual Programming, the Jurgo's tech blog.]]></description><link>https://casual-programming.com</link><generator>GatsbyJS</generator><lastBuildDate>Wed, 17 Dec 2025 13:58:45 GMT</lastBuildDate><item><title><![CDATA[Types in Typescript should make your life easier]]></title><description><![CDATA[Type systems are great, but it depends how you use them. I see often developers obsessed with name conventions or pattern design…]]></description><link>https://casual-programming.com/20251217_types_in_typescript_should_make_your_life_easier/</link><guid isPermaLink="false">https://casual-programming.com/20251217_types_in_typescript_should_make_your_life_easier/</guid><pubDate>Wed, 17 Dec 2025 11:37:00 GMT</pubDate><content:encoded>&lt;p&gt;Type systems are great, but it depends how you use them. I see often developers obsessed with name conventions or pattern design architectures, but not very often to tackle what matters.
what it matters to me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most real failures come from I/O: environment variables, network boundaries, databases, and external APIs. If someone changes a function inside your codebase, you’ll see it in reviews or tests. If an external API changes its payload shape, you often only discover it in production. If you forgot and env vars, your be may not start up after the deployment, if your react client got the wrong response, it may not render your page correctly and so on. A good coding and testing style prioritizes &lt;strong&gt;validating I/O early, explicitly, and at the boundaries&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Defining and mantaining Types should not be a lot of “manual” works and it should be driven by the compiler, not from you hammering differnt types to keep them in sync. There are some rules you can follow.&lt;/li&gt;
&lt;li&gt;You should know as many think as possible at compile time. if you are using Typescript for evertying and you have a  monorepo, then if infra code breaks the be code (let’s say due to an env var change), you should know it at compile time. if the backend change the contract and breaks the render of  the frontend , you should know it at compile time,an so on..&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Zod Is the De‑Facto Standard&lt;/h2&gt;
&lt;p&gt;In the TypeScript ecosystem, &lt;strong&gt;Zod is effectively the de‑facto standard&lt;/strong&gt; for runtime validation that stays aligned with static types.&lt;/p&gt;
&lt;p&gt;Zod:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Synchronizes runtime checks and TypeScript inference&lt;/li&gt;
&lt;li&gt;Makes failures explicit&lt;/li&gt;
&lt;li&gt;Pushes errors to the &lt;em&gt;leafs&lt;/em&gt; of the system, where unknown data enters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Prefer &lt;strong&gt;Zod‑compatible libraries&lt;/strong&gt; so validation remains consistent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Network contracts: &lt;code class=&quot;language-text&quot;&gt;ts-rest&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;tRPC&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Environment variables: Zod schemas parsed at startup&lt;/li&gt;
&lt;li&gt;Databases: Drizzle + Zod for inputs/outputs&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Validate What You Don’t Control&lt;/h2&gt;
&lt;p&gt;If someone changes a function in your codebase, you’ll notice.&lt;br&gt;
If an external system changes its behavior, you won’t—unless you validate.&lt;/p&gt;
&lt;p&gt;Typical I/O boundaries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;Network requests and responses&lt;/li&gt;
&lt;li&gt;Database reads/writes&lt;/li&gt;
&lt;li&gt;Third‑party APIs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fail fast, close to the source.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Never Use &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Never use &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;.&lt;/strong&gt;&lt;br&gt;
If you don’t know the shape, use &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; and narrow it.&lt;/p&gt;
&lt;p&gt;If you know &lt;em&gt;something&lt;/em&gt;, encode it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;Record&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This forces assumptions to be proven instead of silently trusted.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Strings Are Overused&lt;/h2&gt;
&lt;p&gt;A user ID is not “just a string”. It’s a &lt;strong&gt;UserId&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Use branded types:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; UserId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;uuid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;brand&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;UserId&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; UserId&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Reuse branded identifiers everywhere. This prevents accidentally mixing unrelated strings across your domain.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Avoid Enums: They Kill Composability&lt;/h2&gt;
&lt;p&gt;TypeScript &lt;code class=&quot;language-text&quot;&gt;enum&lt;/code&gt;s reduce composability and flexibility.&lt;/p&gt;
&lt;p&gt;Prefer literal unions (or &lt;code class=&quot;language-text&quot;&gt;as const&lt;/code&gt; arrays) instead. They:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compose naturally&lt;/li&gt;
&lt;li&gt;Work cleanly with Zod&lt;/li&gt;
&lt;li&gt;Avoid runtime artifacts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to enforce this, enable:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;erasableSyntaxOnly&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt;Prefer &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; Over &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Interfaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don’t compose as well&lt;/li&gt;
&lt;li&gt;Encourage inheritance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Prefer &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; aliases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better with unions and intersections&lt;/li&gt;
&lt;li&gt;More aligned with functional domain modeling&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Strict Types Aren’t Expensive — Duplication Is&lt;/h2&gt;
&lt;p&gt;Most “types are expensive” complaints come from duplication.&lt;/p&gt;
&lt;p&gt;Model relationships and derive types instead of redefining them.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  dob&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserDob&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; CreateUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; User&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;omit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ModifyUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; CreateUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Derivation keeps refactors cheap and models consistent.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Use Discriminated Unions&lt;/h2&gt;
&lt;p&gt;Discriminated unions make invalid states unrepresentable.&lt;/p&gt;
&lt;h3&gt;Zod Example&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; z &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zod&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; WithOpeningDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  openingDateStatus&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;available&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  opening_date&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; NoOpeningDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  openingDateStatus&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;notav&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; CommonForm &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  title&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  description&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;discriminatedUnion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;openingDateStatus&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  CommonForm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;WithOpeningDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  CommonForm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NoOpeningDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Form&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; Form&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Both runtime and compile‑time validation now agree.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Explicit Environment Variable Validation&lt;/h2&gt;
&lt;p&gt;Validate environment variables at startup. Fail loudly.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; z &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zod&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Stages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;union&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;local&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;dev&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;staging&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;prod&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; DatabaseUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;union&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;literal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;:inmemory:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; EnvSchema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;STAGE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Stages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;AWS_REGION&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;DATABASE_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; DatabaseUrl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;:inmemory:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parsedEnv &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; EnvSchema&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parsedEnv&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; envVarsConfig &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; parsedEnv&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Do not lazily validate config later.&lt;/strong&gt;&lt;br&gt;
Delayed validation leads to opaque runtime failures.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Share Types in a Monorepo&lt;/h2&gt;
&lt;p&gt;If you use a monorepo, &lt;strong&gt;share your types&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Share env var schemas between infra and backend&lt;/li&gt;
&lt;li&gt;Share domain models between backend and frontend&lt;/li&gt;
&lt;li&gt;Share network contracts between server and client&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This prevents drift.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Network Validation with ts‑rest&lt;/h2&gt;
&lt;p&gt;Use &lt;code class=&quot;language-text&quot;&gt;ts-rest&lt;/code&gt; on both server and client so the network boundary is typed &lt;em&gt;and&lt;/em&gt; validated.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zod defines the contract&lt;/li&gt;
&lt;li&gt;The server validates requests and responses&lt;/li&gt;
&lt;li&gt;The client is type‑safe by construction&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No duplicated DTOs. No guessing.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Minimal Monorepo Example (Conceptual)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zod (schemas)&lt;/li&gt;
&lt;li&gt;ts-rest (network)&lt;/li&gt;
&lt;li&gt;Express (server)&lt;/li&gt;
&lt;li&gt;Drizzle (database)&lt;/li&gt;
&lt;li&gt;React (client)&lt;/li&gt;
&lt;li&gt;CDK (infra)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Shared package&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Domain schemas&lt;/li&gt;
&lt;li&gt;Env var schemas&lt;/li&gt;
&lt;li&gt;API contracts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parses env vars using shared schema&lt;/li&gt;
&lt;li&gt;Validates network input via ts-rest&lt;/li&gt;
&lt;li&gt;Uses Drizzle for typed DB access&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Uses ts-rest client generated from shared contract&lt;/li&gt;
&lt;li&gt;Uses shared Zod schemas for input validation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Infra (CDK)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reuses env var definitions from shared package&lt;/li&gt;
&lt;li&gt;Avoids config drift&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Final Takeaways&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Types are great, but &lt;strong&gt;I/O validation is critical&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Validate what you don’t control&lt;/li&gt;
&lt;li&gt;Zod is the de‑facto standard&lt;/li&gt;
&lt;li&gt;Never use &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Avoid enums&lt;/li&gt;
&lt;li&gt;Prefer &lt;code class=&quot;language-text&quot;&gt;type&lt;/code&gt; over &lt;code class=&quot;language-text&quot;&gt;interface&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use branded types for domain identifiers&lt;/li&gt;
&lt;li&gt;Derive related schemas instead of duplicating them&lt;/li&gt;
&lt;li&gt;Use discriminated unions&lt;/li&gt;
&lt;li&gt;Share schemas and contracts across your monorepo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Strong types plus explicit runtime validation lead to predictable systems and far fewer production surprises.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Progressive React: When Your App Still Works with JS Disabled]]></title><description><![CDATA[In the last year, I worked extensively with Remix and React Router 7, and I have to say it was a genuinely pleasant experience. If you’re a…]]></description><link>https://casual-programming.com/20250726_progressive-react-when-your-app-still-works-with-js-disabled/</link><guid isPermaLink="false">https://casual-programming.com/20250726_progressive-react-when-your-app-still-works-with-js-disabled/</guid><pubDate>Sat, 26 Jul 2025 19:37:00 GMT</pubDate><content:encoded>&lt;p&gt;In the last year, I worked extensively with Remix and React Router 7, and I have to say it was a genuinely pleasant experience. If you’re a seasoned web developer like me—someone who was there when AJAX was becoming a thing and struggled to make websites work both with and without JavaScript enabled—you’ll really appreciate the evolution of React Router.&lt;/p&gt;
&lt;p&gt;To demonstrate these concepts, I built a Matrix chat application that works almost entirely without JavaScript. &lt;strong&gt;You can try it yourself at &lt;a class=&quot;siteLink&quot; href=&quot;https://matrix-chat.fly.dev&quot; title=&quot;https://matrix-chat.fly.dev&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://matrix-chat.fly.dev&lt;/a&gt;&lt;/strong&gt; - disable JavaScript in your browser and see how everything works: registration, login, room creation, browsing rooms, and sending messages. The only thing that won’t work is seeing new messages from other users in real-time—you’ll need to refresh the page for that. Then re-enable JavaScript to get the enhanced real-time synchronization.&lt;/p&gt;
&lt;h2&gt;Why This Matters: Beyond Just “Working Without JavaScript”&lt;/h2&gt;
&lt;p&gt;The point of building apps that work without JavaScript isn’t just about supporting users who have disabled JavaScript—though that’s important. The real benefits are more practical and impactful:&lt;/p&gt;
&lt;h3&gt;Escaping the Uncanny Valley&lt;/h3&gt;
&lt;p&gt;The most compelling reason is &lt;strong&gt;performance and user experience&lt;/strong&gt;. In poor network conditions, your JavaScript bundle might take 10-15 seconds to download and parse. During this time, users are stuck in an “uncanny valley”—they can see your app, but nothing works when they click. Buttons don’t respond, forms don’t submit, links don’t navigate. This can last much longer than you think, especially on slower devices or networks.&lt;/p&gt;
&lt;p&gt;With progressive enhancement, your app is immediately functional. Users can start accomplishing their goals right away, even if the enhanced features haven’t loaded yet.&lt;/p&gt;
&lt;h3&gt;Real Performance Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Faster Time to Interactive (TTI)&lt;/strong&gt;: Core functionality is available before JavaScript loads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced Cumulative Layout Shift (CLS)&lt;/strong&gt;: Server-rendered content is stable and complete&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better First Contentful Paint (FCP)&lt;/strong&gt;: No waiting for client-side rendering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resilient to JavaScript failures&lt;/strong&gt;: If your bundle fails to load or throws an error, the app still works&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Accessibility by Default&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Screen readers work immediately&lt;/strong&gt;: Server-rendered HTML is immediately accessible to assistive technologies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyboard navigation&lt;/strong&gt;: Standard HTML elements provide built-in keyboard support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low-powered devices&lt;/strong&gt;: Older devices that struggle with heavy JavaScript can still use the app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Assistive technology compatibility&lt;/strong&gt;: Progressive enhancement ensures compatibility with a wider range of accessibility tools&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;SEO and Crawlability&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Search engines get real content&lt;/strong&gt;: No waiting for JavaScript to render content&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Social media previews work&lt;/strong&gt;: Open Graph tags and meta descriptions are immediately available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web scrapers and bots&lt;/strong&gt;: Third-party tools can access your content without executing JavaScript&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Developer Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easier debugging&lt;/strong&gt;: You can isolate server-side vs client-side issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simpler testing&lt;/strong&gt;: Core functionality can be tested without complex JavaScript environments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Better error boundaries&lt;/strong&gt;: Server-side errors are handled gracefully, client-side errors don’t break core functionality&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Philosophy: Progressive Enhancement as Modern Best Practice&lt;/h2&gt;
&lt;p&gt;This approach represents a return to web fundamentals, but with modern tools that make it sustainable. HTML provides structure, CSS provides presentation, and JavaScript provides behavior enhancement. The magic happens when these technologies work together harmoniously, with each layer gracefully degrading when the next isn’t available.&lt;/p&gt;
&lt;p&gt;Modern React development, especially with server-side rendering and React Server Components, is essentially a sophisticated evolution of this principle. We’re not abandoning the separation of concerns; we’re redefining what those concerns are. Instead of separating HTML, CSS, and JavaScript, we’re now separating server and client responsibilities.&lt;/p&gt;
&lt;h2&gt;About the Matrix Protocol&lt;/h2&gt;
&lt;p&gt;For this project, I didn’t want to build a chat backend from scratch—I just needed a backend-for-frontend. So I leveraged the Matrix Protocol (&lt;a class=&quot;siteLink&quot; href=&quot;https://matrix.org/&quot; title=&quot;https://matrix.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://matrix.org/&lt;/a&gt;), an open standard for real-time communication. This meant I could simply run a Docker image to have a fully functional chat server available.&lt;/p&gt;
&lt;p&gt;Matrix is particularly interesting for this demonstration because it provides a real-world API that supports both REST endpoints and real-time features. This gives us the perfect opportunity to showcase how React Router 7 handles both traditional form submissions (which work without JavaScript) and enhanced real-time features (which require JavaScript for polling or WebSocket connections).&lt;/p&gt;
&lt;h2&gt;React Router 7: The Bridge Between Server and Client&lt;/h2&gt;
&lt;p&gt;If you’re already familiar with React Router or Remix, feel free to skip this section—but if you’re new to this paradigm, understanding these concepts is crucial to appreciating the progressive enhancement approach.&lt;/p&gt;
&lt;h3&gt;The Anatomy of a Route&lt;/h3&gt;
&lt;p&gt;In React Router 7, a route is a file that contains everything needed for a page. Think of it as a complete page definition with three key parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;loader&lt;/code&gt;&lt;/strong&gt; → Executes on the server when the page is accessed with a GET request&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;action&lt;/code&gt;&lt;/strong&gt; → Executes on the server when the page receives non-GET requests (POST, DELETE, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;default export&lt;/code&gt;&lt;/strong&gt; → The UI component that renders both server-side and client-side&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Server vs. Client Execution&lt;/h3&gt;
&lt;p&gt;Here’s where it gets interesting: everything runs on the server first, except for React’s &lt;code class=&quot;language-text&quot;&gt;useEffect&lt;/code&gt; hooks. The default export (your React component) runs in both environments, but with an important distinction:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Server-side&lt;/strong&gt;: Everything executes except &lt;code class=&quot;language-text&quot;&gt;useEffect&lt;/code&gt; hooks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client-side&lt;/strong&gt;: The component is hydrated with server data, then &lt;code class=&quot;language-text&quot;&gt;useEffect&lt;/code&gt; hooks execute&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This dual execution model is what enables progressive enhancement—your app works completely without JavaScript, but gains enhanced interactivity when JavaScript is available.&lt;/p&gt;
&lt;h3&gt;A Practical Example&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LoaderFunctionArgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ActionFunctionArgs &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react-router&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Form&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; useLoaderData&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; useNavigation &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react-router&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Runs on server for GET requests&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; params &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; LoaderFunctionArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; messages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchMessages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;roomId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; messages &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Runs on server for POST/PUT/DELETE requests&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; request &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ActionFunctionArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sendMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Runs on both server and client&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ChatRoom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; messages &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useLoaderData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; loader&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; navigation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNavigation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// This runs on both server and client&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Rendering chat room&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// This ONLY runs on the client&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Setting up real-time polling&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; interval &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setInterval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pollForNewMessages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clearInterval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;messages&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;messages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;/* This form works with or without JavaScript */&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Form method&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt; placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Type a message...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt; disabled&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Sending...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Send&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Form&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Key Components and Hooks&lt;/h3&gt;
&lt;p&gt;React Router provides several crucial components that enable progressive enhancement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;Form&gt;&lt;/code&gt;&lt;/strong&gt; → Creates forms that work both with and without JavaScript&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;Link&gt;&lt;/code&gt;&lt;/strong&gt; → Navigation that enhances to client-side routing when JavaScript is available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;useLoaderData()&lt;/code&gt;&lt;/strong&gt; → Access server-loaded data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;useNavigation()&lt;/code&gt;&lt;/strong&gt; → Track form submission and navigation states for enhanced UX&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Progressive Enhancement in Practice&lt;/h2&gt;
&lt;p&gt;The beauty of this approach becomes clear when you see how fundamental web features are handled. Let’s examine how key functionality works both with and without JavaScript:&lt;/p&gt;
&lt;h3&gt;Without JavaScript: Nearly Full Functionality&lt;/h3&gt;
&lt;p&gt;When JavaScript is disabled, the chat application works almost completely because it relies on fundamental web technologies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User registration and login&lt;/strong&gt; → Forms submit via HTTP POST with server-side authentication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Room creation&lt;/strong&gt; → Standard form submission creates new Matrix rooms&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Room browsing and search&lt;/strong&gt; → GET requests with URL parameters for filtering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Message sending&lt;/strong&gt; → Forms post messages to the Matrix server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Navigation&lt;/strong&gt; → All links work as traditional page navigations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server-side rendering&lt;/strong&gt; → Every page loads with complete HTML content and styling&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The only missing feature&lt;/strong&gt;: Real-time message updates from other users. You’ll need to refresh the page to see new messages. Everything else works exactly the same.&lt;/p&gt;
&lt;h3&gt;With JavaScript: Enhanced Experience&lt;/h3&gt;
&lt;p&gt;When JavaScript is available, the same foundation gets enhanced:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Forms become AJAX calls&lt;/strong&gt; → Smooth, in-page submission without full page reloads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Navigation becomes client-side routing&lt;/strong&gt; → Instant page transitions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real-time updates&lt;/strong&gt; → Polling or WebSocket connections for live message updates&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loading states&lt;/strong&gt; → Visual feedback during form submissions and navigation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Feature Comparison: Matrix Chat Implementation&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Traditional SPA Approach&lt;/th&gt;
&lt;th&gt;React Router 7 Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Login/Register&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Form submission blocked, AJAX call, manual redirect handling&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;Form&gt;&lt;/code&gt; component, server &lt;code class=&quot;language-text&quot;&gt;action&lt;/code&gt;, automatic redirect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Create Room&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client-side form submission, loading states, error handling&lt;/td&gt;
&lt;td&gt;Server &lt;code class=&quot;language-text&quot;&gt;action&lt;/code&gt; with built-in validation and redirect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Search Rooms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Debounced client-side search, manual state management&lt;/td&gt;
&lt;td&gt;URL-based search with server &lt;code class=&quot;language-text&quot;&gt;loader&lt;/code&gt;, automatic caching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Room Messages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;useEffect fetch, manual polling, complex state sync&lt;/td&gt;
&lt;td&gt;Server &lt;code class=&quot;language-text&quot;&gt;loader&lt;/code&gt; + client-side polling with &lt;code class=&quot;language-text&quot;&gt;useEffect&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Implementation Deep Dive&lt;/h2&gt;
&lt;p&gt;Let’s examine how each feature was implemented using React Router 7 patterns, showing the actual code that makes progressive enhancement work.&lt;/p&gt;
&lt;h3&gt;Login/Register&lt;/h3&gt;
&lt;p&gt;The authentication system demonstrates the power of &lt;code class=&quot;language-text&quot;&gt;action&lt;/code&gt; functions and progressive form handling. The same form works with and without JavaScript:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// app/routes/login.tsx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; request &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; LoaderFunctionArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cookieHeader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cookie&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; token &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getTokenFromCookie&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cookieHeader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Redirect if already authenticated&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; request &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ActionFunctionArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; intent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;intent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; password &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;intent &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;login&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;matrixUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/_matrix/client/v3/login&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/json&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;m.login.password&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; username&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        password&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; password&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; access_token &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token string-property property&quot;&gt;&quot;Set-Cookie&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUserSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;access_token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Invalid credentials&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; navigation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNavigation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; actionData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useActionData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; action&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Form method&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;username&quot;&lt;/span&gt; placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Username&quot;&lt;/span&gt; required &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;password&quot;&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;password&quot;&lt;/span&gt; placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Password&quot;&lt;/span&gt; required &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;intent&quot;&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;login&quot;&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt; 
              disabled&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Signing in...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Sign In&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;intent&quot;&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;register&quot;&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        Register
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;actionData&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;actionData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Form&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Why this works progressively:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Without JS&lt;/strong&gt;: Form submits via HTTP POST, page refreshes with results&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;With JS&lt;/strong&gt;: Enhanced with loading states and no page refresh&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server-side&lt;/strong&gt;: Authentication logic runs on the server, cookies are secure&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Create Room&lt;/h3&gt;
&lt;p&gt;Room creation shows how server actions can handle complex API integrations while maintaining form simplicity:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// app/routes/createroom.tsx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; request &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ActionFunctionArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; token &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requireUserSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; roomName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;roomName&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; topic &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;topic&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isPublic &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;visibility&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;matrixUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/_matrix/client/v3/createRoom&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;token&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; roomName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        topic&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; topic&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        visibility&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; isPublic &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;private&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        preset&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; isPublic &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public_chat&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;private_chat&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; room_id &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/room/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;room_id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Failed to create room&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CreateRoom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; navigation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNavigation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; actionData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useActionData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; action&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Form method&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;roomName&quot;&lt;/span&gt; placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Room Name&quot;&lt;/span&gt; required &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;textarea name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;topic&quot;&lt;/span&gt; placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Room Topic&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;select name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;visibility&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;option value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;private&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Private&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;option&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;option value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;public&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Public&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;option&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;select&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt; disabled&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Creating...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Create Room&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;actionData&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;actionData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Form&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Progressive enhancement benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server validation&lt;/strong&gt;: Input validation happens on the server first&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic redirect&lt;/strong&gt;: No manual navigation handling required&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error handling&lt;/strong&gt;: Built-in error states without try/catch blocks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Search Rooms&lt;/h3&gt;
&lt;p&gt;Room search demonstrates URL-driven state management that works perfectly without JavaScript:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// app/routes/browse.tsx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; request &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; LoaderFunctionArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; token &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requireUserSession&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; filter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;filter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; limit&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; generic_search_term&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; filter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;matrixUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/_matrix/client/v3/publicRooms&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;token&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; chunk&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; rooms &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; rooms&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; filter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Browse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; rooms&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; filter &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useLoaderData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; loader&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; navigation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNavigation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Form method&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input 
          name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;filter&quot;&lt;/span&gt; 
          placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Search rooms...&quot;&lt;/span&gt; 
          defaultValue&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;filter &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
        &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Search&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Form&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;loading&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Searching&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;rooms&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;rooms&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;room &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Link key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;room_id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; to&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/room/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;room_id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h3&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;canonical_alias&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;h3&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;topic&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;num_joined_members&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; members&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;span&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Link&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;URL-driven state advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bookmarkable searches&lt;/strong&gt;: Share filtered results via URL&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Back button works&lt;/strong&gt;: Browser navigation handles search history&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server-side filtering&lt;/strong&gt;: Fast initial page loads with filtered results&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Room Messages and Real-time Updates&lt;/h3&gt;
&lt;p&gt;The room page shows the perfect blend of server-side data loading and client-side enhancement:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// app/routes/room.tsx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; request &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LoaderArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cookieHeader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cookie&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; token &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; matrixTokenCookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cookieHeader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; baseUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; matrixBaseUrlCookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cookieHeader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;token &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;baseUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/login&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; roomId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;roomId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Fetch room details&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; roomResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;baseUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/_matrix/client/v3/rooms/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;roomId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/state/m.room.name&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;token&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Fetch initial messages&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; messagesResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;baseUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/_matrix/client/v3/rooms/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;roomId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/messages?dir=b&amp;amp;limit=20&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;token&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; roomData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; roomResponse&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; messagesData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; messagesResponse&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Convert Matrix events to our Message format&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; messages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; messagesData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;chunk
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;m.room.message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;event_id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      sender&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sender&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      timestamp&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;origin_server_ts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    room&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; roomId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; roomData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; roomId &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    messages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    matrixConfig&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; baseUrl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; params &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ActionArgs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cookieHeader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cookie&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; token &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; matrixTokenCookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cookieHeader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; baseUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; matrixBaseUrlCookie&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cookieHeader&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; formData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;formData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; formData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;baseUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/_matrix/client/v3/rooms/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;roomId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/send/m.room.message/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PUT&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;token&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        msgtype&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;m.text&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; success&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Room&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; room&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; messages&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; initialMessages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; matrixConfig &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useLoaderData&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; loader&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; navigation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useNavigation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// Custom hook for Matrix synchronization - this is where the magic happens!&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; messages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isConnected&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useMatrixSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    roomId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    initialEvents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; initialMessages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Server-provided initial data&lt;/span&gt;
    token&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; matrixConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    baseUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; matrixConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;baseUrl
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;room-header&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;room&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;h1&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;connection-status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;isConnected &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🟢 Connected&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🔴 Disconnected&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;messages&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;messages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;strong&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sender&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;strong&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;time&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timestamp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLocaleTimeString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;time&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Form method&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;input 
          name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt; 
          type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;text&quot;&lt;/span&gt; 
          placeholder&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Type a message...&quot;&lt;/span&gt; 
          required 
          disabled&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt; disabled&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitting&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Sending...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Send&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;Form&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
      
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Connection error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, here’s the crucial part - the custom &lt;code class=&quot;language-text&quot;&gt;useMatrixSync&lt;/code&gt; hook:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// app/hooks/useMatrixSync.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useMatrixSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; roomId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; initialEvents&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; baseUrl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  roomId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  initialEvents&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Message&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  token&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  baseUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;messages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setMessages&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;initialEvents&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isConnected&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setIsConnected&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setError&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// This runs on both server and client, but the initial messages &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// are provided by the server loader&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;useMatrixSync: Setting up with&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; initialEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;initial messages&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// This ONLY runs on the client side - perfect for real-time sync!&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;useMatrixSync: Starting client-side sync for room&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; roomId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; syncToken&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; abortController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AbortController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; syncUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;baseUrl&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/_matrix/client/v3/sync&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        syncUrl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;timeout&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;30000&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        syncUrl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;filter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          room&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; rooms&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;roomId&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syncToken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          syncUrl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;since&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; syncToken&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syncUrl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;token&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          signal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; abortController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; syncData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;setIsConnected&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;setError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          
          &lt;span class=&quot;token comment&quot;&gt;// Process new messages&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; roomData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; syncData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rooms&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;join&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;roomId&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; syncData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rooms&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;timeline&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;roomId&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;roomData&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;timeline&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;events&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newMessages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; roomData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeline&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;events
              &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;m.room.message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;event_id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                sender&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sender&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                body&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                timestamp&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;origin_server_ts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token function&quot;&gt;setMessages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;current &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;current&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;newMessages&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
          
          syncToken &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; syncData&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next_batch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token comment&quot;&gt;// Continue syncing&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sync&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AbortError&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;setIsConnected&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;setError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token comment&quot;&gt;// Retry after delay&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sync&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      abortController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;roomId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; baseUrl&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; messages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isConnected&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The Custom Hook Magic: Server-Side Execution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here’s the fascinating part about the &lt;code class=&quot;language-text&quot;&gt;useMatrixSync&lt;/code&gt; hook that perfectly demonstrates React Router 7’s dual execution model:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// This part runs on BOTH server and client&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;messages&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setMessages&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;initialEvents&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// ✅ Server &amp;amp; Client&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Setting up with&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; initialEvents&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;initial messages&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// ✅ Server &amp;amp; Client&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// This part runs ONLY on the client  &lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// ❌ Server (skipped), ✅ Client only&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Starting client-side sync&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// All the real-time synchronization logic&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;roomId&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Why the hook accepts &lt;code class=&quot;language-text&quot;&gt;initialEvents&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The custom hook needs &lt;code class=&quot;language-text&quot;&gt;initialEvents&lt;/code&gt; from the loader because when it runs on the server during SSR, the &lt;code class=&quot;language-text&quot;&gt;useEffect&lt;/code&gt; won’t execute. The server-side execution only initializes the state with the data we fetched in the loader. Then, when the component hydrates on the client, the &lt;code class=&quot;language-text&quot;&gt;useEffect&lt;/code&gt; kicks in and starts the real-time synchronization from where the server left off.&lt;/p&gt;
&lt;p&gt;This creates a seamless handoff:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Server&lt;/strong&gt;: Fetches initial messages, passes them to the hook, hook initializes state&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client&lt;/strong&gt;: Hook hydrates with server state, then &lt;code class=&quot;language-text&quot;&gt;useEffect&lt;/code&gt; begins real-time sync&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Result&lt;/strong&gt;: No gap in data, no loading states, perfect progressive enhancement&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Perfect progressive enhancement:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server-side&lt;/strong&gt;: Initial messages load immediately, forms work without JS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client-side&lt;/strong&gt;: Real-time updates and enhanced UX when JS is available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graceful degradation&lt;/strong&gt;: If polling fails, manual refresh still works&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hook design&lt;/strong&gt;: Accepts server data to bridge server-client execution seamlessly&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Evolution of Separation of Concerns&lt;/h2&gt;
&lt;p&gt;Here’s where things get philosophically interesting. The traditional “separation of concerns” in web development meant separating technologies: HTML in one file, CSS in another, JavaScript in a third. We were taught that mixing these was evil—it created “spaghetti code” that was hard to maintain.&lt;/p&gt;
&lt;p&gt;But React and modern frameworks challenged this thinking. Instead of separating by technology, we began separating by feature or component. A button component might contain its HTML structure, CSS styling, and JavaScript behavior all in one place. This felt wrong at first, but it proved to be more maintainable for complex applications.&lt;/p&gt;
&lt;p&gt;React Router 7 and React Server Components represent the next evolution: separating by execution environment. We’re not just thinking about what runs where, but when it runs and why. This creates a new kind of separation of concerns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server concerns&lt;/strong&gt;: Data fetching, authentication, business logic, initial rendering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client concerns&lt;/strong&gt;: User interactions, real-time updates, enhanced UX, local state&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This isn’t abandoning separation of concerns—it’s refining what those concerns actually are. We’re returning to the web’s original progressive enhancement model, but with modern tools that make it sustainable and developer-friendly.&lt;/p&gt;
&lt;h2&gt;Why This Matters for Backend-for-Frontend&lt;/h2&gt;
&lt;p&gt;In the past, when I built React apps with a separate backend-for-frontend (often in PHP), I had to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manually configure Webpack to split code by route&lt;/li&gt;
&lt;li&gt;Manually type every HTTP call&lt;/li&gt;
&lt;li&gt;Keep frontend and backend logic in sync across different languages&lt;/li&gt;
&lt;li&gt;Handle loading states, error states, and form submissions in every component&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;React Router 7 eliminates this friction. The loader and action functions run on the server, giving you the backend-for-frontend logic right alongside your components. There’s no context switching between languages, no manual API typing, and no wondering whether your frontend and backend are in sync.&lt;/p&gt;
&lt;p&gt;It’s not just about reducing work—it’s about reducing the cognitive overhead of building web applications.&lt;/p&gt;
&lt;h2&gt;Key Takeaways&lt;/h2&gt;
&lt;p&gt;Building this Matrix chat application with React Router 7 reinforced several important principles:&lt;/p&gt;
&lt;h3&gt;More Belongs in Loaders and Actions Than You Think&lt;/h3&gt;
&lt;p&gt;Initially, I tried to keep server-side logic minimal, but I discovered that pushing more logic into loaders and actions creates a better user experience. Authentication checks, data validation, business logic, and even complex data transformations work better on the server where they can fail fast and provide immediate feedback. I even ditched entirely the typescript sdk for matrix in favour of doing every query and command in the loader / action, and having a bunch of custom hooks which would listend for events comming.&lt;/p&gt;
&lt;h3&gt;Embrace URL State&lt;/h3&gt;
&lt;p&gt;Put as much state as possible in the URL—it’s easier for both developers and users. Room IDs, filter states, pagination, and even UI preferences can live in the URL. This makes the application more shareable, bookmarkable, and debuggable. React Router’s nested routing makes this natural and maintainable.&lt;/p&gt;
&lt;h3&gt;Progressive Enhancement Isn’t Just Nice-to-Have&lt;/h3&gt;
&lt;p&gt;When your app works without JavaScript, you’ve built something fundamentally more resilient. It will work on slow networks, older devices, and in environments where JavaScript fails to load. But more importantly, you’ve built something that aligns with the grain of the web rather than fighting against it.&lt;/p&gt;
&lt;h3&gt;The Framework Handles the Hard Parts&lt;/h3&gt;
&lt;p&gt;React Router 7 eliminates so much boilerplate around form handling, loading states, error boundaries, and data synchronization. You write declarative loaders and actions, and the framework handles optimistic updates, race conditions, and state management automatically.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;React is evolving back toward the web’s fundamental principles, and that’s not a step backward—it’s a step forward with better tools. Server-side rendering, progressive enhancement, and unobtrusive JavaScript aren’t old-fashioned ideas; they’re timeless principles that modern frameworks are finally making approachable.&lt;/p&gt;
&lt;p&gt;The Matrix chat application demonstrates that you can build rich, interactive experiences without sacrificing accessibility, performance, or reliability. When your React app works with JavaScript disabled, you know you’ve built something that truly embraces the web platform.&lt;/p&gt;
&lt;p&gt;Try it yourself: disable JavaScript in your browser and see how many of your favorite web applications still work. Then imagine building your next project with progressive enhancement from day one. The web—and your users—will thank you for it.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Thinking in React in few words]]></title><description><![CDATA[Thinking in React In an era dominated by AI agents and vibecoding, mastering the fundamentals has never been more important. That’s why I…]]></description><link>https://casual-programming.com/thinking_in_react_in_few_words/</link><guid isPermaLink="false">https://casual-programming.com/thinking_in_react_in_few_words/</guid><pubDate>Sat, 21 Jun 2025 20:55:00 GMT</pubDate><content:encoded>&lt;h1&gt;Thinking in React&lt;/h1&gt;
&lt;p&gt;In an era dominated by AI agents and vibecoding, mastering the fundamentals has never been more important. That’s why I created my own version of &lt;a class=&quot;siteLink&quot; href=&quot;https://react.dev/learn/thinking-in-react&quot; title=&quot;Thinking in React&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Thinking in React&lt;/a&gt; and the &lt;a class=&quot;siteLink&quot; href=&quot;https://react.dev/learn/tutorial-tic-tac-toe&quot; title=&quot;Tic Tac Toe&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Tic Tac Toe&lt;/a&gt; tutorial - shorter, easier, with Typescript and slot machines.&lt;/p&gt;
&lt;p&gt;Find my code &lt;a class=&quot;siteLink&quot; href=&quot;https://stackblitz.com/edit/vitejs-vite-6q5ngvmj?file=README.md&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The “Minimal State” Principle&lt;/h2&gt;
&lt;p&gt;There’s a core idea in &lt;a class=&quot;siteLink&quot; href=&quot;https://react.dev/learn/thinking-in-react&quot; title=&quot;Thinking in React&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Thinking in React&lt;/a&gt; that’s both crucial and often misunderstood: &lt;strong&gt;Find the minimal but complete representation of UI state&lt;/strong&gt;.
Everyone agrees with this in principle, yet I see many developers struggling in practice.&lt;/p&gt;
&lt;p&gt;Let’s look at an example. Suppose you want a &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; type with &lt;code class=&quot;language-text&quot;&gt;birthDate&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;age&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  birthDate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  age&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You might write:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  birthDate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2022/11/21&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  age&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is incorrect. The problem is that &lt;code class=&quot;language-text&quot;&gt;birthDate&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;age&lt;/code&gt; must stay in sync — and that’s fragile..&lt;/p&gt;
&lt;h3&gt;A Better Approach&lt;/h3&gt;
&lt;p&gt;Instead, compute &lt;code class=&quot;language-text&quot;&gt;age&lt;/code&gt; from &lt;code class=&quot;language-text&quot;&gt;birthDate&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ageFromDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dateString&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; birth &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dateString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; today &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; age &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFullYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; birth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFullYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; monthDiff &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMonth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; birth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMonth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// Adjust age if birthday hasn&apos;t occurred this year yet&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;monthDiff &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;monthDiff &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; today&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; birth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      age&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; age&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; person &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  birthDate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2022/11/21&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ageFromDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;birthDate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 If you’re not familiar with JavaScript getters, &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get&quot; title=&quot;check them out here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;check them out here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You could write an OOP version of this, but the point is clear: &lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;age&lt;/code&gt; should not be stored — it’s derived from &lt;code class=&quot;language-text&quot;&gt;birthDate&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The React Tic Tac Toe Challenge&lt;/h2&gt;
&lt;p&gt;Now that we understand minimal state, let’s bring that into React.&lt;/p&gt;
&lt;p&gt;Where do you store state in React? If you’re not using an external state manager, you use the &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt; hook.&lt;/p&gt;
&lt;p&gt;Here’s the challenge:&lt;br&gt;
&lt;strong&gt;How many &lt;code class=&quot;language-text&quot;&gt;useState&lt;/code&gt; hooks do you need to implement Tic Tac Toe?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The answer: &lt;strong&gt;Only one — and not the one you’re probably thinking.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🧠 For a more patient explanation, check out the full &lt;a class=&quot;siteLink&quot; href=&quot;https://react.dev/learn/tutorial-tic-tac-toe&quot; title=&quot;Tic Tac Toe tutorial&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Tic Tac Toe tutorial&lt;/a&gt; from the React documentation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here it is:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; initialMovesHistory&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Move&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;movesHistory&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setMoveHistory&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;initialMovesHistory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s it! The only state you need is the &lt;strong&gt;history of moves&lt;/strong&gt; for the current game.&lt;br&gt;
&lt;a class=&quot;siteLink&quot; href=&quot;https://stackblitz.com/edit/vitejs-vite-6q5ngvmj&quot; title=&quot;Check the code here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Check the code here&lt;/a&gt; (open &lt;a class=&quot;siteLink&quot; href=&quot;https://stackblitz.com/edit/vitejs-vite-6q5ngvmj?file=src%2FApp.tsx&quot; title=&quot;App.tsx&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;App.tsx&lt;/a&gt;) and see the magic in action.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Defining Types&lt;/h3&gt;
&lt;p&gt;Here’s what we’re working with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Player&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;x&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;o&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GameHistory&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Move&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code class=&quot;language-text&quot;&gt;Player&lt;/code&gt; can be &lt;code class=&quot;language-text&quot;&gt;&apos;x&apos;&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;&apos;o&apos;&lt;/code&gt;. Nothing to see here.&lt;/li&gt;
&lt;li&gt;A &lt;code class=&quot;language-text&quot;&gt;Move&lt;/code&gt; is just a grid index (0–8).&lt;/li&gt;
&lt;li&gt;A &lt;code class=&quot;language-text&quot;&gt;GameHistory&lt;/code&gt; is a list of moves.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;But Who Made the Move?&lt;/h3&gt;
&lt;p&gt;You might wonder:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why am I not storing the player in the &lt;code class=&quot;language-text&quot;&gt;Move&lt;/code&gt;?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Because you can &lt;strong&gt;derive&lt;/strong&gt; it. If &lt;code class=&quot;language-text&quot;&gt;&apos;x&apos;&lt;/code&gt; always starts first, then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Even-indexed moves in the history (&lt;code class=&quot;language-text&quot;&gt;0, 2, 4, …&lt;/code&gt;) belong to &lt;code class=&quot;language-text&quot;&gt;&apos;x&apos;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Odd-indexed moves (&lt;code class=&quot;language-text&quot;&gt;1, 3, 5, …&lt;/code&gt;) belong to &lt;code class=&quot;language-text&quot;&gt;&apos;o&apos;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPlayerFromMoveIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movesHistoryLength&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Player &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; movesHistoryLength &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;x&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;o&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt;Determining Game Status&lt;/h2&gt;
&lt;p&gt;The next derived value is the &lt;strong&gt;game status&lt;/strong&gt;. Here’s how:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; winningCombinations&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Move&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GameStatus&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;inprogress&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      player&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Player&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ended:tie&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ended:won&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      player&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Player&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gameStatus&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;movesHistory&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GameHistory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GameStatus &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hlen &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; movesHistory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; winningComps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; aPlayer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPlayerForSquare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; movesHistory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aPlayer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bPlayer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPlayerForSquare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; movesHistory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cPlayer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPlayerForSquare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; movesHistory&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;aPlayer &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; bPlayer &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; bPlayer &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; cPlayer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ended:won&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          player&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; aPlayer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hlen &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;GRID_SIZE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ended:tie&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;inprogress&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    player&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPlayerFromMoveIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hlen&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From just the &lt;code class=&quot;language-text&quot;&gt;movesHistory&lt;/code&gt; and a set of &lt;code class=&quot;language-text&quot;&gt;winningCombinations&lt;/code&gt;, you can fully determine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Whether the game is still in progress.&lt;/li&gt;
&lt;li&gt;If it ended in a tie.&lt;/li&gt;
&lt;li&gt;If someone won — and who they are.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;That’s All, Folks!&lt;/h2&gt;
&lt;p&gt;Everything else is glue code and some CSS. Again, &lt;a class=&quot;siteLink&quot; href=&quot;https://stackblitz.com/edit/vitejs-vite-6q5ngvmj?file=README.md,src%2FApp.tsx&quot; title=&quot;check the full code here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;check the full code here&lt;/a&gt; if you’re curious.&lt;/p&gt;
&lt;h2&gt;A Note on Performance&lt;/h2&gt;
&lt;p&gt;You might be concerned about performance — but in most real apps, bottlenecks come from side effects like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP requests&lt;/li&gt;
&lt;li&gt;Local storage access&lt;/li&gt;
&lt;li&gt;Expensive re-renders&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don’t prematurely optimize.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🧙 Want to become a React performance wizard?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Make sure you understand &lt;strong&gt;React’s compiler&lt;/strong&gt; and &lt;strong&gt;memoization&lt;/strong&gt; first.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Loose Types Make Your Code Verbose — Type Narrowing to the Rescue!]]></title><description><![CDATA[Loose Types Make Your Code Verbose — Type Narrowing to the Rescue! TypeScript’s type system isn’t strictly safe by default — and that was…]]></description><link>https://casual-programming.com/loose-types-make-ts-verbose/</link><guid isPermaLink="false">https://casual-programming.com/loose-types-make-ts-verbose/</guid><pubDate>Thu, 12 Jun 2025 15:19:00 GMT</pubDate><content:encoded>&lt;h1&gt;Loose Types Make Your Code Verbose — Type Narrowing to the Rescue!&lt;/h1&gt;
&lt;p&gt;TypeScript’s type system isn’t strictly safe by default — and that was likely a conscious decision to make it more accessible to JavaScript developers. This flexibility helped drive adoption in the JS community. But as TypeScript gained popularity, it also attracted developers from other languages. As a result, the community now includes both developers who aren’t used to static types, and others who don’t fully understand JavaScript’s quirks. That mix has led to a lot of confusion about how types should actually be used in TypeScript.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;TL;DR Version&lt;/h2&gt;
&lt;p&gt;If you don’t have time, here is what you are gonna learn:&lt;/p&gt;
&lt;p&gt;When you are defining your types, follow these rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ Avoid &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; at any cost; prefer &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;❌ If you need an object type, avoid  &lt;code class=&quot;language-text&quot;&gt;object&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;✅ Use Instead  &lt;code class=&quot;language-text&quot;&gt;Record&amp;lt;string, MyUnion&gt;&lt;/code&gt;and make the union as strict as possible.&lt;/li&gt;
&lt;li&gt;✅ With properly typed data, &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining&quot; title=&quot;optional chaining&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;optional chaining&lt;/a&gt; (&lt;code class=&quot;language-text&quot;&gt;?.&lt;/code&gt;) will usually be all you need.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; Object: Starting Simple&lt;/h2&gt;
&lt;p&gt;Here’s a pattern I’ve seen many times in real-world code.
Imagine we have a basic &lt;code class=&quot;language-text&quot;&gt;User&lt;/code&gt; object that allows arbitrary data.
let’s say you want to get the &lt;code class=&quot;language-text&quot;&gt;user.data.role&lt;/code&gt; property from your user.
Ideally, if you know what is the &lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html&quot; title=&quot;optional chaining&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;optional chaining&lt;/a&gt; (the &lt;code class=&quot;language-text&quot;&gt;?.&lt;/code&gt; operator) you would expect that you could do something like &lt;code class=&quot;language-text&quot;&gt;const role = user?.data?.role&lt;/code&gt; and eventually assign &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt; if something in this chain does not exist.&lt;/p&gt;
&lt;p&gt;At first glance, &lt;code class=&quot;language-text&quot;&gt;data?: any&lt;/code&gt; feels like the simplest way to allow any shape of object… but it silently disables all checks&lt;/p&gt;
&lt;p&gt;so the type would be:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  data&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;user1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play/?#code/C4TwDgpgBAqgzhATlAvFA3gKClAlgEwC4o5hFcA7AcwG5soKBDAWwmNPOrp30eEYD8xRhRB0AvnUwBjAPYVSUAK4JEheElQZ6OAoQBEARn0AaHQxZt9KpMbPjMjuQtkAbCADpXsqgAobiB68-B6IbhAAlEA&quot; title=&quot;Try this example on TS Playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Try this example on TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;your compiler will be happy, but you will get an error at runtime.&lt;/p&gt;
&lt;p&gt;The compiler is happy because typing properties with  any does not mean only accept “any value”, in reality  &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; means  &lt;code class=&quot;language-text&quot;&gt;&quot;accept any value&quot; AND &quot;disable the typecheck for this property&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now if you are an old-school js developer, you know that the js, has many dynamic languages, is based on &lt;a class=&quot;siteLink&quot; href=&quot;https://en.wikipedia.org/wiki/Duck_typing&quot; title=&quot;Duck Typing&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Duck Typing&lt;/a&gt;.
In a nutshell, if you are too lazy to read wikipedia, duck typing means you got to write a bunch of checks at runtime if object properties exists.
This force you to write repetitive, defensive checks, and if you are not an experienced javascript developer, probably you don’t even know what to check exactly.&lt;/p&gt;
&lt;p&gt;It is my belief that &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt; was one of the major weapons to convince js developers to move to typescript. But in 2025 any still exists in typescript mainly for retrocompatibility reasons (and any linter discourages you to use it)&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt; to the Rescue&lt;/h2&gt;
&lt;p&gt;If you think you should use &lt;code class=&quot;language-text&quot;&gt;any&lt;/code&gt;, it probably means you want to use &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;let’s see how this changes:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  data&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;user1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;role&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;role&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// you need to add this if or the compiler will not let you do it.&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play/?#code/C4TwDgpgBAqgzhATlAvFA3gKClAlgEwC4o5hFcA7AcwG5soKBDAWwmNPOrp30eEYD8xAK4UA1hQD2Adwp0AvnUwBjSRVJRhCRIXhJUGejgKEARAEZTAGiMMWbU1qSWbOHn0aF0iSQBs2UI7apvKYoZi4AGYAFE6IAgB0vPxQAGSpUKCQkpGa2onJjKgoKKaSAEYAVhDKwKZpGYE+-vWUeUhJHlAAlFAA9H1QIJLCDBAQ+JmSUIz4k8AAFrhweLmSyIvQqsxgvrj60ri+vgySwFD+58Oj+NO4wAm2qup+EAm+klSx+Z38ic0QbpAA&quot; title=&quot;Try this example on TS Playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Try this example on TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, TypeScript &lt;em&gt;forces&lt;/em&gt; you to check before use, that’s why the check is changed. Now it is safe, but it is super verbose. For this reason, I saw many developers preferring to use any and hoping to not be on call if this becomes an error in production.&lt;/p&gt;
&lt;p&gt;✅ The check is still at runtime, but &lt;strong&gt;you can’t forget it anymore&lt;/strong&gt;. The compiler has your back. Still very verbose indeed.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What About &lt;code class=&quot;language-text&quot;&gt;object&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;Using &lt;code class=&quot;language-text&quot;&gt;object&lt;/code&gt; feels more descriptive, I mean, in js an object is that thing you define with &lt;code class=&quot;language-text&quot;&gt;{}&lt;/code&gt;, right? it is basically an &lt;a class=&quot;siteLink&quot; href=&quot;https://youtu.be/pKO9UjSeLew?si=zavllTNv_Gmtqppf&amp;t=58&quot; title=&quot;hashmap&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;hashmap&lt;/a&gt;, correct? It seems exactly what I need!
Here is how your type would be:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  data&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; object&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;data  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;role&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A little better, but still too verbose. Also this is not particularly safe.
In fact, this allows &lt;strong&gt;any value where &lt;code class=&quot;language-text&quot;&gt;typeof value === &quot;object&quot;&lt;/code&gt;&lt;/strong&gt;, which includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Arrays (&lt;code class=&quot;language-text&quot;&gt;[]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;{}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s because typescript need to reflect what javascript do.
In general, Not ideal for safe usage or good DX.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;✅ Use &lt;code class=&quot;language-text&quot;&gt;Record&amp;lt;string, unknown&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The reality is that what you need is a record. Your key values are probably strings, and if you don’t know your values type, you can use &lt;code class=&quot;language-text&quot;&gt;unknown&lt;/code&gt;. Something like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  data&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Record&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;user1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play/?ssl=15&amp;ssc=2&amp;pln=7&amp;pc=1#code/C4TwDgpgBAqgzhATlAvFA3gKClAlgEwC4o5hFcA7AcwG5soKBDAWwmNPOrp30eEeIAlCAGMA9onwAeDpSoAaKAFcKAawpiA7hQB8dAL51M4iqWUJkaLDhwFCAIgCM9+fRxNWDpReeubUXn5CdH1MUMxcADMACntEMQAbCHs8CnMkADpAxigAMlz0xCy+RgB+DPik1BQ0e0YqCApgewBKaxsTOESIDISxKmjvTOyK7pawoA&quot; title=&quot;Check this on the Try this example on TS Playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Check this on the Try this example on TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This enforces you to have data :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Must be a plain object&lt;/li&gt;
&lt;li&gt;Keys must be strings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;How you use it:&lt;/h3&gt;
&lt;p&gt;This is finally what we want!&lt;/p&gt;
&lt;h3&gt;Bonus tip&lt;/h3&gt;
&lt;p&gt;String is not the only type you can use for object keys in javascript and typescript. But if you don’t know what a symbol is, or why this is true in js:  &lt;code class=&quot;language-text&quot;&gt;typeof [] === &apos;object&apos;&lt;/code&gt;,  stick with &lt;code class=&quot;language-text&quot;&gt;Record&amp;lt;string, ...&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Narrowing with Union Types&lt;/h2&gt;
&lt;p&gt;You can do better than this. You can also limit the types of values allowed inside &lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Record&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;user1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string-property property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because you’ve already told TypeScript what values are possible, narrowing is straightforward and less error-prone.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Using narrow, well-defined types makes your code safer, reduces bugs, and dramatically improves your developer experience.&lt;/p&gt;
&lt;p&gt;Want to dig deeper into advanced type guards or build custom ones for your library? Drop a comment — or better, share how &lt;em&gt;you&lt;/em&gt; handle dynamic data with TypeScript!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Implementing a Node.js/Express Server Using MinIO for Image Uploads]]></title><description><![CDATA[Implementing a Node.js/Express Server Using MinIO for Image Uploads What We’re Going to Do In this article, we’ll set up a Node.js server…]]></description><link>https://casual-programming.com/node-server-upload-images-minio/</link><guid isPermaLink="false">https://casual-programming.com/node-server-upload-images-minio/</guid><pubDate>Sat, 21 Sep 2024 15:19:00 GMT</pubDate><content:encoded>&lt;h1&gt;Implementing a Node.js/Express Server Using MinIO for Image Uploads&lt;/h1&gt;
&lt;h2&gt;What We’re Going to Do&lt;/h2&gt;
&lt;p&gt;In this article, we’ll set up a &lt;strong&gt;Node.js server&lt;/strong&gt; using &lt;strong&gt;Express&lt;/strong&gt; and &lt;strong&gt;MinIO&lt;/strong&gt; for image uploads and downloads. Is gonna be fully functional locally without requiring any AWS credentials. Our server will have two key features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate Pre-signed URLs&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Endpoint&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;http://localhost:3000/api/urls/:key&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This will generate &lt;code class=&quot;language-text&quot;&gt;PUT&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; pre-signed URLs for securely uploading and downloading files from MinIO without exposing credentials. the put url could be used by any http client to upload an image&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Upload an Image from a URL&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Endpoint&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;/api/uploads/url?url=imageUrl&amp;amp;key=keyName&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This will download an image from a given URL, upload it to MinIO with a specified &lt;code class=&quot;language-text&quot;&gt;key&lt;/code&gt;, and return a public URL to access the image.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We’ll deploy &lt;strong&gt;MinIO&lt;/strong&gt; locally using &lt;strong&gt;Docker Compose&lt;/strong&gt; and implement the server using &lt;strong&gt;Node.js&lt;/strong&gt;, &lt;strong&gt;express&lt;/strong&gt;, &lt;strong&gt;Axios&lt;/strong&gt; and the &lt;strong&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/aws/aws-sdk-js-v3&quot; title=&quot;AWS Typescript SDK&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;AWS Typescript SDK&lt;/a&gt;&lt;/strong&gt; (this last one will be configured to use minio instead of s3 in the backend).&lt;/p&gt;
&lt;h2&gt;For the Impatient&lt;/h2&gt;
&lt;p&gt;If you want to dive right in, you can find the complete working code in the repository below. Follow the instructions in the &lt;code class=&quot;language-text&quot;&gt;README&lt;/code&gt; to get started:&lt;/p&gt;
&lt;p&gt;👉 &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/s3-test-minio&quot; title=&quot;https://github.com/jurgob/s3-test-minio&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/s3-test-minio&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Introduction to S3, MinIO and Pre-signed URLs&lt;/h2&gt;
&lt;h3&gt;Amazon S3 and Minio&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Amazon S3 (Simple Storage Service)&lt;/strong&gt; is a popular cloud storage solution that allows you to store and retrieve large amounts of data. It’s often used for file uploads, backups, and serving static content. However, S3 itself is a &lt;strong&gt;closed-source service&lt;/strong&gt;, making it challenging to test locally without using the cloud.&lt;/p&gt;
&lt;p&gt;To address this issue, we can use &lt;strong&gt;MinIO&lt;/strong&gt;, an open-source, S3-compatible storage solution that can be run locally. MinIO enables developers to simulate S3 interactions without needing an internet connection or an AWS account. You can use &lt;strong&gt;MinIO&lt;/strong&gt; through the official AWS s3 sdk just chaning the service url to point at the Minio url.&lt;/p&gt;
&lt;h3&gt;Pre-signed URLs?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pre-signed URLs&lt;/strong&gt; are secure, time-limited links that allow you to perform specific actions (like uploading or downloading files) without exposing your credentials. They are commonly used in scenarios where direct access to S3 (or a compatible service like MinIO) is required, but security is a concern.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why do you need them?&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Example: PUT Pre-signed URL&lt;/h4&gt;
&lt;p&gt;A &lt;strong&gt;PUT&lt;/strong&gt; pre-signed URL allows you to upload a file directly to S3 (or MinIO) without needing credentials on the client-side.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Example PUT request with a pre-signed URL&lt;/span&gt;
PUT https://bucketname.s3.amazonaws.com/yourkey?X-Amz-Expires&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token comment&quot;&gt;# your presigned url&lt;/span&gt;

Headers:
Content-Type: image/jpeg
Content-Lenght: &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;fileSize&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

Body: 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;the image content &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; binary format&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;check the &lt;strong&gt;uploadStream()&lt;/strong&gt; function defined below to see how to do it with axios.&lt;/p&gt;
&lt;h3&gt;Why Are Pre-signed URLs Needed?&lt;/h3&gt;
&lt;p&gt;Pre-signed URLs are essential for securely uploading and downloading files directly to cloud storage (like S3 or MinIO) &lt;strong&gt;without putting your backend in the middle of the process&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Managing file upload on the backend side is much harder then what you may thig, so Instead of routing large file uploads through your server, pre-signed URLs let clients upload files &lt;strong&gt;directly&lt;/strong&gt; to storage (usually hosted by AWS), reducing [your] server load and improving efficiency. The URLs are temporary and grant &lt;strong&gt;limited access&lt;/strong&gt; to specific files, ensuring security while allowing clients to upload or download files without exposing your credentials.&lt;/p&gt;
&lt;h2&gt;Architecture Quick Overview&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Node.js Server (Express):&lt;/strong&gt; Handles the API logic, generates pre-signed URLs, and uploads images to MinIO.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A set of docker compose services including:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;minio&lt;/strong&gt;: MinIO is a high-performance, self-hosted object storage service that is fully compatible with Amazon S3 APIs. It allows you to store large amounts of unstructured data (like images, videos, backups).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;createbuckets&lt;/strong&gt;: a script to do the initial setup of minio&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;npm run dev:&lt;/strong&gt; this npm script will spin up both the nodejs server and the docker compose. Is gonna be the only thing you need to run to make the server work.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Setting up the server dependencies with docker compose&lt;/h2&gt;
&lt;p&gt;First, let’s set up our MinIO instance. We’ll be using Docker to run MinIO locally, and Docker Compose will make this process seamless.&lt;/p&gt;
&lt;p&gt;Create a &lt;code class=&quot;language-text&quot;&gt;docker-compose.yml&lt;/code&gt; file with the following content:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;3.8&apos;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;minio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; minio/minio
    &lt;span class=&quot;token key atrule&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; minio
    &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;9000:9000&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;9001:9001&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; MINIO_ROOT_USER=minio_username
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; MINIO_ROOT_PASSWORD=minio_password
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; /tmp/mino_data&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/data
    &lt;span class=&quot;token key atrule&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; server /data &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;console&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;address &quot;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;9001&quot;

  &lt;span class=&quot;token key atrule&quot;&gt;createbuckets&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; minio/mc
    &lt;span class=&quot;token key atrule&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; minio
    &lt;span class=&quot;token key atrule&quot;&gt;entrypoint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token scalar string&quot;&gt;
      /bin/sh -c &quot;
      /usr/bin/mc alias set myminio http://minio:9000 minio_username minio_password;
      /usr/bin/mc mb myminio/miniobucket;
      /usr/bin/mc policy set public myminio/miniobucket;
      exit 0;
      &quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;if you run this with &lt;code class=&quot;language-text&quot;&gt;npm run dev:server&lt;/code&gt; and you navigate to &lt;code class=&quot;language-text&quot;&gt;http://localhost:9001&lt;/code&gt;. you should see the minio dashboard. you can login using &lt;code class=&quot;language-text&quot;&gt;minio_username&lt;/code&gt; as username and &lt;code class=&quot;language-text&quot;&gt;minio_password&lt;/code&gt; as password&lt;/p&gt;
&lt;p&gt;you can now run &lt;code class=&quot;language-text&quot;&gt;npm run cli&lt;/code&gt; and see an image upload in your system.&lt;/p&gt;
&lt;h3&gt;Explaining the Docker Compose File&lt;/h3&gt;
&lt;p&gt;This &lt;code class=&quot;language-text&quot;&gt;docker-compose.yml&lt;/code&gt; file is designed to run a local &lt;strong&gt;MinIO&lt;/strong&gt; instance and automatically create a bucket with public access. Here’s a breakdown of what each section does:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;version: &apos;3.8&apos;&lt;/code&gt;: Specifies the version of Docker Compose being used.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;services:&lt;/code&gt;: Defines the services (containers) that Docker will run.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;minio:&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Image&lt;/strong&gt;: Uses the official &lt;code class=&quot;language-text&quot;&gt;minio/minio&lt;/code&gt; image to run MinIO.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Container Name&lt;/strong&gt;: Names the container &lt;code class=&quot;language-text&quot;&gt;minio&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ports&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Maps port &lt;code class=&quot;language-text&quot;&gt;9000&lt;/code&gt; on the host to &lt;code class=&quot;language-text&quot;&gt;9000&lt;/code&gt; on the container for the MinIO API.&lt;/li&gt;
&lt;li&gt;Maps port &lt;code class=&quot;language-text&quot;&gt;9001&lt;/code&gt; on the host to &lt;code class=&quot;language-text&quot;&gt;9001&lt;/code&gt; on the container for the MinIO web console.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment Variables&lt;/strong&gt;: Sets up the root credentials for accessing MinIO:
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MINIO_ROOT_USER&lt;/code&gt;: Sets the username.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;MINIO_ROOT_PASSWORD&lt;/code&gt;: Sets the password.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Volumes&lt;/strong&gt;: Mounts &lt;code class=&quot;language-text&quot;&gt;/tmp/mino_data&lt;/code&gt; on the host to &lt;code class=&quot;language-text&quot;&gt;/data&lt;/code&gt; inside the container, ensuring that data persists locally.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Command&lt;/strong&gt;: Starts MinIO in server mode, storing data in &lt;code class=&quot;language-text&quot;&gt;/data&lt;/code&gt; and running the web console on &lt;code class=&quot;language-text&quot;&gt;port 9001&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;createbuckets:&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Image&lt;/strong&gt;: Uses the &lt;code class=&quot;language-text&quot;&gt;minio/mc&lt;/code&gt; image (MinIO client) to manage the MinIO instance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;depends_on&lt;/strong&gt;: Ensures that this service runs only after the &lt;code class=&quot;language-text&quot;&gt;minio&lt;/code&gt; container is up and running.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entrypoint&lt;/strong&gt;: Runs a shell script to:&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Set up an alias (&lt;code class=&quot;language-text&quot;&gt;myminio&lt;/code&gt;) pointing to the MinIO instance at &lt;code class=&quot;language-text&quot;&gt;http://minio:9000&lt;/code&gt; with the credentials.&lt;/li&gt;
&lt;li&gt;Create a new bucket named &lt;code class=&quot;language-text&quot;&gt;miniobucket&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the bucket’s policy to public, allowing anyone to access objects in the bucket.&lt;/li&gt;
&lt;li&gt;Exit the script after the setup.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This setup ensures MinIO starts, creates a bucket, and configures it for public access automatically.&lt;/p&gt;
&lt;h2&gt;Creating the Node.js server&lt;/h2&gt;
&lt;p&gt;There are gonna be 2 files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt; -&gt; this is contain the really intresting part. it’s were we are gonna use the offical aws s3 sdk, configure it to point at our loca &lt;strong&gt;minio&lt;/strong&gt;,  we are gonna use it to create presigned urls and we are gonna use &lt;strong&gt;axios&lt;/strong&gt; to both download images and to upload images into minio.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;src/server.ts&lt;/code&gt; -&gt; this will containt the server endpoints definition&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Understanding: &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;index.ts&lt;/code&gt; file is responsible for interacting with MinIO by generating &lt;strong&gt;pre-signed URLs&lt;/strong&gt; and &lt;strong&gt;uploading files&lt;/strong&gt; via streams. Let’s break it down:&lt;/p&gt;
&lt;h4&gt;1. &lt;em&gt;&lt;strong&gt;Setting Up MinIO Client&lt;/strong&gt;&lt;/em&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s3Client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    region&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;REGION&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    credentials&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        accessKeyId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;minio_username&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        secretAccessKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;minio_password&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    endpoint&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://127.0.0.1:9000&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;MinIO&lt;/strong&gt; client is created using AWS SDK’s &lt;code class=&quot;language-text&quot;&gt;S3Client&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The credentials (&lt;code class=&quot;language-text&quot;&gt;accessKeyId&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;secretAccessKey&lt;/code&gt;) are set to the values defined in the Docker Compose file (&lt;code class=&quot;language-text&quot;&gt;minio_username&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;minio_password&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The &lt;code class=&quot;language-text&quot;&gt;endpoint points&lt;/code&gt; to the local MinIO instance running on &lt;code class=&quot;language-text&quot;&gt;localhost:9000&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. &lt;em&gt;&lt;strong&gt;Generating Pre-signed URLs&lt;/strong&gt;&lt;/em&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;xport &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; generatePresignedUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objectKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmd &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bucketName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;miniobucket&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;unkdonw cmd option&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; CmdObj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cmd &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; PutObjectCommand &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GetObjectCommand

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; commandOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        Bucket&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; bucketName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; objectKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; command &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cmd &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt; 
        &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PutObjectCommand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commandOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetObjectCommand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commandOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
        
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; presignedUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getSignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s3Client&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; command&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; expiresIn&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;600&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Presigned URL:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; presignedUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; presignedUrl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Error generating presigned URL:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;This function generates pre-signed URLs for either uploading (PUT) or downloading (GET) a file from MinIO.&lt;/li&gt;
&lt;li&gt;The URL is generated using the AWS SDK’s getSignedUrl function and is valid for 600 seconds (10 minutes).&lt;/li&gt;
&lt;li&gt;The pre-signed URL is a secure, temporary URL that allows users to interact with a specific object (file) without needing credentials.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;4. &lt;em&gt;&lt;strong&gt;Uploading a Stream to MinIO&lt;/strong&gt;&lt;/em&gt;&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; uploadStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;presignedUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; readStream&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Readable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;presignedUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; readStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; contentType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&apos;Content-Length&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;This function uploads a stream (e.g., an image file) to MinIO using a PUT pre-signed URL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Axios&lt;/strong&gt; is used to send a &lt;code class=&quot;language-text&quot;&gt;PUT&lt;/code&gt; request with the stream and required headers:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Content-Type:&lt;/strong&gt; The MIME type (e.g., &lt;code class=&quot;language-text&quot;&gt;image/jpeg&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content-Length:&lt;/strong&gt; The size of the image.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the request is successful, the image will be stored in the MinIO bucket, accessible via the &lt;strong&gt;GET pre-signed URL&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;Key Takeaways&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Pre-signed URLs enable secure, time-limited access to specific files in MinIO.&lt;/li&gt;
&lt;li&gt;The server uploads files by sending streams (image data) using a pre-signed PUT URL.&lt;/li&gt;
&lt;li&gt;Axios handles both generating and uploading streams, while the AWS SDK is used to interact with MinIO.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;The complete &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt; file:&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; axios &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;axios&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;createReadStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;statSync&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; S3Client&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PutObjectCommand&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; GetObjectCommand &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-sdk/client-s3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; getSignedUrl &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@aws-sdk/s3-request-presigner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; stat&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fs/promises&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Readable &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node:stream&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; s3Client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;S3Client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
    region&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;REGION&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    credentials&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        accessKeyId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;minio_username&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        secretAccessKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;minio_password&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
    endpoint&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://127.0.0.1:9000&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; generatePresignedUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;objectKey&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmd &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bucketName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;miniobucket&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;unkdonw cmd option&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; CmdObj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cmd &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; PutObjectCommand &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; GetObjectCommand

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; commandOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        Bucket&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; bucketName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Key&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; objectKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; command &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cmd &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt; 
        &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PutObjectCommand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commandOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
        &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;GetObjectCommand&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;commandOptions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
        
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; presignedUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getSignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s3Client&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; command&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; expiresIn&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;600&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Presigned URL:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; presignedUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; presignedUrl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Error generating presigned URL:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; uploadFileWithPresignedUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;presignedUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; filePath&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createReadStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filePath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileStats &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filePath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uploadStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;presignedUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fileStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fileStats&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/jpeg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; uploadStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;presignedUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; readStream&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Readable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;presignedUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; readStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      headers&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/jpeg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string-property property&quot;&gt;&apos;Content-Length&apos;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ERROR UPLOADING THE IMAGE:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Understanding &lt;code class=&quot;language-text&quot;&gt;src/server.ts&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This Node.js server built with &lt;strong&gt;Express&lt;/strong&gt; provides an API to download an image from a given URL, upload it to MinIO, and return a pre-signed &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt; URL for retrieval. Here’s how the image download and upload process works.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Endpoint&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;/api/uploads/images&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;This route handles the logic for downloading an image from a given URL and uploading it to MinIO.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/api/uploads/images&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;string&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The url query parameter is required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/api/uploads/images?key=example&amp;amp;url=https://example.com/image.jpg&apos;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; HTTPError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The imageUrl query parameter is required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;string&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The key query parameter is required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/api/uploads/images?key=example&amp;amp;url=https://example.com/image.jpg&apos;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; HTTPError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; get&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;token comment&quot;&gt;// download the content of the imageUrl param and put it in a readable stream. check the content type is an image. retrive the content length and put it in a variable&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; responseType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;stream&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;content-type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;content-length&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;contentType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;image/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The URL does not point to an image&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; imageStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Readable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uploadStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; imageStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


        res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            contentType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            contentLength&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            imageUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            getUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; get
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;httpError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h5&gt;1. Get Query Parameters:&lt;/h5&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;url&lt;/code&gt;: The URL of the image to download.
&lt;code class=&quot;language-text&quot;&gt;key&lt;/code&gt;: The unique key externally provied (name) for the file in MinIO.
The server validates that both the url and key parameters are provided.&lt;/p&gt;
&lt;h5&gt;2. Generating Pre-signed URLs&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; get&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;PUT Pre-signed URL&lt;/code&gt;: Used to upload the image to MinIO.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;GET Pre-signed URL&lt;/code&gt;: Generated for retrieving the image after upload.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These URLs are generated using the generatePresignedUrl function, which communicates with MinIO to create temporary access URLs for uploading and downloading files.&lt;/p&gt;
&lt;h5&gt;3. Downloading the Image&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; responseType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;stream&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;content-type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;content-length&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;contentType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;image/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The URL does not point to an image&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Image Download: The server uses Axios to download the image from the provided url. It requests the image as a stream (&lt;code class=&quot;language-text&quot;&gt;responseType: &apos;stream&apos;&lt;/code&gt;), making it easier to handle large files without loading the entire file into memory.&lt;/li&gt;
&lt;li&gt;Headers:
&lt;ul&gt;
&lt;li&gt;contentType: The MIME type of the image, ensuring it is a valid image format.&lt;/li&gt;
&lt;li&gt;contentLength: The size of the image file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The server checks if the downloaded file is an image by verifying if the content-type starts with “image/“.&lt;/p&gt;
&lt;h5&gt;4. Uploading the Image to MinIO&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; imageStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Readable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uploadStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; imageStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Stream Upload: The server takes the downloaded image (which is a readable stream) and uploads it to MinIO using the PUT pre-signed URL.&lt;/li&gt;
&lt;li&gt;The &lt;code class=&quot;language-text&quot;&gt;uploadStream&lt;/code&gt; function handles the actual file upload:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Headers&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Content-Type&lt;/code&gt;: Set to the downloaded image’s MIME type.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Content-Length&lt;/code&gt;: Set to the size of the image.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This ensures that the image is uploaded in the correct format and size.&lt;/p&gt;
&lt;h5&gt;5. Response to Client&lt;/h5&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    contentType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    contentLength&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    imageUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    getUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; get
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After the image is successfully uploaded, the server responds with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;key&lt;/code&gt;: The unique key (name) under which the image was saved in MinIO.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;contentType&lt;/code&gt;: The MIME type of the image.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;contentLength&lt;/code&gt;: The size of the image.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;imageUrl&lt;/code&gt;: The original URL from which the image was downloaded.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;getUrl&lt;/code&gt;: A pre-signed GET URL that allows the user to download the image from MinIO.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;&lt;strong&gt;Endpoint&lt;/strong&gt;: &lt;code class=&quot;language-text&quot;&gt;/api/urls/:key&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;This is the entire endpoint code; it is quite self-explanatory at this point:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/api/urls/:key&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; get&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            put&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            get
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;httpError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;The entire &lt;code class=&quot;language-text&quot;&gt;scr/server.ts&lt;/code&gt;:&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ts&quot;&gt;&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; express&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Response &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cors &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;cors&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; generatePresignedUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; uploadStream &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; axios &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;axios&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Readable &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;stream&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTTPError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    example&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/api/urls/:key&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; get&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            put&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            get
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;httpError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// add an endpoit /api/upload/images/:key/:url which genereate a get presigned url and upload the image to the presigned url and return the get presigned url&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/api/uploads/images&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;string&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The url query parameter is required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/api/uploads/images?key=example&amp;amp;url=https://example.com/image.jpg&apos;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; HTTPError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The imageUrl query parameter is required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;string&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;The key query parameter is required&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/api/uploads/images?key=example&amp;amp;url=https://example.com/image.jpg&apos;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; HTTPError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; get&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;put&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;get&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;token comment&quot;&gt;// download the content of the imageUrl param and put it in a readable stream. check the content type is an image. retrive the content length and put it in a variable&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; axios&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; responseType&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;stream&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;content-type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentLength &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;headers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;content-length&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;contentType&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;image/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;The URL does not point to an image&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; imageStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Readable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uploadStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; imageStream&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentLength&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contentType&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


        res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            contentType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            contentLength&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            imageUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            getUrl&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; get
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;httpError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;httpError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Response&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ERROR: &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err 
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt; 
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; err
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; err
        &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; _err &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; err &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; HTTPError&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        
        res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; _err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            example&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; _err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;example&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            status&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
            message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; err&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Start the server on port 3000&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Server is running on http://localhost:&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Npm scripts:&lt;/h2&gt;
&lt;p&gt;is worth to mention how the npm scripts are working in this project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;s3-test&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ...
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;cli&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsx src/cli.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;start:db&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;docker compose up&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsx src/server.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;dev:server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node --import=tsx --watch src/server.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;concurrently --kill-others=true &apos;npm run start:db&apos; &apos;npm run dev:server&apos; &quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ...
  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;dev&lt;/em&gt;: start the server and the docker compose using concurrently&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;start:db&lt;/em&gt;: docker copose&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;dev:server&lt;/em&gt;: spin up the node.js server with hotreloading&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;cli&lt;/em&gt;: run a test to upload the test.jpeg image in the asset directory&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You’ve now successfully set up a Node.js server with MinIO for handling image uploads using pre-signed URLs. MinIO offers a cost-effective, self-hosted alternative to AWS S3 for object storage, and the use of pre-signed URLs allows clients to securely upload and retrieve files without exposing sensitive credentials.&lt;/p&gt;
&lt;p&gt;For the complete code, visit the repository &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/s3-test-minio&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt; and start building your own object storage solution locally with Node.js and MinIO.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Effortless Node.js Development with TypeScript: A Zero-Configuration Guide]]></title><description><![CDATA[This guide provides a straightforward approach to setting up a Node.js project with TypeScript, without the need for complex configurations…]]></description><link>https://casual-programming.com/effortless_nodejs_development_with_typescript/</link><guid isPermaLink="false">https://casual-programming.com/effortless_nodejs_development_with_typescript/</guid><pubDate>Tue, 23 Jul 2024 16:37:00 GMT</pubDate><content:encoded>&lt;p&gt;This guide provides a straightforward approach to setting up a Node.js project with TypeScript, without the need for complex configurations. By taking advantage of the latest Node.js features like watch mode, the built-in test runner, and the assert library, this setup minimizes dependencies while ensuring a smooth and efficient development experience. Follow step-by-step instructions to initialize your project, integrate TypeScript, set up Git, and add testing capabilities. In this guide I wanted to minimize to depencencies you install and the configuration files you have to add in your project. If you are not doing Frontend you can go very far with a very simple scaffolding.&lt;/p&gt;
&lt;h1&gt;TLDR&lt;/h1&gt;
&lt;p&gt;for the more impatients, just here is the &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/boilerplate_node_typescript&quot; title=&quot;source code&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;source code&lt;/a&gt;. Just go there and follow the README.&lt;/p&gt;
&lt;h1&gt;Scaffolding a Node.js Project with TypeScript with No Configuration&lt;/h1&gt;
&lt;p&gt;Creating a Node.js project with TypeScript without the hassle of complex configurations can be streamlined with the following steps. This guide walks you through setting up a boilerplate project that includes TypeScript support, automatic type checking, and testing.&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before we start, install &lt;code class=&quot;language-text&quot;&gt;fnm&lt;/code&gt; (Fast Node Manager) and use it to install Node.js version 20:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;fnm &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; v20.15.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Initialize the Node.js Project&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a new directory for your project and navigate into it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; boilerplate_node_typescript
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; boilerplate_node_typescript&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Initialize a new Node.js project:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; init&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(Optional) If you are using &lt;code class=&quot;language-text&quot;&gt;fnm&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;nvm&lt;/code&gt;, set the Node.js version for the project:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; .nvmrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, every time you navigate into the project directory, the Node.js version will be set automatically.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Set Up Git&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Initialize a new Git repository:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; init&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code class=&quot;language-text&quot;&gt;.gitignore&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; .gitignore&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the following lines to &lt;code class=&quot;language-text&quot;&gt;.gitignore&lt;/code&gt; to exclude the &lt;code class=&quot;language-text&quot;&gt;node_modules&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;dist&lt;/code&gt; directories:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gitignore&quot;&gt;&lt;pre class=&quot;language-gitignore&quot;&gt;&lt;code class=&quot;language-gitignore&quot;&gt;&lt;span class=&quot;token entry string&quot;&gt;node_modules&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token entry string&quot;&gt;dist&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Install TypeScript&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install TypeScript and &lt;code class=&quot;language-text&quot;&gt;tsx&lt;/code&gt; (a tool for running TypeScript files directly):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; typescript tsx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; directory and an entry file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; src
&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; src/index.ts&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Update &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Add the following scripts to your &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dist/index.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node --import=tsx --watch --no-warnings src/index.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsc src/index.ts --outDir dist&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;typecheck&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsc src/index.ts --noEmit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;typecheck:watch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsc src/index.ts --noEmit --watch&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node dist/index.js&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Add Some Code&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code class=&quot;language-text&quot;&gt;sum.ts&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; src/sum.ts&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the following code to &lt;code class=&quot;language-text&quot;&gt;src/sum.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update &lt;code class=&quot;language-text&quot;&gt;src/index.ts&lt;/code&gt; to use the &lt;code class=&quot;language-text&quot;&gt;sum&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; sum &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the development script to see your code in action:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This script will watch for changes and reload automatically.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can also build and start the project:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run build
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Add Type Checking&lt;/h2&gt;
&lt;p&gt;While &lt;code class=&quot;language-text&quot;&gt;tsx&lt;/code&gt; is great for development, it doesn’t report type errors. Use TypeScript’s &lt;code class=&quot;language-text&quot;&gt;tsc&lt;/code&gt; for type checking:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add a typecheck script to &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; (already added above):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;typecheck&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsc src/index.ts --noEmit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;typecheck:watch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsc src/index.ts --noEmit --watch&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the type checking script:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run typecheck&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Add Tests&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install &lt;code class=&quot;language-text&quot;&gt;@types/node&lt;/code&gt; for TypeScript support in Node.js:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; @types/node&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a test file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; src/sum.test.ts&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the following code to &lt;code class=&quot;language-text&quot;&gt;src/sum.test.ts&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; sum &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./sum&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; test &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;node:test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; strictEqual &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;node:assert&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;sum(1, 2) equals 3&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;strictEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add test scripts to &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node --import=tsx --test src/**/*.test.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;test:watch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node --import=tsx --test --watch src/**/*.test.ts&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the tests:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;test&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Work in a Reactive Environment&lt;/h2&gt;
&lt;p&gt;For an efficient development workflow, open three terminals and run:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Terminal 1: Development mode&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Terminal 2: Type checking&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run typecheck:watch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Terminal 3: Testing&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run test:watch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You are done! This setup provides a simple and effective way to scaffold a Node.js project with TypeScript without any complex configuration. Enjoy coding!&lt;/p&gt;
&lt;h2&gt;Bonus: adding test coverage.&lt;/h2&gt;
&lt;p&gt;We can use tools like &lt;code class=&quot;language-text&quot;&gt;nyc&lt;/code&gt; to make our life much easier.&lt;/p&gt;
&lt;p&gt;install nyc:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; nyc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;then modify the package.json like this:&lt;/p&gt;
&lt;p&gt;package.json&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;scripts: {
    ...
    &quot;test&quot;: &quot;nyc --reporter=html --reporter=text node  --import=tsx --test src/**/*.test.ts&quot;,
    ...,
    &quot;coverage&quot;: &quot;nyc report --reporter=text --reporter=text-summary&quot;,
    &quot;coverage:html&quot;: &quot;npx http-server coverage&quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;add to your .gitignore the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;...
.nyc_output/*
coverage/*&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;now, if you run &lt;code class=&quot;language-text&quot;&gt;npm test&lt;/code&gt;, you will see some new information after the test run:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/78af432126d410015a21ffd9c6dde9b2/d74fe/01_run_npm_test.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.65822784810127%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAABdklEQVR42q1T2W7cMAyUrcu6ZcleA0mQtC8B+v8fOBW52WCNJCja5mFAiQaHQ3koeu8opTBqrYgxIoTAkXJ0zjljXVeklDhPd8I0TRBCnNHWhn3bQXHbNlADKt73kWuNo3MO8zzDGAOtNaSUUEpxvJ0J3CDGgFILWm/oW+fOtVQmJ+KbMiK6TbAsC+e894zbREQqRJkh3EAacr2A1JKVWGu5+4eR/oRp+YFJVQg55M6CZd/jrwmFOgZR/IfCrxSqfSi8DNLlm0jNK4R6JKnEPqD/j1DaDmVXKFMgTYa27WSFk0XU9UwWus+fCI0ehSOZc0KJiT1H/su5XM2dCrzzbJPgyB6Jv98vwomwvFSkS4aaNdrrhtgi5Kzw8FhhtUF5rqhPFVpp9F87fHCww1bmDeTPE6F/8jDO8CU8R9h8/Tl9c5DTDHtZEC6Bc/HnMHMgf5KdvrDWsR28FbRie9t5M2iUWq/rV3N9X8s8xj2OY6h/4OLP3vA3Z3QXXRNSjK8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;01 run npm test&quot;
        title=&quot;&quot;
        src=&quot;/static/78af432126d410015a21ffd9c6dde9b2/f058b/01_run_npm_test.png&quot;
        srcset=&quot;/static/78af432126d410015a21ffd9c6dde9b2/c26ae/01_run_npm_test.png 158w,
/static/78af432126d410015a21ffd9c6dde9b2/6bdcf/01_run_npm_test.png 315w,
/static/78af432126d410015a21ffd9c6dde9b2/f058b/01_run_npm_test.png 630w,
/static/78af432126d410015a21ffd9c6dde9b2/40601/01_run_npm_test.png 945w,
/static/78af432126d410015a21ffd9c6dde9b2/d74fe/01_run_npm_test.png 1164w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;After&lt;/em&gt; you have runned the test, you will be able to print any time you want several report.&lt;/p&gt;
&lt;p&gt;to run a text based report just run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run coverage&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;you will see:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2bd902ffdc6a2850301374a84f20584b/d74fe/02_npm_run_coverage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.9620253164557%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABkElEQVR42n1Ty46cMBAEY2PAYPMw4BkSKZrdTZRbDrnk/z+s4uoRk+xGk0PJ7bb7Vd1drOuKy+WCbdsemOcZMUbs+y4n/xCU+UZ5WRZBSgnee7Rti67rUPR9L5/4yAcaUaZumiYB7zyNMdBaoyiK52iaBsMwIIwB1lqM4yiOnXMSNYQgdwamTP1pXJal4J1DP3joSkt0ZtW7XgIsS3w4oU7kIWDoh0cVDE4bpdQfh27JmSwdrGtgGwt/BNR1nfmwmEYHk2X/KetMDbc6uDnrtMl6I0kQ77Lsrh3cZycflFEIX8ccscpOFeapRaHKu65UaPPfPjloVT7nsMrlsuRa1zlyjUrpewYZzJS8EuT67zvlE1VVCSTT+GVG+rbBrx4heuxveSSOEWG9jwIbQp7JF3k8x+Mj2CyZgJcfES8/I3Sn4bcWr792XN9yI2Lz//F4OjZH5m++G5vRInyf0KbcpNmiLP7l6hwVdvYjpORt33Ac17wVCemScM3ytq+yMdwCntwY4tyk2+0m5bPME7yz5N9ozfbBesvgcAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;02 npm run coverage&quot;
        title=&quot;&quot;
        src=&quot;/static/2bd902ffdc6a2850301374a84f20584b/f058b/02_npm_run_coverage.png&quot;
        srcset=&quot;/static/2bd902ffdc6a2850301374a84f20584b/c26ae/02_npm_run_coverage.png 158w,
/static/2bd902ffdc6a2850301374a84f20584b/6bdcf/02_npm_run_coverage.png 315w,
/static/2bd902ffdc6a2850301374a84f20584b/f058b/02_npm_run_coverage.png 630w,
/static/2bd902ffdc6a2850301374a84f20584b/40601/02_npm_run_coverage.png 945w,
/static/2bd902ffdc6a2850301374a84f20584b/d74fe/02_npm_run_coverage.png 1164w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;or you can run the html report with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run coverage:html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;now if you go at &lt;code class=&quot;language-text&quot;&gt;http://localhost:8000/&lt;/code&gt; from your browser you will see in details the coverage file by file:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2ea302f47b15cd9afa24808c7f3f28af/b8bf8/03_html_coverage_report.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 27.848101265822784%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAABYlAAAWJQFJUiTwAAABJElEQVR42o2Q226DMBBE+f+Paj8glfrQqgolhYBDuGOwudgGM107kfralY7GOztayRswxlBVFYZBguUNUlahrDiENBiEwii017afkBcdzGbBOUfTtvQ2EJPGvd9xCjk+UoOgrmsotXq00Vifaox5vLWGtdaz2x32sH88vZ1UU95VsC4Kjnmascy0eFWE9p5WbtmB/9RxPHLBtf5G1l6Q8yvuQ4q8TxCXZ+/deIx8SJA0Ea7UM54g62OkbYSUvJzmN+pdlhF3kSFo5gxR84b37JV4QViecOtC1DJGOf6QJnSvT0zjFxFiFiHK7oxivKByc+FyFxQ8QrOkCLSdIFSLfinQzwWk7rBjgfPXTUDtkr4t6E8jjp17NithjgVqkx6XdUpXxy/JJ8m/MuC1jgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;03 html coverage report&quot;
        title=&quot;&quot;
        src=&quot;/static/2ea302f47b15cd9afa24808c7f3f28af/f058b/03_html_coverage_report.png&quot;
        srcset=&quot;/static/2ea302f47b15cd9afa24808c7f3f28af/c26ae/03_html_coverage_report.png 158w,
/static/2ea302f47b15cd9afa24808c7f3f28af/6bdcf/03_html_coverage_report.png 315w,
/static/2ea302f47b15cd9afa24808c7f3f28af/f058b/03_html_coverage_report.png 630w,
/static/2ea302f47b15cd9afa24808c7f3f28af/40601/03_html_coverage_report.png 945w,
/static/2ea302f47b15cd9afa24808c7f3f28af/78612/03_html_coverage_report.png 1260w,
/static/2ea302f47b15cd9afa24808c7f3f28af/b8bf8/03_html_coverage_report.png 1728w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;you can even click on a sigle file to check which part of your source code is not covered by your tests:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8266846bdb0c16e96dbe693856b90a3f/27f8b/04_html_coverage_report_2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 23.417721518987342%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAzklEQVR42pWQTW+DMAyG+f//aOf1usMOE+vUda0oH6JAIMBKHMIzg9bLLtVe+ZHj2HLsRM4J0zTR2ZFLet1ILiVpVlFeO2wvmnPUzUhWNPg5YIyhqmu8CHZw5I3nZW+I00CUli2tFojzWjBrc8f6iBeP07Oov2tZFv5qvVrxPmxxZGxH2xuaTrEVpq8xtta42vxws9xkfMi3G/AIUZw8EZ93HPJnPvNXjsU7h+yNU/lB1p5++XpIao4UQ0Ik0hNm0bGdzh5WU9Y9+Jfu3/EDWKmAadI5Z24AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;04 html coverage report 2&quot;
        title=&quot;&quot;
        src=&quot;/static/8266846bdb0c16e96dbe693856b90a3f/f058b/04_html_coverage_report_2.png&quot;
        srcset=&quot;/static/8266846bdb0c16e96dbe693856b90a3f/c26ae/04_html_coverage_report_2.png 158w,
/static/8266846bdb0c16e96dbe693856b90a3f/6bdcf/04_html_coverage_report_2.png 315w,
/static/8266846bdb0c16e96dbe693856b90a3f/f058b/04_html_coverage_report_2.png 630w,
/static/8266846bdb0c16e96dbe693856b90a3f/40601/04_html_coverage_report_2.png 945w,
/static/8266846bdb0c16e96dbe693856b90a3f/78612/04_html_coverage_report_2.png 1260w,
/static/8266846bdb0c16e96dbe693856b90a3f/27f8b/04_html_coverage_report_2.png 1730w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Exploring Utopian Testing Strategies for Node.js REST APIs]]></title><description><![CDATA[TLDR Writing tests for Node.js REST APIs can be complex due to various challenges: End-to-end (E2E) and integration/unit tests often differ…]]></description><link>https://casual-programming.com/exploring_utopian_testing_strategies_for_nodejs_rest_apis/</link><guid isPermaLink="false">https://casual-programming.com/exploring_utopian_testing_strategies_for_nodejs_rest_apis/</guid><pubDate>Thu, 07 Mar 2024 11:23:00 GMT</pubDate><content:encoded>&lt;h2&gt;TLDR&lt;/h2&gt;
&lt;p&gt;Writing tests for Node.js REST APIs can be complex due to various challenges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;End-to-end (E2E) and integration/unit tests often differ despite overlapping.&lt;/li&gt;
&lt;li&gt;E2E tests are slow and prone to flakiness.&lt;/li&gt;
&lt;li&gt;Unit tests sometimes focus on implementation rather than architecture.&lt;/li&gt;
&lt;li&gt;I/O operations, such as database access and spinning up APIs, make E2E tests slow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solutions like using express.listen(0) and in-memory databases can mitigate this issue. Additionally, a subset of these tests can be run periodically against live environments (that’s what in Vonage we were calling Smoke Tests).&lt;/p&gt;
&lt;p&gt;Check out this &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs-utopistic-testing-approach&quot; title=&quot;Example Code of a Node.js api integrating this Utopian Testing Strategy&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Example Code of a Node.js api integrating this Utopian Testing Strategy&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Let’s talk about testing&lt;/h2&gt;
&lt;p&gt;Let’s discuss some general concepts and problem about testing REST API&lt;/p&gt;
&lt;h3&gt;The Testing Problem&lt;/h3&gt;
&lt;p&gt;The testing landscape for Node.js REST APIs (and REST APIs in general) is fraught with challenges. E2E tests, essential for validating user scenarios, often suffer from slowness and fragility. Conversely, unit tests may not always capture architectural concerns and tend to be implementation-centric. Additionally, the diverse technologies involved in testing further compound the complexity. This is often exacerbated by a culture of siloing developers and SDET, and in general, a lack of consideration of the costs such an approach brings (slowing down refactoring/releases due to extensive test changes can significantly reduce overall quality more than the lack of test coverage).&lt;/p&gt;
&lt;h3&gt;Understanding The Testing Pyramid&lt;/h3&gt;
&lt;p&gt;The testing pyramid, with unit tests at the base, followed by integration tests and E2E tests at the apex, is a reflection of testing priorities. However, the pyramid shape also signifies the increasing “cost” associated with tests as we move towards the top. E2E tests, being more user-like, are costly to maintain and slow to execute. Moreover, parallelizing E2E tests can introduce complexities, such as dependencies between test cases.&lt;/p&gt;
&lt;p&gt;Also often Integrated Tests and E2E tests tend to have great overlap but typically teams tend to not take benefit from this, typically because they are mantained by different teams and they are using different technologies (in my previus company we got the unit/integration tests in javascript and the e2e in python as instance).&lt;/p&gt;
&lt;h3&gt;Understanding Smoke Tests&lt;/h3&gt;
&lt;p&gt;Let me introduce the concept of Smoke Test, which is not very well defined across the industry, but in Vonage it had a very specific meaning.
“Smoke tests” refer to periodic E2E tests that validate essential functionalities of the application. These tests are typically run at regular intervals, providing a quick check on the system’s health. By prioritizing critical paths, smoke tests offer a balance between efficiency and coverage, complementing the broader testing strategy.
In your tests Testing Pyramid this would be a new level at the apex.&lt;/p&gt;
&lt;h2&gt;An Utopian Testing Strategy Proposal.&lt;/h2&gt;
&lt;p&gt;It would be great if you could write the tests once and run them both against your real API and on an in-memory version of your API.
Let’s do that:&lt;/p&gt;
&lt;h3&gt;Configuring your app&lt;/h3&gt;
&lt;p&gt;here is our rest api (and testing) configuration:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; z &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zod&apos;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; envSchema &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;coerce&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;TEST_API_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//if empty, the test will use an inmemory-mock server&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;MONGO_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// if empty, the express server will use an inmemory-mock mongodb version&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;MONGO_DB_NAME&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; env &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; envSchema&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;NODE_ENV: &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;TEST_API_URL: &lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_API_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; env
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I think this is self explenatory&lt;/p&gt;
&lt;h3&gt;Giving your api the ability to run with an inmemory MongoDB&lt;/h3&gt;
&lt;p&gt;I chose MongoDB for simplicity; this can work with every type of DB that has an in-memory version (as far as I know, Postgres and CouchDB have that).
Here is what the dbClient looks like:&lt;/p&gt;
&lt;h3&gt;Having a dedicated rest api&lt;/h3&gt;
&lt;p&gt;Assuming I’ve implemented a &lt;code class=&quot;language-text&quot;&gt;createApp&lt;/code&gt; function which returns an Express app, I can create a test utility:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;createApp&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../server&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Server &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AddressInfo &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;node:net&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; env &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../env&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createMockServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; server&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;Server&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; intUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_API_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createApp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// this will open the server on a random ephimeral port&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; address &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; AddressInfo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;close&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;close&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        intUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;http://localhost:&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        intUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_API_URL&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; intUrl
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function-variable function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;server&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                server&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Basically, if the &lt;code class=&quot;language-text&quot;&gt;TEST_API_URL&lt;/code&gt; environment variable is not set, it will create a mock server and return the URL. The &lt;code class=&quot;language-text&quot;&gt;close()&lt;/code&gt; function needs to be called at the end of your test. If you are setting &lt;code class=&quot;language-text&quot;&gt;TEST_API_URL&lt;/code&gt;, then this function will just return that, and the &lt;code class=&quot;language-text&quot;&gt;close()&lt;/code&gt; function will not do anything.&lt;/p&gt;
&lt;p&gt;Here is how a test looks like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;endpoint /users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; assert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doesNotReject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;close &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createMockServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;axios&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        baseURL&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        method&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;post&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test@email.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;   
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    assert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deepStrictEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;201&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Unexpected status code from POST /users endpoint&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    assert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deepEqual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;test@email.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Unexpected response from POST /users endpoint&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    assert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Expected _id to be defined&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Using an in-memory version of your db&lt;/h3&gt;
&lt;p&gt;Similarly to the REST API, inside the dbClient, you can check if the &lt;code class=&quot;language-text&quot;&gt;MONGO_URL&lt;/code&gt; is set. If not, you will use the in-memory version (so every “ephemeral API” will have a dedicated in-memory DB):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;MongoClient&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;mongodb&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; MongoMemoryServer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;mongodb-memory-server&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; env &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./env&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  email&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;  &lt;span class=&quot;token function&quot;&gt;createDBClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mongoServer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;MongoMemoryServer&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mongo_db_name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mongo_url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MONGO_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    mongoServer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; MongoMemoryServer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    mongo_db_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;db_&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    mongo_url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mongoServer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;  /&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;mongo_db_name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MONGO_DB_NAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;MONGO_DB_NAME is required when using a real mongodb server (aka when MONGO_URL is defined)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    mongo_url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MONGO_URL&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MONGO_DB_NAME&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    mongo_db_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MONGO_DB_NAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; db &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MongoClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mongo_url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; collectionUsers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mongo_db_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;users&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;disconnect&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mongoServer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; mongoServer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;createUser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;User&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;insertedId&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; collectionUsers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insertOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; collectionUsers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findOne&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;_id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; insertedId&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; newUser&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    disconnect&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    createUser
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;how to run this&lt;/h3&gt;
&lt;p&gt;Here is the script section of your &lt;code class=&quot;language-text&quot;&gt;package.json&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// the rest of your package.json file config....&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;script&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tsx watch --env-file=.env src/index.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node --env-file=.env.test  --import tsx --test src/**/*.test.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;test:smoke:createuser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node --env-file=.env.test.smokes  --import tsx --test src/test_e2e/createuser.smoke.test.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;test:w&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;node --env-file=.env.test --import tsx --test --watch  src/**/*.test.ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is the content of the &lt;code class=&quot;language-text&quot;&gt;.env&lt;/code&gt; files (this is used to run the REST API, I’m spinning up MongoDB with Docker locally. Check the &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs-utopistic-testing-approach&quot; title=&quot;example readme&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;example readme&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;MONGO_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;mongodb://root:secret@localhost:27017
&lt;span class=&quot;token assign-left variable&quot;&gt;MONGO_DB_NAME&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;admin%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;here is the content of the &lt;code class=&quot;language-text&quot;&gt;.env.test&lt;/code&gt; files:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# this is empty!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;here is the content of the &lt;code class=&quot;language-text&quot;&gt;.env.test.smokes&lt;/code&gt; files ( I just need to set the &lt;code class=&quot;language-text&quot;&gt;TEST_API_URL&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;TEST_API_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;http://localhost:3000&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Why I call this “Utopian”&lt;/h2&gt;
&lt;p&gt;First of all, even if I called this “Utopian”, it does not solve all the problems. Testing race conditions is one such issue. (Even though if you attach stats on your smoke tests, it can give you some indication of those.) But if you could write just one type of test, it should be this one.&lt;/p&gt;
&lt;p&gt;What you should keep in mind is that testing is just one factor of quality; others include metrics, alerts, type systems, linters (if you believe in them), and software design.&lt;/p&gt;
&lt;p&gt;Anyway, I call this a “Utopia” because it is very difficult to achieve. Typical problems include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not all frameworks of Node.js support listening to ephemeral ports.&lt;/li&gt;
&lt;li&gt;Not all databases provide an in-memory version.&lt;/li&gt;
&lt;li&gt;You may have external dependencies that are very complicated to mock.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Achieving high-quality software involves a delicate balance between various factors, including code quality, test coverage, duplication of effort, metrics, mean time to recovery (MTTR), and refactoring time. By adopting utopian testing strategies, such as incorporating smoke tests, re-evaluating the testing pyramid, and optimizing test execution, developers can navigate the complexities of testing Node.js REST APIs more effectively. This approach fosters meaningful insights, driving continuous improvement and enhancing overall software quality.
Check out this &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs-utopistic-testing-approach&quot; title=&quot;Example Code of a Node.js API integrating this Utopian Testing Strategy&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Example Code of a Node.js API integrating this Utopian Testing Strategy&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Exhaustive Pattern Matching in TypeScript]]></title><description><![CDATA[Pattern matching is a powerful programming construct that allows developers to match values against a series of patterns and execute code…]]></description><link>https://casual-programming.com/exhaustive_pattern_matching_in_typeScript/</link><guid isPermaLink="false">https://casual-programming.com/exhaustive_pattern_matching_in_typeScript/</guid><pubDate>Sun, 03 Mar 2024 20:27:00 GMT</pubDate><content:encoded>&lt;p&gt;Pattern matching is a powerful programming construct that allows developers to match values against a series of patterns and execute code based on the matched pattern. Exhaustive pattern matching ensures that all possible cases are handled, leaving no room for unintended behavior. In this article, we’ll explore exhaustive pattern matching in TypeScript, its importance, and various techniques to achieve it.&lt;/p&gt;
&lt;h2&gt;Why Exhaustive Pattern Matching?&lt;/h2&gt;
&lt;p&gt;Exhaustive pattern matching is crucial for writing robust and maintainable code. By ensuring that all possible cases are handled, it helps prevent unexpected runtime errors and makes code more predictable and easier to reason about.&lt;/p&gt;
&lt;p&gt;Let’s start with an example in Rust to illustrate the concept:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;rust&quot;&gt;&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;token type-definition class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Penny&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Nickel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Dime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Quarter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;value_in_cents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;u32&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt; coin &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Penny&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Nickel&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Dime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Quarter&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this Rust code, the &lt;code class=&quot;language-text&quot;&gt;match&lt;/code&gt; expression guarantees exhaustive pattern matching for the &lt;code class=&quot;language-text&quot;&gt;Coin&lt;/code&gt; enum. Each variant is handled explicitly, leaving no possibility of unhandled cases.&lt;/p&gt;
&lt;p&gt;Try to remove some of the match in the value_in_cents function in &lt;a class=&quot;siteLink&quot; href=&quot;https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2021&amp;gist=66af4923be7b7c1bb165f0d12399ab26&quot; title=&quot;the rust playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;the rust playground&lt;/a&gt;, you will get an error at compile time.&lt;/p&gt;
&lt;h2&gt;Exhaustive Pattern Matching in TypeScript&lt;/h2&gt;
&lt;p&gt;Rust kind of force you to into the Exhaustive Pattern Matching. Typescript does not.
So, if you are a Typescript developer who has never heard of this concept, you may implement the code above in this way:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Check this on the &lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play?ssl=16&amp;ssc=2&amp;pln=1&amp;pc=2#code/C4TwDgpgBAwg9gSwHZQLxQEQAUJKSDKAH0wDkEBjAawgBtCSMARBAWwgcwEUBXAQwBOwCAIwBuAFASAZjyQVgCOCgBufWjwgBJJDFzAAzgAoKiJAC5YZgJSWkPVgCMRUAN4SonqAYDuCYBQAFlAmNm4eXpEUfAbQ2Lj4GOYRkalQAhDAPAIoAIySaZ7RsWSUNPTJhakZWTlQAKwFhcVxLOxJKVXpmdl5AAxNaS3c-EIiHV1eNb1QAEyNnZEAJhDSfDy0wJWT3bUofZ0AvhLHUhJAA&quot; title=&quot;TS Playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Do you see the problem? If you forget to manage a case, the compiler will not help you. If tomorrow, there’s a new type of Coin, the compiler will not tell you that you have to update the &lt;code class=&quot;language-text&quot;&gt;valueInCents&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;(p.s. if you are asking yourself why I didn’t use an enum , it’s because in Typescript &lt;a class=&quot;siteLink&quot; href=&quot;https://dev.to/ivanzm123/dont-use-enums-in-typescript-they-are-very-dangerous-57bh&quot; title=&quot;enum are not type-safe&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;enum are not type-safe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In TypeScript, achieving exhaustive pattern matching involves leveraging the &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; type. By using &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;, TypeScript ensures that a function or switch statement covers all possible input types or values.&lt;/p&gt;
&lt;h3&gt;Enter the &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;What does the &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; keyword do?. In TypeScript, the never keyword represents the type of values that never occur. When a function has a return type of never, it means that the function never returns normally and either throws an error or enters an infinite loop. never is a useful tool for making TypeScript code more robust and ensuring that all possible cases are handled. Read more about it in the &lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/docs/handbook/basic-types.html#never&quot; title=&quot;official TS docs&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;official TS docs&lt;/a&gt; or go even more deep &lt;a class=&quot;siteLink&quot; href=&quot;https://www.zhenghao.io/posts/ts-never&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Using &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; in Functions&lt;/h3&gt;
&lt;p&gt;Here is how we can implement the example we did in Rust using never:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this function, if a new Coin type is introduced in the future, TypeScript ensures that we handle it explicitly by assigning it to a variable of type &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; (which will give a compile error). This guarantees exhaustive pattern matching.&lt;/p&gt;
&lt;p&gt;Try to add a value to the Coin union or to remove a case in the switch &lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play?ssl=16&amp;ssc=2&amp;pln=1&amp;pc=1#code/C4TwDgpgBAwg9gSwHZQLxQEQAUJKSDKAH0wDkEBjAawgBtCSMARBAWwgcwEUBXAQwBOwCAIwBuAFASAZjyQVgCOCgBufWjwgBJJDFzAAzgAoKiJAC5YZgJSWkPVgCMRUAN4SonqAYDuCYBQAFlAmNm4eXpEUfAbQ2Lj4GOYRkalQAhDAPAIoAIySaZ7RsWSUNPTJhakZWTlQAKwFhcVxLOxJKVXpmdl5AAxNaS3c-EIiHV1eNb1QAEyNnZEAJhDSfDy0wJWT3bUofVAxUEgQKiKdAL4SV1ISQA&quot; title=&quot;on the typescript background&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;on the typescript background&lt;/a&gt;, you will see the compiler complaining.&lt;/p&gt;
&lt;h3&gt;Using &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; in Switch Statements&lt;/h3&gt;
&lt;p&gt;Similarly, we can achieve exhaustive pattern matching using &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; in switch statements:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;myFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            value&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This will also return an error in case you forget a &lt;code class=&quot;language-text&quot;&gt;break&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Try to remove a break in the &lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play?ssl=22&amp;ssc=2&amp;pln=1&amp;pc=1#code/C4TwDgpgBAwg9gSwHZQLxQEQAUJKSDKAH0wDkEBjAawgBtCSMARBAWwgcwEUBXAQwBOwCAIwBuAFASAZjyQVgCOClYgAYnIVKkACgqIkALlgGAlMYBuiACZQA3hKhOoj57QjAoFvrR7R0AAySzlAAzgDuCMAUABZQemb2riFOFHyh0Ni4+BiGySkh3r4Q6ACMwQUpAEYCEHxUFQVpGWSUNPR5lSlFfugArI1dUDV1DfkhzZks7LnjlT0lUKVBcwUj9YMT6Zm8gsKinUNOC+gATAOr1bUbl9YQ0nw8tMCHRwtoUAFQ6VBIEBYifIAXwkIKkQA&quot; title=&quot;typescript playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;typescript playground&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Error handling.&lt;/h2&gt;
&lt;p&gt;You may have noticed that in the default branch, which in theory is never reached, I’m returning a 0. The reason is that Typescript is not a very safe/strict type system (and this is by design), so you can always end up having unexpected value. It can be because you are parsing the information from a network request, cli input, file, etc… and your parser is not very strict. Or it can be just because you have just used &lt;code class=&quot;language-text&quot;&gt;as Coin&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CoinNotValid&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// thh compiler will be happy. value is gonna be 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;aka: if I have passed an invalid coin, the value in cent is 0.
you may instead want to be more explicit in the error handling and delegate it to the caller of the &lt;code class=&quot;language-text&quot;&gt;valueInCent&lt;/code&gt; function.
you could throw an Error like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CoinNotValid&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or you could return &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. If you go this way, you should change the signature of the function to return &lt;code class=&quot;language-text&quot;&gt;number | undefined&lt;/code&gt;  The Compiler does not force you, but in this way you will force whoever is using the function to manage &lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;. Obviously I’m assuming you are working with &lt;code class=&quot;language-text&quot;&gt;&quot;strict&quot;: true&lt;/code&gt; in your complier option&lt;/p&gt;
&lt;p&gt;the could would look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CoinNotValid&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//the complier force you to manage the case is undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Go to the &lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play?ssl=18&amp;ssc=119&amp;pln=1&amp;pc=1#code/C4TwDgpgBAwg9gSwHZQLxQEQAUJKSDKAH0wDkEBjAawgBtCSMARBAWwgcwEUBXAQwBOwCAIwBuAFASAZjyQVgCOCgBufWjwgBJJDFzAAzgAoKiJAC5YZgJSWkPVgCMRROQBMI05BDdQA3hJQQVAGAO4IwBQAFlAmNv6BwUkUfAbQ2Lj4GOaJSXlQAhDAPAIoAIyS+UEpaWSUNPQ5VXmFxaVQAKyVVTXpLOzZuc0FRSXlAAzd+b3c-EIig8PBrWNQAExdQ0ke0nw8tMBNSyNtKO6e3r6pUEgQKiJTUAC+Ei8SpkgGwCMG5vZOIjQUDUGm0un0xgw8GQpDgwAAauoEG5CNdoUhrEEiCRxlAAPR44BRaCmVhgWgIQHSOACCjQEBwHhQYBwKCsPhIPgAc2gRJJqWgCAMUHOXlubikQA&quot; title=&quot;typescript playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;typescript playground&lt;/a&gt; and try to remove the &lt;code class=&quot;language-text&quot;&gt;|| 0&lt;/code&gt;. the compiler will complain. Try to remove also the &lt;code class=&quot;language-text&quot;&gt;|undefined&lt;/code&gt; from the signature, now the compiler will be happy. Unluckily it is gonna be up to you to be disciplined.&lt;/p&gt;
&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;While using &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt; for exhaustive pattern matching is effective, there are alternative approaches available in the TypeScript ecosystem:&lt;/p&gt;
&lt;h3&gt;ts-pattern Library&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;ts-pattern&lt;/code&gt; library provides a powerful pattern matching syntax for TypeScript:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; match&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isMatching &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ts-pattern&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Coin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Coin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isMatching&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Coin&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Coin&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Penny&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Nickel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Dime&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Quarter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exhaustive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;valueInCents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;CoinNotValid&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Coin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Check how the complier works on &lt;a class=&quot;siteLink&quot; href=&quot;https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbziAhjAxgCwDR2AZwFk0tgA7AczgF84AzKCEOAchnwFow0YBTKMiwDcAKBHoIZfPADCEcnAC8cANoAiAAq8yZAJ5q4uNQDlg6ANa8ANgaMARUL1tw1ARQCuKWPzUBdOCj4cBJSMKIwumC8cHIKyhFREHQx8mQqZO4gAEb8-mJ07mToMMCScABuKFbuvACSZDLa7AAUEuQAXCnkAJQIInADeHTNAIQExBiY5BTNsWS4bWTd3XBQvDDuAnCFACa8dOS8O-2DaxtbqJMAPHMAfK2p3SeDgwB0AO7AMJjNLFo6uhYuGaK0UtzgAEYni8Xh8vj8WKYLNYgXAQUpwQBWaEwgZw76-BwgXio9FgyEABhxuPxCI8Xj4UFJoPBACZsc8Ya9eAAPTAodzSYDlXgg0TUMQhaSrXj4doZbL8JQVKo1eqNMgtNRzYwQGAANSqwB2BkCXSWcAAPpa4BSREA&quot; title=&quot;TS Playground&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;TS Playground&lt;/a&gt;, to make it run you will need to export it to CodeSandbox (check the export menu in the TS Playground).&lt;/p&gt;
&lt;p&gt;note: I’m not an expert of the ts-pattern library, it is possible there’s a better way to write this.&lt;/p&gt;
&lt;h3&gt;ECMAScript Pattern Matching Proposal&lt;/h3&gt;
&lt;p&gt;The &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/tc39/proposal-pattern-matching&quot; title=&quot;ECMAScript Pattern Matching proposal&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;ECMAScript Pattern Matching proposal&lt;/a&gt; introduces native pattern matching syntax to JavaScript and TypeScript. While still a proposal, it shows promise for simplifying pattern matching in TypeScript in the future.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Exhaustive pattern matching is a valuable technique for writing reliable and maintainable code. By leveraging TypeScript’s type system and features like &lt;code class=&quot;language-text&quot;&gt;never&lt;/code&gt;, developers can ensure that all possible cases are handled, leading to more robust software. Additionally, with libraries like &lt;code class=&quot;language-text&quot;&gt;ts-pattern&lt;/code&gt; and upcoming language features, pattern matching in TypeScript is becoming even more expressive and convenient.
Anyway, My personal opinion is that the pattern matching in typescript  right now, in terms of ergonomics, is  very far from the one you got in languages like Rust.  Such a fundamental things should be part of the language, so I’m really looking forward for the pattern matching proposal.
But don’t wait for it, us it now! with ts-pattern or with never.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[My journey in the React world]]></title><description><![CDATA[Why I’m writing this In this article I’m gonna tell you how I’ve discovered React. It was an exciting journey, becouse At the first I didn’t…]]></description><link>https://casual-programming.com/my_story_with_react/</link><guid isPermaLink="false">https://casual-programming.com/my_story_with_react/</guid><pubDate>Fri, 01 Apr 2022 22:19:00 GMT</pubDate><content:encoded>&lt;h4&gt;Why I’m writing this&lt;/h4&gt;
&lt;p&gt;In this article I’m gonna tell you how I’ve discovered React. It was an exciting journey, becouse At the first I didn’t get react, then I started to understand a series of concept that made me a better developer overall, not only a better js / frontend guy.&lt;/p&gt;
&lt;h4&gt;Who am I&lt;/h4&gt;
&lt;p&gt;I started my careed in my own start up doing &lt;a class=&quot;siteLink&quot; href=&quot;http://www.gwtproject.org/&quot; title=&quot;Google GWT&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Google GWT&lt;/a&gt;, then for 4 years I did mobile websites targetting even very old mobile phones thus having an interface working without JS was a must. In this period I also did a geolocated chat using Angular.js as a freelancer.&lt;/p&gt;
&lt;p&gt;Then I change my job and for 2 years I worked with mustache and React.&lt;/p&gt;
&lt;p&gt;Then 5 years ago I change completly my career and I became a backend developer, since then I follow react as an hobbist and I use it mainly for doing small POC around our APIs.&lt;/p&gt;
&lt;h4&gt;Who should read this?&lt;/h4&gt;
&lt;p&gt;Any JS developer could read this, but I feel that someone who is not familiar with  React and its ecosystem would just be a little overwhealmed by the ammount of things I’m talking about and would not benefit too much with this.&lt;/p&gt;
&lt;h4&gt;Why you should read this&lt;/h4&gt;
&lt;p&gt;By telling you my story I would like you to understand that getting a new framework takes time, you don’t get it all in 5 min (or at least I don’t).&lt;/p&gt;
&lt;p&gt;By giving some “historical” context of how was the frontend world when React came out, I hope to highlinght why React was a big thing back then.&lt;/p&gt;
&lt;p&gt;In the end I hope I will give a brief reacap of all the main React concepts toghether with a list of must see video / must read articles.
Is not gonna be a short read, but if you care only about the Design concepts I m talking, just click on the following list of links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=x7cQ3mrcKaY&quot; title=&quot;Pete Hunt: React: Rethinking best practices -- JSConf EU&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Pete Hunt: React: Rethinking best practices -- JSConf EU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=nYkdrAPrdcw&amp;t=632s&quot; title=&quot;Jin Chen: Talking about Flux&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Jin Chen: Talking about Flux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://en.wikipedia.org/wiki/Isomorphic_JavaScript&quot; title=&quot;Isomorpchic Javascript&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Isomorpchic Javascript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=xsSnOQynTHs&quot; title=&quot;Dan Abramov presenting redux&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Dan Abramov presenting redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#:~:text=While%20container%20components%20tend%20to,as%20classes%20and%20as%20functions.&quot; title=&quot;Presentational and Container Components&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Presentational and Container Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=kp-NOggyz54&quot; title=&quot;How to write Component that do logic&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;How to write Component that do logic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also keep in mind, this is not a React developer guide, there are a lot of better articles and guided for that, starting with the amazing &lt;a class=&quot;siteLink&quot; href=&quot;https://reactjs.org/docs/getting-started.html&quot; title=&quot;Official React Documentation&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Official React Documentation&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;The Journey&lt;/h4&gt;
&lt;h5&gt;Part 1: Adopting React&lt;/h5&gt;
&lt;p&gt;The first part of my react journey is obviously how I decided to use it.&lt;/p&gt;
&lt;p&gt;I start my fist job in London as a frontend developer, the company I was working wanted to migrate their website based on &lt;a class=&quot;siteLink&quot; href=&quot;https://handlebarsjs.com/&quot; title=&quot;handlebarsjs&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;handlebarsjs&lt;/a&gt; to some other more modern js framework and they asked me to choose.&lt;/p&gt;
&lt;p&gt;Everyone kind of knew/want Angular tehre, I had a previus experiense with it. So in I was like “in the end I m gonna choose Angular, but they give me one week, so  I was sure I would have choose  Angular. But I had 1 week to decide, so I decided to write a todo list with Angular, Ember.js and React.
I Wrote the Angular and Ember with no problem, but then I started with React my initial reaction was “what da F** is this?” I do I display things? Why do I have to use so many callbacks everywhere? Where do I put my business logic?&lt;/p&gt;
&lt;p&gt;I was lost. I understood that my usual &lt;a class=&quot;siteLink&quot; href=&quot;https://en.wikipedia.org/wiki/Cowboy_coding&quot; title=&quot;Cowboy Coding Approach&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Cowboy Coding Approach&lt;/a&gt; was not enough to have something working. So I started to search material about React.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Enter Pete Hunt, how I got exited about React&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This was the first video I saw, Pete Hunt back then was working at Facebook and he was kind of “The Voice of React”.
Apparently they presented react before this video and some people didn’t like it at all, telling ironicly that “facebook was rechinking eb best practices”. They use this as the title of this talk that try to explain the React Design decision&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pete Hunt: React: Rethinking best practices — JSConf EU&lt;/em&gt;
&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=x7cQ3mrcKaY&quot; title=&quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;here the takeaway were (and they were A LOT):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Templates incourage poor separation of concerns&lt;/li&gt;
&lt;li&gt;separating technologies (css, html, js) is not really separating concern&lt;/li&gt;
&lt;li&gt;templates reinvent (in a underpowered way) concepts that already exists in programming languages, like (scoping)[&lt;a class=&quot;siteLink&quot; href=&quot;https://en.wikipedia.org/wiki/Scope_(computer_science)&quot; title=&quot;https://en.wikipedia.org/wiki/Scope_(computer_science)&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://en.wikipedia.org/wiki/Scope_(computer_science)&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;not doing spaghetti code is up to you, not to the tecnology. Instead of separate css/html/js, do small component, also, be sure to have components with state separated by component that are pure UI.&lt;/li&gt;
&lt;li&gt;work with your designer.&lt;/li&gt;
&lt;li&gt;react component are just (idempotent function)[&lt;a class=&quot;siteLink&quot; href=&quot;https://en.wikipedia.org/wiki/Idempotence#:~:text=Idempotence%20(UK%3A%20%2F%CB%8C%C9%AA,result%20beyond%20the%20initial%20application&quot; title=&quot;https://en.wikipedia.org/wiki/Idempotence#:~:text=Idempotence%20(UK%3A%20%2F%CB%8C%C9%AA,result%20beyond%20the%20initial%20application&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://en.wikipedia.org/wiki/Idempotence#:~:text=Idempotence%20(UK%3A%20%2F%CB%8C%C9%AA,result%20beyond%20the%20initial%20application&lt;/a&gt;.] (aka if you pass a certain input you will &lt;code class=&quot;language-text&quot;&gt;always&lt;/code&gt; have the same output, like in math)&lt;/li&gt;
&lt;li&gt;React components are pure function that you compose, so they are easyer to test&lt;/li&gt;
&lt;li&gt;To simplify your life, immagine your state as a Giant JSON, and immagine to rerender the entire app all the time&lt;/li&gt;
&lt;li&gt;rewrite your entire app every frame for real is slow, the virtual DOM make this efficent automatically render only the difference. &lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=x7cQ3mrcKaY&amp;t=1207s&quot; title=&quot;AKA react virtual doom is like the Doom3 engine&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;AKA react virtual doom is like the Doom3 engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Virutal DOM can &lt;code class=&quot;language-text&quot;&gt;run in node JS&lt;/code&gt; this means you can test ui with not super convoluted testing environment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was amazed by all of this. I didn’t understood it all, but in my head I got this image:&lt;/p&gt;
&lt;div&gt;
&lt;img src=&quot;https://i.ytimg.com/vi/nYkdrAPrdcw/maxresdefault.jpg&quot; width=&quot;300px&quot; height=&quot;200px&quot;&gt;
&lt;/div&gt;
&lt;p&gt;and I was thinking “oh, my job as developer is just to model the entire state as a big JSON, translate this in visual component according with the designer, and then I m done”. More or less. Still my components were very nested, I found myselef pass callback everywere. Also people were saying me “with backbone or angular I don’t have to pass those callback everywhere, I just use the 2 way binding”.
That’s when I discover Flux.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Meet Jin Chen, how I discover about Flux&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jin Chen: Talking about Flux&lt;/em&gt;
&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=nYkdrAPrdcw&amp;t=632s&quot; title=&quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I ve always struggled with MVC. I found it verbose. Plus at this moment I felt the react idea made a lot of sense, but I was strugling doing even the easier thing.
Luckily I saw this video of  Jin Chang talking about flux, an “unidirectional data flow model”
My understanding here was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MVC can be messy&lt;/li&gt;
&lt;li&gt;2 way binding is bad, unidirectional flow is good&lt;/li&gt;
&lt;li&gt;make the functionality “unread chat messages” which is bug free is really difficult&lt;/li&gt;
&lt;li&gt;the UI just dispatch actions, the store is taking the action and modifing your state. UI just read the state from the store and react to state changes&lt;/li&gt;
&lt;li&gt;react and flux works very well togheter, they are complementary&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a nutshell I had this image in my mind:&lt;/p&gt;
&lt;div&gt;
&lt;img src=&quot;https://imgopt.infoq.com/fit-in/1200x2400/filters:quality(80)/filters:no_upscale()/news/2014/05/facebook-mvc-flux/en/resources/flux-react.png&quot; width=&quot;300px&quot; height=&quot;200px&quot;&gt;
&lt;/div&gt;
&lt;p&gt;also I ve understood why I always struggled with MVC, it can became this:&lt;/p&gt;
&lt;div&gt;
&lt;img src=&quot;https://www.freecodecamp.org/news/content/images/2020/04/Screenshot-2020-04-16-at-6.38.14-PM.png&quot; width=&quot;300px&quot; height=&quot;200px&quot;&gt;
&lt;/div&gt;
Which is a mess!
&lt;p&gt;Adding With flux (or a state manager in general) my code became much more clear. In hear I ve remembrered Pete Hunt saying “not doing spaghetti code is up to you”.&lt;/p&gt;
&lt;p&gt;More concept I was learning and better my code was becamming. Also I had the feeling that I was learning a lot about javascript and pattern design rather then specific things about React And Flux.&lt;/p&gt;
&lt;p&gt;Also at this point something was clear to me: Facebook is using React for doing facebook itself and instagram. Google back then was not using angular for doing gmail or google.&lt;/p&gt;
&lt;p&gt;I started using that at work.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Isomorphic Javascript aka Server Side Rendering&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Somewhere I can find now, I get the concept of &lt;a class=&quot;siteLink&quot; href=&quot;https://en.wikipedia.org/wiki/Isomorphic_JavaScript&quot; title=&quot;Isomorpchic Javascript&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Isomorpchic Javascript&lt;/a&gt;.
This means you can render your JS both in the backend and in the frontend. You can do this for 2 reason:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;prerender stuff on the backend make feel the loadtime much faster to the user.&lt;/li&gt;
&lt;li&gt;if used extensivly, your app can work even wihtout JS.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Given my context, I was even more amazed by those possibility, but the tools were clearly not making easy all those things.&lt;/p&gt;
&lt;h5&gt;Phase 2: Improving React knoledge&lt;/h5&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;The rising of Redux&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;… TODO …&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Here I am using React and Flux and this promise of a server side rendering. but flux was not really thinked for that.
To be fear Flux was a library, but it was described with the sentence: “more a pattern then a library”
I remember the impression I had, everyione liked the Flux pattern, but a lot of ppl though the Flux library could be improved.
So library like &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/yahoo/fluxible&quot; title=&quot;https://github.com/yahoo/fluxible&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/yahoo/fluxible&lt;/a&gt; and &lt;a class=&quot;siteLink&quot; href=&quot;https://acdlite.github.io/flummox&quot; title=&quot;https://acdlite.github.io/flummox&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://acdlite.github.io/flummox&lt;/a&gt; were rising. I was even writing mine on top of FLux. I wanted to write samething that makes you achive the SSR in an simple way.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Dan Abramov presenting redux&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=xsSnOQynTHs&quot; title=&quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;hot reload? “time travel”? are you craxy? I rememberd I though “ok, this guy as won”.
I abbandoned any work I was doing to my framework based on flux and I started to use it.&lt;/p&gt;
&lt;p&gt;Redux was everything I wanted and it was offering a lot of things that I didn’t know yet I wanted.
The vast majority of it was just javascript (an action is just a json, a reducer is just a function, the compose utils was litteraly something he could have been released by itelf).&lt;/p&gt;
&lt;p&gt;I started to use it but after a while I had some problem writing code, I felt I was nesting a lot of things and my code was generically hard to change. I thought that maybe the fault was that redux was too long to write, so I tryied to reduce the boilerplate writing a framework on top of redux called &lt;a class=&quot;siteLink&quot; href=&quot;https://www.npmjs.com/package/reduxt&quot; title=&quot;reduxt&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;reduxt&lt;/a&gt;. It didn’t helped much (and looking this know I feel a little bit of shame for reduxt :P). As often to me while using React, the problem was not the tool itself, but the way you are designing your code. Luckily I read this MUST READ article of Dan Abramov: &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#:~:text=While%20container%20components%20tend%20to,as%20classes%20and%20as%20functions.&quot; title=&quot;Presentational and Container Components
&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Presentational and Container Components
&lt;/a&gt; and my life changed. I realised that no other tools or library were needed, I ve just needed to learn how to organize my code better.&lt;/p&gt;
&lt;p&gt;Now my state was written in a bunch of pure js functions (the reducers) and the visualization was written in a bunch of components that were as well pure js functions (what dan called presentational component in the article). another way to see it is the following: 1 your state is just a big JSON object 2 this json object is generated by the your reducers that accept an action and the prevState and return a specific part of the state, 3 the presentational components take part of those json using maybe some selectors and they just render it in HTML.
Everything else a side those  things is just gloo you write to make stuff work, namely Containers Components, Sagas , middleware , etc etc..&lt;/p&gt;
&lt;p&gt;The good part is that you can write your UI and THEN make it work for real. I still remember when I wrote my login/logout logic. As you can immagine in the first iteration I was loosing the login every time I ve refreshed the page. To solve that, I ve just to added a middleware (maybe &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/BartWaardenburg/redux-simple-storage-middleware&quot; title=&quot;this one&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;this one&lt;/a&gt;) and it just worked, with 0 changed in every part of the code. If you have experience with redux this could seems obvious, but to me back then, I could feel how much feel “clean” working with react and redux.&lt;/p&gt;
&lt;p&gt;takeaways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the “important” thing in your website are: store, reducers, selectors, actions, presentational components.&lt;/li&gt;
&lt;li&gt;every side effect should be outside of those (unless in the action you are using thunk), typically in middlewares&lt;/li&gt;
&lt;li&gt;the vast majority of your UI is in the presentational components.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*** How to work with the designer: Styleguide ***&lt;/p&gt;
&lt;p&gt;I was starting be confident with react, and in this period I started a semi-serius pet project with a colegue of mine, who was a UI/UX designer who could code some JS.&lt;/p&gt;
&lt;p&gt;One of the thing the React team was stressing in their talk was to work a lot with the designer, if the UX designer is using a tool like desing tools like Figma or Sketch, the way they organize their components should be exaclty the same as your UI component.&lt;/p&gt;
&lt;p&gt;In my experience this is true if your designer is focusing a lot on the UX, that means usability, wich means consistency, wich usually means the abstract the UI in the right way reusing components when it make sense.&lt;/p&gt;
&lt;p&gt;Luckily for me this was the situation, so in this side project I did the backend and in the frontend I let the designer write entirely by himself the presentational component.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;The React Router&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;… TODO …&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=Vur2dAFZ4GE&quot; title=&quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;How to write Component that do logic&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;… TODO …&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=kp-NOggyz54&quot; title=&quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;How to write Component that do logic&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;… TODO …&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=kp-NOggyz54&quot; title=&quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Recent” react stuff&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;React Hooks and context API&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Possibilities and tools react allows&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Next.js the missing framework&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s a quote from a friend of mine .
Next js was making it easier the webpack configuration, you can do it only if you got&lt;/p&gt;</content:encoded></item><item><title><![CDATA[An interactive way to learn javascript: jsquest]]></title><description><![CDATA[Do you want to learn javascript / test your javascript skills, but reading articles and books is not your cup of tea? Here you go:  That s…]]></description><link>https://casual-programming.com/an_interactive_way_to_learn_javascript_jsquest/</link><guid isPermaLink="false">https://casual-programming.com/an_interactive_way_to_learn_javascript_jsquest/</guid><pubDate>Tue, 17 Aug 2021 22:19:00 GMT</pubDate><content:encoded>&lt;p&gt;Do you want to learn javascript / test your javascript skills, but reading articles and books is not your cup of tea?&lt;/p&gt;
&lt;p&gt;Here you go: &lt;a class=&quot;siteLink&quot; href=&quot;https://jsquest.io&quot; title=&quot;https://jsquest.io&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://jsquest.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That s all you need to know, go there and play with it, you will get it, the rest of the article is gonna just be some blah blah about why I did it and how.&lt;/p&gt;
&lt;h3&gt;What is this jsquest&lt;/h3&gt;
&lt;p&gt;If you are a person who can focus very intensively but just for very short amount of time, then I’m sure you struggle when you try to read books about coding. They are long, a lot of words, is hard to focus for me.&lt;/p&gt;
&lt;p&gt;That’s why my preferred guide for js is this one: &lt;a class=&quot;siteLink&quot; href=&quot;http://xahlee.info/js/js.html&quot; title=&quot;http://xahlee.info/js/js.html&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;http://xahlee.info/js/js.html&lt;/a&gt;. I really think It’s describing JS in the minimum amount of words possible.&lt;/p&gt;
&lt;h3&gt;The story of jsquest&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;March 2007,&lt;/strong&gt; i need to do my driving license, and I decide to study for the theory exam by myself. I found this amazing app where there are questions divided by arguments. You can try to respond, if you fail, there’s a link to the theory of that argument. That s just amazing and in one week I pass the exam. (Then it took me months to pass the driving exam, but that’s another story).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;December 2011,&lt;/strong&gt; is night, I’m in my bed thinking: “I want to improve my JS skills”. Js was my main language since a couple of years, but I felt I was using it like I was using JAVA (not in the best way, probably). So I’ve searched on google “advanced javascript”. I end up in this website where there was just some interactive code. Nothing else. But just trying to change the code, was enough for me to feel I was learning. It was mind blowing! Then I discovered that that website was supplementary material for &lt;a class=&quot;siteLink&quot; href=&quot;https://www.manning.com/books/secrets-of-the-javascript-ninja-second-edition?gclid=Cj0KCQjwvO2IBhCzARIsALw3ASpUYSSM4DP8wyBeWjvL5lDF2wR205voX6UfDx8SzfsgOeGi2izieTIaAnsUEALw_wcB&quot; title=&quot;Secrets of the JavaScript Ninja&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Secrets of the JavaScript Ninja&lt;/a&gt; from &lt;a class=&quot;siteLink&quot; href=&quot;https://johnresig.com/&quot; title=&quot;John Resig&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;John Resig&lt;/a&gt;, the author of &lt;a class=&quot;siteLink&quot; href=&quot;https://en.wikipedia.org/wiki/JQuery&quot; title=&quot;jQuery&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;jQuery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;February 2015,&lt;/strong&gt; my team leader at the time ask me to teach some javascript to our designer. Also, 3 friends of mine wanted to change their position at the same time, they were all JS developers. This is when I discover the &lt;a class=&quot;siteLink&quot; href=&quot;http://xahlee.info/js/js.html&quot; title=&quot;Xah Lee JS guide&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Xah Lee JS guide&lt;/a&gt; and I’ve started to use it to structure my lessons. I did with all of them several calls, i would say I’ve spent probably 20 hours with all of them to explain js fundamentals. The way I was doing this it was explaining them things via Skype and then Using a google docs to make them questions. In order to not have any misunderstanding, the questions were js code. And they had to respond with the result of the code execution. I call it &lt;em&gt;“forcing people to understand”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;October 2016,&lt;/strong&gt; another couple of people heard about those “courses” and they would love the idea of doing them but as you can imagine, is not easy to dedicate around 20 hours per person and everyone is busy, so is hard to get organized. Is also not particular pleasant to get lessons from me, patience is not exactly my best quality. That s when I’ve decided to do &lt;a class=&quot;siteLink&quot; href=&quot;https://jsquest.io&quot; title=&quot;jsquest&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;jsquest&lt;/a&gt;, taking inspiration from all the moments I told you.&lt;/p&gt;
&lt;h3&gt;The how of jsquest&lt;/h3&gt;
&lt;p&gt;I’ve created this react website (which work also offline, because I’m obsessed with offline first JS app). So is a classic creater-react-app website.
I’m the most absent mind person ever, so in the very end every question is just an object in an array like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; questions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;  
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;    
     &lt;span class=&quot;token literal-property property&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;default assignment&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token literal-property property&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;var a; log(a);&quot;&lt;/span&gt;  
   &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code is evaluated when you click “Check” with the js command eval, check here to see the implementation. it worked almost in every case aside some edge case where &lt;a class=&quot;siteLink&quot; href=&quot;https://stackoverflow.com/questions/40143683/execute-javascript-in-a-sand-box&quot; title=&quot;not even stackoverflow could help me&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;not even stackoverflow could help me&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I save every given response in the local storage, evaluating on load time if they are true or not.
For doing the responsive layout, I‘ve experimented a little with the &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries&quot; title=&quot;CSS container queries&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;CSS container queries&lt;/a&gt; using the library &lt;code class=&quot;language-text&quot;&gt;react-container-query&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I ‘ve beautified the code with this trick I used often in React, doing something like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pre&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;  &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;pre&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;adding a string with two whitespace as the third argument of JSON.stringify, is gonna format the code using those two space as formatter token.&lt;/p&gt;
&lt;p&gt;I use it in my node.js debug all the time. The problem if you want to render this in html is that the content is automatically formatted, the only way to preserve the formatting is using the  tag &lt;code class=&quot;language-text&quot;&gt;pre&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I’ve tryed to use react component to do code highlight instead of this trick, but the render was slow and in the end I prefer a responsive user experience then adding the colors.&lt;/p&gt;
&lt;h3&gt;In the end&lt;/h3&gt;
&lt;p&gt;It was a fun experiment, the whole experience made me a better js developer. Probably online there are tons of better interactive platforms to test/study JS, such as &lt;a class=&quot;siteLink&quot; href=&quot;https://justjavascript.com/&quot; title=&quot;https://justjavascript.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://justjavascript.com/&lt;/a&gt;, so if your goal is to learn JS, check around.&lt;/p&gt;
&lt;p&gt;But if you like the project and you want to contribute, feel free to send your PR here: &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/js_questions&quot; title=&quot;https://github.com/jurgob/js_questions&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/js_questions&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[An easy way to try Vonage Communication API locally]]></title><description><![CDATA[At Vonage’s API department we’ve designed a collection of tools you might have come across as Communication API```. It allows you to do…]]></description><link>https://casual-programming.com/an-easy-way-to-try-vonage-communication-api-locally/</link><guid isPermaLink="false">https://casual-programming.com/an-easy-way-to-try-vonage-communication-api-locally/</guid><pubDate>Sun, 08 Aug 2021 16:37:00 GMT</pubDate><content:encoded>&lt;p&gt;At Vonage’s API department we’ve designed a collection of tools you might have come across as Communication API```. It allows you to do anything from sending/receiving SMS and phone calls, to creating video, audio, and text chats, all the way to the really “crazy” stuff like connecting a regular phone call to someone responding from a browser.&lt;/p&gt;
&lt;p&gt;This article is not about Communication API. I will instead introduce you to a CLI tool called &lt;strong&gt;Conversation API function&lt;/strong&gt; that will deeply simplify prototyping apps using Communication API, with as little config as possible.&lt;/p&gt;
&lt;p&gt;If I have tingled your attention, and you want to get your hands in the dirt, visit &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/conversation-api-function&quot; title=&quot;https://github.com/jurgob/conversation-api-function&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/conversation-api-function&lt;/a&gt; and follow the instructions from there. &lt;strong&gt;You will have something up and running in less than 20 minutes&lt;/strong&gt; (10 if you are a node developer).&lt;/p&gt;
&lt;p&gt;If you have some extra time, make sure to also check out the examples and learn the variety of things this CLI allows you to do. You can stop reading here if you were just looking for a quick installation guide :).&lt;/p&gt;
&lt;p&gt;But if you want to know something more about the why and the what of this CLI, keep reading on…&lt;/p&gt;
&lt;h3&gt;&lt;em&gt;&lt;strong&gt;The Vonage configuration API fatigue&lt;/strong&gt;&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;To test our communication API, you need to set up several things. let’s say you want to test how you can receive a voice call and say some text, and you want to do it locally. what you need to do is the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;register to Vonage and buy an LVN&lt;/li&gt;
&lt;li&gt;create an application&lt;/li&gt;
&lt;li&gt;configure your number to be connected to your application&lt;/li&gt;
&lt;li&gt;your “backend” is in your local machine as far as you are developing, so you need to expose this somehow with tools like Localtunnel.&lt;/li&gt;
&lt;li&gt;configure your application to hit your public Locatunnel address, so you can receive in your local application the Vonage events.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;after you do this, you can test a scenario where you receive a phone call.
Let’s say you want to try a PHONE to BROWSER scenario. That means you have to add the following steps:&lt;/p&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;setup some frontend&lt;/li&gt;
&lt;li&gt;configure our SDK in your frontend&lt;/li&gt;
&lt;li&gt;typically set up some DB for storing some state of your business app.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Those steps are “easy” but not a little time-consuming, and the initial configuration and setup can be still pretty tricky for new developers.&lt;/p&gt;
&lt;p&gt;Simplifying this is the main reason I wrote this tool.&lt;/p&gt;
&lt;p&gt;In the below picture, a schema of a typical app using Communication APIs, in this case using the so-called &lt;strong&gt;Conversation API&lt;/strong&gt; and the &lt;strong&gt;Voice API&lt;/strong&gt;. THere’s also a front end using the &lt;strong&gt;Client SDK&lt;/strong&gt;:&lt;/p&gt;
&lt;img style=&quot;max-width: 600px; width: 100%&quot; src=&quot;https://developer.vonage.com/images/conversation-api/conv-app-setup.png&quot;&gt;
&lt;h3&gt;&lt;strong&gt;What the tool is doing for me? the short version&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This tool requires just some minimal configuration once, then you will be able to develop and execute those javascript examples, that from now on I’m gonna call &lt;em&gt;conversation function,&lt;/em&gt; in a super-easy way, and they are gonna be testable in your local machine!.&lt;/p&gt;
&lt;p&gt;Do you want to share an example with someone else? just publish it on Github, if another person wants to test it, he can just download it, eventually run `npm install` and run the example. You are gonna run the same code, but you will not share any data or information!.&lt;/p&gt;
&lt;p&gt;You may already have everything you need at this point, and you may prefer digging into the examples rather than reading the rest of the article. It’s fine! do it! Possibly have fun and create a new example of a use case I still didn’t think about, I accept pull requests in the read me!&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;What the tool is doing for me?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;note:&lt;/strong&gt; again, you can use the tool without really knowing all of the following, but is gonna help you in a deeper understanding of the tool and the Vonage API itself.&lt;/p&gt;
&lt;p&gt;In general, when you use our API, you need to do the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The very first time, you need to create an account (e.g. My Company)&lt;/li&gt;
&lt;li&gt;once you’ve got an account, (with the related api_key and api_secret), you need to create an application (e.g: My Chat Application or My Telephony Support System)&lt;/li&gt;
&lt;li&gt;Once you create an application you get a private key, you need that to generate a JWT token.&lt;/li&gt;
&lt;li&gt;If you want to program an incoming call or incoming Facebook message(e.g. you want to say “hello” to everyone calling you), you need to have a Vonage phone number (so-called LVN, Long Virtual Number), and you need to bind it to your application. Also, you need to configure a set of webhook URLs with your back end URL in order to be notified about something that happened in your application (e.g. someone is calling your LVN number)&lt;/li&gt;
&lt;li&gt;if you are implementing the use case in step 4 and you want to test it locally, then you have to expose your laptop with some tool like &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/localtunnel/localtunnel&quot; title=&quot;Localtunnel&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Localtunnel&lt;/a&gt; or &lt;a class=&quot;siteLink&quot; href=&quot;https://ngrok.com/&quot; title=&quot;Ngrok&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Ngrok&lt;/a&gt; and then update your application’s webhook in order to reach your laptop.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;conversation-api-functions&lt;/strong&gt; is gonna automatically run the steps 1/2/3 once you run the &lt;code class=&quot;language-text&quot;&gt;fist_config&lt;/code&gt; command. Every time you use &lt;code class=&quot;language-text&quot;&gt;run&lt;/code&gt; to execute your node function, steps 4 and 5 are gonna be done.&lt;/p&gt;
&lt;p&gt;As soon as the &lt;code class=&quot;language-text&quot;&gt;first_config&lt;/code&gt; is creating a new &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.nexmo.com/application/overview&quot; title=&quot;Vonage application&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Vonage application&lt;/a&gt;, this app is gonna be used for every conversation function you are gonna run on your laptop, and every device where you are gonna run that is gonna use a different application. That’s why if someone else is using your code, the data are not gonna be shared anyhow.&lt;/p&gt;
&lt;h3&gt;The anatomy of a conversation function&lt;/h3&gt;
&lt;p&gt;In the creation of this tool, I got inspired a lot from tools like &lt;a class=&quot;siteLink&quot; href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/welcome.html&quot; title=&quot;AWS Lamda function&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;AWS Lamda function&lt;/a&gt; , &lt;a class=&quot;siteLink&quot; href=&quot;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html&quot; title=&quot;AWS SAM&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;AWS SAM&lt;/a&gt; and &lt;a class=&quot;siteLink&quot; href=&quot;https://jamstack.org/&quot; title=&quot;Jamstack technologies&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Jamstack technologies&lt;/a&gt; and in particular &lt;a class=&quot;siteLink&quot; href=&quot;https://vercel.com/&quot; title=&quot;Vercel&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Vercel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All those things strive to let you focus only on what you are doing, without the need to be worried about details like “coding my infrastructure or “adding a CDN in front of my application” or “configure Webpack to split my Javascript code per page”. Those are concepts that you may ignore your all life and still be very successful in writing Next.js app in Vercel or lambda functions in ASW SAM.&lt;/p&gt;
&lt;p&gt;in the same way, all you need to do when you write a conversation function is to write an &lt;code class=&quot;language-text&quot;&gt;index.js&lt;/code&gt; file where you export a js module that exports certain methods.&lt;/p&gt;
&lt;p&gt;what those methods do, are documented &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/conversation-api-function/blob/main/template/index.js&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;you may notice that excluding the handler &lt;code class=&quot;language-text&quot;&gt;route&lt;/code&gt; is a bit of an exception, every other handler has a 1:1 relationship with the webhook capabilities you can configure in your application. Check the &lt;strong&gt;Webhook types&lt;/strong&gt; section in this link: &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.nexmo.com/application/overview&quot; title=&quot;https://developer.nexmo.com/application/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://developer.nexmo.com/application/overview&lt;/a&gt;, check for example the first row that shows &lt;code class=&quot;language-text&quot;&gt;voice&lt;/code&gt; property with and &lt;code class=&quot;language-text&quot;&gt;answer_url&lt;/code&gt; sub-property. &lt;br&gt;
In the CLI you just need to implement the &lt;code class=&quot;language-text&quot;&gt;voiceAnswer&lt;/code&gt; handler, which is an express middleware.&lt;/p&gt;
&lt;p&gt;As you can see you don’t need to be concerned about the part where you configure/update your Vonage app, or even spin up your express server.&lt;/p&gt;
&lt;h3&gt;In Conclusion&lt;/h3&gt;
&lt;p&gt;I’ve briefly introduced this new internal tool to quickly use the Vonage Communication API, if you have reached this part of the article, probably you now have a working example on your laptop and you’ve learned some notion about the Vonage API echo system. Your next step should now go in the Examples section here: &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/conversation-api-function#examples&quot; title=&quot;https://github.com/jurgob/conversation-api-function#examples&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/conversation-api-function#examples&lt;/a&gt; and see how many crazy things you can do!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Nodejs audio, lesson 5: make a phone call to your laptop with Vonage API]]></title><description><![CDATA[So that’s when I bring on what I do for living In lesson1 and lesson2 we saw how to use row audio in nodejs, and how to use your mic and…]]></description><link>https://casual-programming.com/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api/</link><guid isPermaLink="false">https://casual-programming.com/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api/</guid><pubDate>Sun, 08 Aug 2021 01:57:00 GMT</pubDate><content:encoded>&lt;p&gt;So that’s when I bring on what I do for living&lt;/p&gt;
&lt;p&gt;In lesson1 and lesson2 we saw how to use row audio in nodejs, and how to use your mic and speaker. &lt;br&gt;
Today we are gonna see how to make this audio going over the internet and connect it to a mobile phone.&lt;/p&gt;
&lt;h3&gt;Make it run&lt;/h3&gt;
&lt;p&gt;To make you understand deeply what we are gonna do, I have to explain you several concept of the vonage api, but first I want to you to see this working, just to get you exited.&lt;/p&gt;
&lt;p&gt;go there &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/conversation-api-function&quot; title=&quot;https://github.com/jurgob/conversation-api-function&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/conversation-api-function&lt;/a&gt; follow the instruction to make it work.&lt;/p&gt;
&lt;p&gt;In short, that’s a cli command to execute some examples. Now clone this repo: &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/ws-phonecall-receiver&quot; title=&quot;https://github.com/jurgob/ws-phonecall-receive r&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/ws-phonecall-receive r&lt;/a&gt;and make it run with the cli.&lt;/p&gt;
&lt;p&gt;In the process you were required to buy and configure a phone number from vonage (the so-called LVN, Long Virtual Number). What you have to do now is start the &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/ws-phonecall-receiver&quot; title=&quot;ws-phonecall-receive&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;ws-phonecall-receive&lt;/a&gt; example and after that dial the lvn from your phone.&lt;/p&gt;
&lt;p&gt;You are gonna hear your phone audio through your computer speaker and you will be able to respond back!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some context first&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before I explain what is going on, I need to explain what you are using.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Vonage Comunication API &lt;a class=&quot;siteLink&quot; href=&quot;https://www.vonage.co.uk/communications-apis/apis/?icmp=l3nav_apis_novalue#Communications&quot; title=&quot;https://www.vonage.co.uk/communications-apis/apis/?icmp=l3nav_apis_novalue#Communications&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://www.vonage.co.uk/communications-apis/apis/?icmp=l3nav_apis_novalue#Communications&lt;/a&gt; Are a set of api that allows you to do video, audio, send sms, IM messages and chat in an easy way&lt;/li&gt;
&lt;li&gt;When you work with real time api like ours, the comunication is tipical bidirectional, so you reach the api, but also the api need to be able to reach you. You typically do this adding your server address in the webhook configuration, but for doing it in your localhost, you need some trick, so to simplify this, I did the the tool called conversations-api-function.&lt;/li&gt;
&lt;li&gt;so again, &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/conversation-api-function&quot; title=&quot;https://github.com/jurgob/conversation-api-function&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/conversation-api-function&lt;/a&gt; is a cli tool that I did for internal usage (so don’t expect support on that), it is done so you can quickly build prototype in your laptop and test them locally (is called conversation-api-function because initially I got kind of inspired by the aws lamda functions)&lt;/li&gt;
&lt;li&gt;What the conversation-api-function is doing for you is just creating an &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.nexmo.com/application/overview&quot; title=&quot;application&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;application&lt;/a&gt; , and connecting it to your LVN.&lt;/li&gt;
&lt;li&gt;The application has some webhook you can configure to notify your back end every time something happen (e.g. someone is calling you). Every time you start locally your code, your laptop is exposed on the public internet and the application is updated in order to inform your laptop&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/80ebadc46dada258d24355ace0260e36/b12f7/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-0.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 76.58227848101265%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAABq0lEQVR42m1Ty07CQBTt//EBrP0Df8BEXLkg8ROMf8CCaIhGgguibaligNDSQLGltPRt6UNXnnakTEfPYtK5M+fec++ZclEUfVLYHxDHcRVk7lTg6IMgCGzb3u12ZKWZcR0sGdXW6/V2uwXTdV1N0yzLSpIEcST1PI+sBIR1JOP2osRkMhEEQVVVXddxivh0OhVFcTgc8jyPI6wIIilHJEEkyi6XS1RbrVbgG4YBsu/7+FAU5a2EJEnj8Xg2myFYkMMwNE0TarMs00tgC+W4gYxJiaovx3HQ0bFnFBwMBlCCEET6B8znc+QlQdIaVuiqvn97RlncZmxAHBJQp5o2GSRtYdEz5KEIwyQrdKJakTqOLdtmfU7TFGfEEtpz8o0g8hbOW5a5MZL6HQ7Ta7Va7XYbRWhJFQrBjqt+mLK2KZkUudvtwoNOpwM/oIJ5idjmafLw/H5xc399K3hBuC9GSJFhWr/fl2UZbjHkMIy+v/K7x6eT07PzyytFWdQq93q9RqPRbDaRAp3//QcgG0Me8S+vkoj3U+sZGzwsMIml//49SICOsjzH/Ohp/wDXTjCZKDIHxQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;lesson 5 make a phone call to your laptop with vonage api 0&quot;
        title=&quot;&quot;
        src=&quot;/static/80ebadc46dada258d24355ace0260e36/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-0.png&quot;
        srcset=&quot;/static/80ebadc46dada258d24355ace0260e36/c26ae/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-0.png 158w,
/static/80ebadc46dada258d24355ace0260e36/6bdcf/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-0.png 315w,
/static/80ebadc46dada258d24355ace0260e36/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-0.png 630w,
/static/80ebadc46dada258d24355ace0260e36/40601/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-0.png 945w,
/static/80ebadc46dada258d24355ace0260e36/b12f7/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-0.png 1020w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Now, let’s see the code&lt;/h3&gt;
&lt;p&gt;as you notice, the first thing you do is calling the LVN. When your lvn receive a call, the &lt;code class=&quot;language-text&quot;&gt;voiceAnswer&lt;/code&gt; callback is executed. This is a simple express middelware that should return a json response. This json response should be a valid &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.nexmo.com/voice/voice-api/ncco-reference&quot; title=&quot;ncco&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;ncco&lt;/a&gt;. An ncco is a set of instruction you use to program your call. It exist because is much easier using the ncco than using the api and manage all the details. &lt;br&gt;
In this ncco, what you are telling to the server is just to connect the caller (your phone) to a to a websocket url that We are gonna expose in this same function&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a1d1f6c1fd07f662926e8bb452844adc/c2d9c/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 73.41772151898735%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZklEQVR42pVS13LDIBDUf9i0o4kiEG6yYyd5yf9/Uw6VyDPJ2PEOugHB3l5rpM99yedzKSVo20qXbeh86tuYjAvWB2VaEIJSyn6hAWVMPvrTjYGmhNARjM1Pl+PfaIy1rsv+eOtOV6X0llQHs49naLg0JmSFC2MGmHTqDTohT5w000NgtHiTXOuNHrLP3nIhmZDPlBlHLQXwNew+93nXRWQGq7nUwrgl6xoQ/SnBqrxASSk4l2NhOR45E5RsthVkXPNm+saMVjI6FoJf+piCP+fwdtx/XIfL0HcpQiy2KzHvjO+wf8mZaHWt9n3pUfmUwiG6EpxrXXTtMYeCXY/x0OehZKWtAFAgJIiVzCfLee/t+x61Xe/baFRqLV7RqX2kYrJTH1ZlZAJI/MmrJwqi5o+WPWrVCMBIpJpnikxtvpN4QAYAzgXZbgj552gtZJz70MUYPfgkQNJX+E2dEK2UkjgVmPhLyt9dc3bRINMYBgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;lesson 5 make a phone call to your laptop with vonage api 1&quot;
        title=&quot;&quot;
        src=&quot;/static/a1d1f6c1fd07f662926e8bb452844adc/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png&quot;
        srcset=&quot;/static/a1d1f6c1fd07f662926e8bb452844adc/c26ae/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png 158w,
/static/a1d1f6c1fd07f662926e8bb452844adc/6bdcf/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png 315w,
/static/a1d1f6c1fd07f662926e8bb452844adc/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png 630w,
/static/a1d1f6c1fd07f662926e8bb452844adc/40601/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png 945w,
/static/a1d1f6c1fd07f662926e8bb452844adc/78612/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png 1260w,
/static/a1d1f6c1fd07f662926e8bb452844adc/c2d9c/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-1.png 1326w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;your function is expoing this websocket url. look the handler &lt;code class=&quot;language-text&quot;&gt;route&lt;/code&gt; , this is executed at your example startup, and his giving you and &lt;a class=&quot;siteLink&quot; href=&quot;https://expressjs.com/en/4x/api.html#app&quot; title=&quot;express app&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;express app&lt;/a&gt; you can use to add any handler you want.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5e3a0908e2d15f9f87fb75e35b269248/97bfd/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 81.0126582278481%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAACCElEQVR42nVTB47cMAy8f6yLCqliNVty3ytILkEC5P//Ce1dIJvD3YCQYZsjDUfkk0AjbDJWDb1TKP1QjAtgnOqCRK1sJ6S8VFVNqKrqcmke8MQZa9uWK9dIw2zibhA2IvAYjO20RRkNeq2cAhdSyBNjrP5HJrYEPVwh9DhPcpyFT96Z9/dt2UoJboxeIUjWAqLuXNs09YmDLDhvGWegGGoGoJBrBUIIkEJyjoJLOosSmWgFNIxz+iclAJDeQzZoq5c3HF+6/X25rts2znPetrKWtI9H5OgEWvRZmqiss51LMdKeJJsjotSOSSXiVNteAPTJlRz63jmvcw62syS2qStSfAvC/WQBGKclJecVjBZoJROUDdon1UUuVHs36Hy27YPb/CwDlAqDHWbjIz88ZPSRS0krldk+EP6/qjP1ti13vdp/Qhea09IzoW6+xp187F1XLRoeCjf+09T6KzKtAKhjDutLWl+U6aiZzq464/Coao96209Pbrpp99fv81qeX9d9ylPvtsHPg19LKLFbcpp76jz4aNhNdpnLuo/LGF/3vE5pWfP+vC1r2fcyDjYNidqr/tjbdzJDe9zt2z7++bG/brlM+dvvX3kqVAtPa4OWRsU439T1JzVbYwAkKqAJO8KgNWC0lMpwGwRqakRQ5iNZSumcu10YDV9FE3igvsX5uNxeCI+y/wKxrYvfF4V5XgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;lesson 5 make a phone call to your laptop with vonage api 2&quot;
        title=&quot;&quot;
        src=&quot;/static/5e3a0908e2d15f9f87fb75e35b269248/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-2.png&quot;
        srcset=&quot;/static/5e3a0908e2d15f9f87fb75e35b269248/c26ae/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-2.png 158w,
/static/5e3a0908e2d15f9f87fb75e35b269248/6bdcf/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-2.png 315w,
/static/5e3a0908e2d15f9f87fb75e35b269248/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-2.png 630w,
/static/5e3a0908e2d15f9f87fb75e35b269248/40601/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-2.png 945w,
/static/5e3a0908e2d15f9f87fb75e35b269248/97bfd/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-2.png 1078w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;the instruction &lt;code class=&quot;language-text&quot;&gt;const speaker = getSpeakerStream()&lt;/code&gt; , which is executed at the script start up, is accessing it you your speaker.&lt;/p&gt;
&lt;p&gt;in the line &lt;code class=&quot;language-text&quot;&gt;app.ws(&apos;/socket&apos;, …&lt;/code&gt;, I’m adding a websoket handler at the url &lt;code class=&quot;language-text&quot;&gt;/socket&lt;/code&gt; that is supposed to receive a ws stream containing the call audio.&lt;/p&gt;
&lt;p&gt;As you can imagine, the interesting details are hidden in the &lt;code class=&quot;language-text&quot;&gt;getSpeakerStream()&lt;/code&gt; , &lt;code class=&quot;language-text&quot;&gt;startStreamMicAudioIntoWebSocket()&lt;/code&gt; and in the &lt;code class=&quot;language-text&quot;&gt;writeWSMsgintoSpeaker&lt;/code&gt; function. Let’s check them:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;getSpeakerStream()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 610px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d74bac95002dbe30308241bfa192a281/5aae9/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 60.12658227848101%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABvElEQVR42nWRjW6bMBSFeYtpDdj43yYkmEEgQLBJCFG7VVsXTZqmvf977JKfrtO2Y8uW0fl8zzUBVaneDCLbKiXHQz0M9X6ovCvHfdXviqrKvJ+PWimjtV2viUi5XCbGhGEYUJnwtKAmM6v1zndl9aH1bbVra+/yTWltWtV51W2F1nK1XOYZyyzRuqorxllAYhy+f0eEUqVnuYuoRoWnzUkMX7HthBBMGrE5slUufaOnwUyObex+3JvEBISQKIo45xhFGKOiPzTTc+nGjT8mtmCCGqOixQNCEQIfZH1YhIsFRghjHFBKEUJQIY4xE7IAbDgV/Vj6KS1qpWXbN/imGAillJASvcKwSSnjOBZK14enHJp+/LL7eM62vdSq802yNELC/RxqJ/NjGYDB/zY2JMP18VP//C3vhuH8szl9zhoHr/H0Mr38eB4mBwCY0V03mBKarlK3d5wLRAiGHi5NzhPd3Nfo6I3uMKVJmjjntNQ0JlABc4mZnFfKwRddhP5UcE0CPw1u7dZtZ7t2XUu1TB6/J8ezGc/c1ugv7AZbaymj10N0SRjCmFNeP0T/I2eYMfbaCb6t9/33/Df8C+2gcXswSr6CAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;lesson 5 make a phone call to your laptop with vonage api 3&quot;
        title=&quot;&quot;
        src=&quot;/static/d74bac95002dbe30308241bfa192a281/5aae9/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-3.png&quot;
        srcset=&quot;/static/d74bac95002dbe30308241bfa192a281/c26ae/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-3.png 158w,
/static/d74bac95002dbe30308241bfa192a281/6bdcf/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-3.png 315w,
/static/d74bac95002dbe30308241bfa192a281/5aae9/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-3.png 610w&quot;
        sizes=&quot;(max-width: 610px) 100vw, 610px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;that is pretty straightforward, basically we are just getting access to the speaker same way we did in lesson1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;writeWSMsgintoSpeaker()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/98de0180eb426cc9614b516bd794f837/97bfd/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-4.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 137.34177215189874%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAIAAADzvTiPAAAACXBIWXMAAAsTAAALEwEAmpwYAAACvUlEQVR42o1Ui5KjNhD0Z+TWQu/3AyEBBmOv73zJVZL//6GMwbvZymXtG4SQqtSaobulnbBRhtIN9bBM83k5XS91LK+v43EZhqGFVmo0RhkXtAvSWGMMQgivsSMYUy5VyOV8DWV8XZahy94ba03TYISaj4G3/i12hFLSIKFUff0e+6l0yRux36P9ywtu0LaUEILvDd/bBobNfIguRCaEUJowhjCDWqS2XGohNaUU7deMqNl2a97K2cF2VBooe/z2A5L7trTjlA+H7rh0ywID64wwjEsmFBOaM0lhAFMmKICJMTq1rU2dazsFNSSnjaS84YowgWGR8lAUk1ZIywF2GxguFN9h3CiXYp1s28E/+1x9nbX1vhtif0zjEsow9HmeCvR9TeNQpFBb/bd/Nqmrlz/G61/18qOer5fraTlNeTrX01fnAxDDOWXAA2dbDyy8E4Z810+//11PlzrNxzHPQwsUMmWp0Mp6E5JUCpZuzH9QatVZaBP6KfRzLDUPUxs8TNPxW16uqY4uF2stIfjn2N1qQAiY0XkK48JciymFhMpY7Ty4YP/lt3dL/RdM1hBcBp/DfHVtSYezDa0zsj8UsGODP407GGwGj7cx5ZqSM7EVIQsp8MO4g1c8BZMp63JrQTaZqpTyo5MfgRnjxXdBOfCJFBy9fHmM/ACmt8zOOgaKrrL+a//HYPgoqaKNlBAgtoFz8Am9/wcmBHJ1oYtdLwQXPnPryVp0g9CD4u9lr6eUpFTqfIqHc/n6p0u3K2Gce230Z/h3qVaxcBNtSiCyt9pacKhQ8t3Jj8BvnMMBTLmF05VlOWrr8NOyNzDMgw1BOsCAQwhufknnDQw3TPLRSgvHCC4lQshztulbwOLYH7Rz3CZpwlOhdxsf0EMqznmz3pV3CZ6C4dVaw1UO+E1a/Mux88GzmyP5Uyf/DP4HHVngWlXsNBgAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;lesson 5 make a phone call to your laptop with vonage api 4&quot;
        title=&quot;&quot;
        src=&quot;/static/98de0180eb426cc9614b516bd794f837/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-4.png&quot;
        srcset=&quot;/static/98de0180eb426cc9614b516bd794f837/c26ae/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-4.png 158w,
/static/98de0180eb426cc9614b516bd794f837/6bdcf/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-4.png 315w,
/static/98de0180eb426cc9614b516bd794f837/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-4.png 630w,
/static/98de0180eb426cc9614b516bd794f837/40601/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-4.png 945w,
/static/98de0180eb426cc9614b516bd794f837/97bfd/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-4.png 1078w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;A lot more code here.&lt;/p&gt;
&lt;p&gt;We start with something familiar from the lesson2, we are accessing the mic.&lt;/p&gt;
&lt;p&gt;then we got:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; chunker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SizeChunker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
  &lt;span class=&quot;token literal-property property&quot;&gt;chunkSize&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;640&lt;/span&gt;   
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
micInputStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chunker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;this is basically taking the mic audio flow and chunking it in piece of 640 bytes.&lt;/p&gt;
&lt;p&gt;now with &lt;code class=&quot;language-text&quot;&gt;chunker.on(&apos;data&apos;…&lt;/code&gt; we are saying that every time I’ve got ready an audio package from my mic with the size of 640 , you should send this to Vonage via websoket.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;writeWSMsgIntoSpeaker()&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/da1726218fd10efa04b3fbe8ad7fa77d/136a2/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-5.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 37.34177215189873%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA8UlEQVR42p2Oy07DMBBF/SHxTOJ4kiZxnferCSmp1MeiqpDgF1hQWPD/K+yolRBILDgaXY9G4zuX0boQut/X8fWUfDxVny/t27l4Pa6vl+L9kj+PEUnKu7Gej/lmG0RxMx9WiZaRCogYuigFFUrv53Y3VQ+dbvp+mOYyVdIDgQ7nHBDRdY0ggGnAvhbmWpADRJRkOk+yDIU0ZabCF55PnvDtrrEADrfmBvPuBJZVP5+ax0Pedm2TjZuyHKZq2JKUy+2fMDM1PxFQpSpTaaPqOEx0USqljJnjOHgP+Rt7mYiM8iXPopx/y/YHLAxDYw//4gsTRj9tcP+bEwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;lesson 5 make a phone call to your laptop with vonage api 5&quot;
        title=&quot;&quot;
        src=&quot;/static/da1726218fd10efa04b3fbe8ad7fa77d/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-5.png&quot;
        srcset=&quot;/static/da1726218fd10efa04b3fbe8ad7fa77d/c26ae/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-5.png 158w,
/static/da1726218fd10efa04b3fbe8ad7fa77d/6bdcf/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-5.png 315w,
/static/da1726218fd10efa04b3fbe8ad7fa77d/f058b/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-5.png 630w,
/static/da1726218fd10efa04b3fbe8ad7fa77d/136a2/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-5.png 884w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;this also should be simple, we are “writing” every data package we receive from the backend in our speaker, so we can ear the voice coming from the phone. notice we are doing this only if this check pass: &lt;code class=&quot;language-text&quot;&gt;if(isBuffer(msg))&lt;/code&gt; , that’s because audio is not the only thing Vonage is sending you via web socket but that’s the only thing you want to pass to your speaker.&lt;/p&gt;
&lt;h3&gt;That’s all Folks&lt;/h3&gt;
&lt;p&gt;It was long but we did it!&lt;/p&gt;
&lt;p&gt;Let me know if you have any comment, feedback question!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Nodejs audio, lesson 4: apply some audio effects to your voice]]></title><description><![CDATA[As we learned in  and , your mic is a  and your speakers are a , to make them work together you just need to pipe them. But what if we want…]]></description><link>https://casual-programming.com/lesson-4-apply-some-audio-effects-to-your-voice/</link><guid isPermaLink="false">https://casual-programming.com/lesson-4-apply-some-audio-effects-to-your-voice/</guid><pubDate>Wed, 04 Aug 2021 02:33:00 GMT</pubDate><content:encoded>&lt;p&gt;As we learned in &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-1-enter-the-mic-9df64d0c1ad3&quot; title=&quot;lesson 1&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;lesson 1&lt;/a&gt; and &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-e3ad98abf044&quot; title=&quot;lesson 2&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;lesson 2&lt;/a&gt;, your mic is a &lt;a class=&quot;siteLink&quot; href=&quot;https://nodejs.org/api/stream.html#stream_readable_streams&quot; title=&quot;readable stream&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;readable stream&lt;/a&gt; and your speakers are a &lt;a class=&quot;siteLink&quot; href=&quot;https://nodejs.org/api/stream.html#stream_writable_streams&quot; title=&quot;writable stream&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;writable stream&lt;/a&gt;, to make them work together you just need to pipe them.&lt;/p&gt;
&lt;p&gt;But what if we want to apply some audio effects to our voice?&lt;/p&gt;
&lt;p&gt;for this we are gonna put `something` in the between of those 2 streams. this something is gonna be an npm library called &lt;a class=&quot;siteLink&quot; href=&quot;https://www.npmjs.com/package/sox-audio&quot; title=&quot;sox-audio&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;sox-audio&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;let’s install it with&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;npm install &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;s sox&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;audio&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;then let’s create a file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;touch lesson_04__p1_audio_effects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and let’s add this code in it:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8820bd3c9aa43cdf76d5a0e1538a6ee6/84ee5/lesson-4-apply-some-audio-effects-to-your-voice-0.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 184.81012658227846%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAlCAIAAADNzV5SAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEoklEQVR42oVV2XLjNhDUX2Sz5oEb4E0CBAnwEElZPrKVVF5Secn//0eGktdlW95d1BSLkDCYme6e4UHK2JhKG9uYttZtVWvv+mFw4ziYppGCR3EchPuKbtYhjlEcRTFVQk+0sczaXBfeN8OgXVuZEnZZyhmsW/8DxohRgkUiq64eZ3N+1OtZqmSe23Fura6mphiboq+LRKmPzgghSkkUI0QYIhQzGRMRE0YIoRQTguEA5IZRDGFuI2NGKaKc5Vo0vbBTNS9pPzGZUErfHr2t+hoZDoVwSzOsubZudlWdB8EnCP3YmVC7PbnHv2Rp8jKN4/jXzlAb5xwOEsabcWmXh9z0da58XRRK/Dz6AcIKIeCKKAzC4C68+/ryEoaQeRCGv3TmEaY0KWKmcFriBKwACoBfzlkQBD9zlkLEwJLKcjtK7bm7F+4ktKtspzuPEI5+pDBIWEoJKSKMu+3JzKe09bxbxPTM+y3zW+Pnys1p2UAdn0UG5zDElMMhuz7lTUv1oKYn3q/KrXpc+vO3uh+iW2eILAQ4B4C23Z5rf0y0Z3ogpcWF4VWb1qawPimbW5W8Rg4IZd3pD3M8l+5YuUWlCSUovLuDioLL81r4xcJ3zsAWlwpzyVQGRlVKpSKMxZgAlDFlCBPQNkj91UBFB+g18EWglLTGMiOFoZW9PqlQJGsgf9p4VTadrbqubtsSzJiaUnagjEHYEHqGJzEVeGdbAj2YCaRgK7kUIF4YCbeC3dMGKexdlVW5W5rz39V0r4pGdKscj3JaUt0CT5+L5JK23LVNCPBsj/eF6Zj2cnzk3Ym3czNtdn3MGwOwAWhvBfsCGPQ7oGGOD+7hz6SxfA/7KC4iaeetOz3X1sNc4DByKHlNf48MNcNeSRhEPq0aDGOgsjjXKGtE0ajSpI1VSSo5M5mqU/la/AHCZlkaY1Yax5IcZzVvHE0rJWjTZFoXWudpksDR3Wd3i9H3dQC09v8QQSJBXJG0pIUmSQ6/Z3lSlGlRpJfUPll72pAw0MO1V/4kzNC3uR+M1I61M9EjmGwnBGcR+tBbL8PgOt+81+van07+fOqPs82GkxgeoMO4GQDzdj7B4bf+L1RdN32vt83NU6udS9zC+g3YzvrZLA97q5Y1+dz5MnVcX9+f3DS1fnJ6WkS/Srep/lhPJz2uVT8KlYRvBsuVZwEQAuDWd8PU9329rdZ2pq51lhe7MhEGvZJLe0QfIl8Bgx7O53M5rpD2cuzaac6mB9mORCa72gmj/CLyG8Ag7SAOA99Xx2kve127ddalGzkA5s8g0mpYQKRZWX+sOUmS8MI9MLRubjnazveJ37h/4O6U9otZn9z9N5A39NDHxlBKwX1QmfcGwh6P3bK64Thkbkncys2Y2LF2E0yorHo3jL6nHYVxFDZ12rVFWaZ7u+sykyJTEgC7fgD2LzlC7yNzIZWKCQdV49zEqsxzYDRXqYLhlAquOOPQM7oGqOEiKO/VDhxHisbQScptyXhW/TINep1qZ0tJ4pzGAgWCRHnCcPg1vvvy1g5RPWI93ZkN3/9LHv9D2z/58Vwsz0E5/J7a3xL7JbX7i2q/Zt0H+x+B/lsvDgF78wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;lesson 4 apply some audio effects to your voice 0&quot;
        title=&quot;&quot;
        src=&quot;/static/8820bd3c9aa43cdf76d5a0e1538a6ee6/f058b/lesson-4-apply-some-audio-effects-to-your-voice-0.png&quot;
        srcset=&quot;/static/8820bd3c9aa43cdf76d5a0e1538a6ee6/c26ae/lesson-4-apply-some-audio-effects-to-your-voice-0.png 158w,
/static/8820bd3c9aa43cdf76d5a0e1538a6ee6/6bdcf/lesson-4-apply-some-audio-effects-to-your-voice-0.png 315w,
/static/8820bd3c9aa43cdf76d5a0e1538a6ee6/f058b/lesson-4-apply-some-audio-effects-to-your-voice-0.png 630w,
/static/8820bd3c9aa43cdf76d5a0e1538a6ee6/40601/lesson-4-apply-some-audio-effects-to-your-voice-0.png 945w,
/static/8820bd3c9aa43cdf76d5a0e1538a6ee6/84ee5/lesson-4-apply-some-audio-effects-to-your-voice-0.png 1076w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;find the &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_04__p1_audio_effects.js&quot; title=&quot;full code here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;full code here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;now run&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;node lesson_04__p1_audio_effects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and try to talk: you should hear your voice like you are inside of a garage. I suggest you to use an headset during your tests, if you don’t you will add an echo in your voice and you will probably not be able to appreciate reverb effect.&lt;/p&gt;
&lt;h3&gt;Tell me more about audio effects&lt;/h3&gt;
&lt;p&gt;In general, sox-audio is just a wrapper on top of sox, so you can search online how to apply effects, but when you call &lt;code class=&quot;language-text&quot;&gt;addEffect&lt;/code&gt; you are colling the cli command under the hood, so you can take any example of sox usage and apply the same params. here is a good article to start: &lt;a class=&quot;siteLink&quot; href=&quot;https://h3manth.com/2009/01/08/sox-sound-exchange-2&quot; title=&quot;https://h3manth.com/2009/01/08/sox-sound-exchange-2&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://h3manth.com/2009/01/08/sox-sound-exchange-2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;p&gt;check out the lesson 4 part 2 file here: &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_04__p2_multiple_audio_effects.js&quot; title=&quot;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_04__p2_multiple_audio_effects.js&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_04__p2_multiple_audio_effects.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;you can specify a number from 0 to 3, corrisponding to a different effect:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;node lesson_04__p2_multiple_audio_effects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;  
  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Nodejs audio, lesson 3: math and music, baudio for the win]]></title><description><![CDATA[Before you read this, be sure you read the  and  What is audio? in unix everything is a file, even programs and devices. the way those…]]></description><link>https://casual-programming.com/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win/</link><guid isPermaLink="false">https://casual-programming.com/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win/</guid><pubDate>Wed, 04 Aug 2021 00:30:00 GMT</pubDate><content:encoded>&lt;p&gt;Before you read this, be sure you read the &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-1-enter-the-mic-9df64d0c1ad3&quot; title=&quot;lesson 1&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;lesson 1&lt;/a&gt; and &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-e3ad98abf044&quot; title=&quot;lesson 2&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;lesson 2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What is audio? in unix everything is a file, even programs and devices. the way those things comunicate with each other, are strings (or numbers in this case).&lt;/p&gt;
&lt;p&gt;that means basically you can “play” everything. That’s more or less the concept behind the npm package &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/substack/baudio&quot; title=&quot;baudio&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;baudio&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;disclaimer:&lt;/strong&gt; I m gonna beefily cover this topic, so if you don’t understand it, just skim or skip. The porpouse here is just to show you that your microphone or music files are not the only thing you can use to produce audio.&lt;/p&gt;
&lt;p&gt;create a file with&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;touch lesson_03__math_music_baudio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;now put this code in it:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1bd6f6ac5199e96bd3473a281dde3dcb/e2cbf/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 87.9746835443038%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB9UlEQVR42o1T7ZKiMBD0PRTynZlMEiAQcEVPd+uq9v0f6Qbdf6fldgVIher56OnsQoA81LyseT5+HOu6LlOX0LtWiPYddlIK6YKKWVDCgCljAk/gpZTvyZphPQ7LsF4g920rDk3Dq/0FNjIn74/n8bQ6qw77ffs75g/ZQrCpuDxqhzolQ6SEbH4RYmetFVJNt29efrn5y3e+/B3Xq1TqbQkb2VqDMXvKEkhh9jFjHqRUbbuRxWvsvHMGovJkjAkxO0o/f5RivtJG3Gf2nGy4Z4pp7PIQqQwWI8SecnKBjHP8Vkq9GvnOWatpKHX8+lqWpQ+MfhprOa01Ji5HIyI39lQ/7tnoUMZ5ul3r5yfzRx8iEiGCB45snPcc4gXZWa4eICwf4/nP8XxZAhHPb2taSTaB1uruBfmsbOeY3A1lmutyOuYu53Eqc419QXAheCKPAbQ2h0PzWIzHZhsVRyYIzqNoG60Ep1FSGC1YbgZn5hL44bFwF9yCMYqF4s0mmI3FlJOu1zDMfK2m87nUqR4rRe7b5MwKAIBPKcQIiB7R8YYPt8zGBxd7n3tLma1qQtLUq1T4tkmlG74qd+z327qjeXw2tZnArgrgOjDEgQF06HRIbDg+18Y+5Pl/2juelKKByhTGOdWZXdFC1Ehsr2a/f+jzytv/ACHxmJL8kfbRAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;nodejs audio lesson 3 math and music baudio for the win 0&quot;
        title=&quot;&quot;
        src=&quot;/static/1bd6f6ac5199e96bd3473a281dde3dcb/f058b/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png&quot;
        srcset=&quot;/static/1bd6f6ac5199e96bd3473a281dde3dcb/c26ae/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png 158w,
/static/1bd6f6ac5199e96bd3473a281dde3dcb/6bdcf/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png 315w,
/static/1bd6f6ac5199e96bd3473a281dde3dcb/f058b/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png 630w,
/static/1bd6f6ac5199e96bd3473a281dde3dcb/40601/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png 945w,
/static/1bd6f6ac5199e96bd3473a281dde3dcb/78612/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png 1260w,
/static/1bd6f6ac5199e96bd3473a281dde3dcb/e2cbf/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-0.png 2138w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;find the full code &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_03__math_music_baudio.js&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;now just hear your “music” running:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;node lesson_03__math_music_baudio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;you are gonna listen some white noise.&lt;/p&gt;
&lt;p&gt;if you want to hear a different sound, just run&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;node lesson_03__math_music_baudio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;pass a number from 0 to 4 for different noises.&lt;/p&gt;
&lt;h3&gt;What we did?&lt;/h3&gt;
&lt;p&gt;As usual, our speaker is a writable stream. baudio is basically a library that given a a callback is generating a readable stream.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; music &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;baudio&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;musicSelected&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;music&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;speaker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;musicSeleceted in the end is the selected callback to generate the music we want, we use the operator .pipe as usual to play our music in our speakers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some notes about baudio&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;basically doing ”music” with baudio means implement a function that is accepting a t (is a point in time, is a float number that is gonna be bigger at every call) and must return a float number between -1 and 1.&lt;/p&gt;
&lt;p&gt;If you are curious about the topic and you can to compose something more complicated that what I did , checkout this: &lt;a class=&quot;siteLink&quot; href=&quot;https://www.youtube.com/watch?v=2oz_SwhBixs&quot; title=&quot;https://www.youtube.com/watch?v=2oz_SwhBixs&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://www.youtube.com/watch?v=2oz_SwhBixs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;next lesson:&lt;/strong&gt; &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/lesson-4-apply-some-audio-effects-to-your-voice-617d5a1b714e&quot; title=&quot;Lesson 4: Apply some audio effects to your voice&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Lesson 4: Apply some audio effects to your voice&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Nodejs audio, lesson 2: ear your voice from your speakers]]></title><description><![CDATA[In the  we did the setup of our project, and we learned how to acquire audio from our mic and dump it into a file. In this article, we are…]]></description><link>https://casual-programming.com/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win/</link><guid isPermaLink="false">https://casual-programming.com/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win/</guid><pubDate>Tue, 03 Aug 2021 20:24:00 GMT</pubDate><content:encoded>&lt;p&gt;In the &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-1-enter-the-mic-9df64d0c1ad3&quot; title=&quot;previous lesson&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;previous lesson&lt;/a&gt; we did the setup of our project, and we learned how to acquire audio from our mic and dump it into a file.&lt;/p&gt;
&lt;p&gt;In this article, we are gonna use your microphone.&lt;/p&gt;
&lt;p&gt;Let’s start creating a file for this lesson:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;touch lesson_02__speaker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;then lets install an npm packege called&lt;code class=&quot;language-text&quot;&gt;speaker&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;npm install &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;s speaker&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;remember, to make this package work, you neet to be sure you have installed &lt;a class=&quot;siteLink&quot; href=&quot;http://sox.sourceforge.net/&quot; title=&quot;sox&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;sox&lt;/a&gt;. That’s the same tool we have installed in the previous lesson to make the &lt;code class=&quot;language-text&quot;&gt;mic&lt;/code&gt; package work, so if you did the lesson 1, you don’t need to install sox now.&lt;/p&gt;
&lt;p&gt;now inside the &lt;code class=&quot;language-text&quot;&gt;lesson_02_spkeaker.js&lt;/code&gt; add the following code:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ab8f7dc8c745074377980962159b35f4/e4611/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 114.55696202531647%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAAsTAAALEwEAmpwYAAACrUlEQVR42oVUiY6bMBDNX7SbQDC+xjY2YG7IJtnN1Uuq1P//mY5Juqp2k3ZkjQD5ed68eXhhDK0q732Vl77wVdf1bVNLKVKSpkmSkCSKb7H+EAtCCKUpNyWUg6gH5auqKcepHvqqLWxhMyU4pynGHTB+RTDhQCFLDVBvE061ZHXtrNO5gc4ZC5Jzfh/MEC0N0zkBx4qelT11DaUMSa2iCFf0iHYAM4bNCWOL6TWrm+15r50L/RKCO5Jk/ShmMOfRaiWN7Y/f6ueD814pgfXW/4tbZeybg7Z1b5tBmgy0RJ7JP4pewaiElDIwxPY+f1o9fY6WT9FyuZ77TALth7FAJOcMBROuFmXHq0m0O+EHk+m29aD0armMH7SwEELMY0iEttX2qJpRDq9yOkO3d8PWtSOXwASQu3OewQLPRsHq7aHZncAVYjjC5izGU9bvupdLf/oBxn6sH8AYqLZyZfNyyXwni14UbSo1kZqBEahe5lLK1uv3o772zEmS4I5qe6hwVN0mb0ZQMgmiRVgQj75vEgSjmRQAYzSOVkkc3eYTrxEWz+Z6NLNAOziM8pRDwiTRLkkpkiRcpBlQDcjrodo32hwgb4rdxV9+5f0Gn1Fz2L3K8dn6BjKH/O+AAQDxaAyhzPTlZ7c7mbIV00ltv8vhbLp9d/iKakulP+Lf5rzO8hJrFv2GqYxVE68G5ntdda7pi3HHBBo2etf7jTZ+1QpQXTQpCjXLHPL8HNYc8Vu+in8TLBUqBZeanBUtL1qat9zVTALFHF4bk7u2zes6995idi4L3saeOU7JVrLbC1ztTg7HZmjqaSOHgxqPaB6cAhcCN0LQns1c2R8w9pziv6Hx9yBcCryGlKCUBmaBXiA/myW+3inXHGjTcIMRoixDhnlNrbdW53mGh9511d+C/QYbisfW227YgQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;nodejs audio lesson 2 math and music baudio for the win 0&quot;
        title=&quot;&quot;
        src=&quot;/static/ab8f7dc8c745074377980962159b35f4/f058b/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png&quot;
        srcset=&quot;/static/ab8f7dc8c745074377980962159b35f4/c26ae/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png 158w,
/static/ab8f7dc8c745074377980962159b35f4/6bdcf/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png 315w,
/static/ab8f7dc8c745074377980962159b35f4/f058b/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png 630w,
/static/ab8f7dc8c745074377980962159b35f4/40601/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png 945w,
/static/ab8f7dc8c745074377980962159b35f4/78612/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png 1260w,
/static/ab8f7dc8c745074377980962159b35f4/e4611/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-0.png 1298w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;go &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_02__speaker.js&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt; to find the full code&lt;/p&gt;
&lt;p&gt;run the file with the command:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;node lesson_02__speaker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;if you talk now, you will ear back your voice. press &lt;em&gt;ctrl + c&lt;/em&gt; to close the application.&lt;/p&gt;
&lt;h3&gt;What have we done?&lt;/h3&gt;
&lt;p&gt;the mic is initialized as the previous lesson.&lt;/p&gt;
&lt;p&gt;with those line we are gonna initialize the speaker:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; speaker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Speaker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;sampleRate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; audioConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rate&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; audioConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;channels&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;bitDepth&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; audioConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bitDepth  
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;the object `speaker` is now a Writable stream so we can “write” our audio in our speakers with the line:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;micInputStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;speaker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;next lesson:&lt;/strong&gt; &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-3-math-and-music-baudio-for-the-win-a9a8d28ef0a5&quot; title=&quot;Nodejs audio lesson 3: Math and Music, baudio for the win&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Nodejs audio lesson 3: Math and Music, baudio for the win&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Nodejs audio, lesson 1: enter the mic]]></title><description><![CDATA[This is gonna be a series of article teaching your how to use audio with nodejs Click  to go to the final Github repo. In my work at Vonage…]]></description><link>https://casual-programming.com/nodejs-audio-lesson-1-enter-the-mic/</link><guid isPermaLink="false">https://casual-programming.com/nodejs-audio-lesson-1-enter-the-mic/</guid><pubDate>Tue, 03 Aug 2021 20:15:00 GMT</pubDate><content:encoded>&lt;p&gt;This is gonna be a series of article teaching your how to use audio with nodejs&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Click&lt;/strong&gt; &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs_audio_examples&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt; &lt;strong&gt;to go to the final Github repo.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In my work at Vonage I deal with audio a lot. Despite this, I m very far from being an audio expert. I don’t work with the details or even with the media part, so I decided to do some experiment to understand it better. During those experiments, I’ve realized that is something very fun, but not very documented. There are few libraries we are gonna use written by different people that are just managing what is called “raw audio”, when I make them work together, I felt like some kind of magic was happening. In this series of article, I m gonna share with you my experience, I hope you are gonna feel the same joy I felt.&lt;/p&gt;
&lt;h3&gt;Getting started&lt;/h3&gt;
&lt;p&gt;we are gonna need to following tools installed in your laptop&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;sox&lt;/li&gt;
&lt;li&gt;nodejs 14&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Installing sox&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The majority of the npm package we are gonna use rely heavily on &lt;code class=&quot;language-text&quot;&gt;sox&lt;/code&gt; which is a multi-platform cli tool to manage audio (they define it &lt;em&gt;the Swiss Army knife of sound processing programs&lt;/em&gt;). you can download it here: &lt;a class=&quot;siteLink&quot; href=&quot;http://sox.sourceforge.net/&quot; title=&quot;http://sox.sourceforge.net/&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;http://sox.sourceforge.net/&lt;/a&gt; but if you are on mac and you have brew installed, just run &lt;code class=&quot;language-text&quot;&gt;brew install sox&lt;/code&gt; . Once you have installed it, let’s verify the installation is completed (you may need to open another terminal before you do that):&lt;/p&gt;
&lt;p&gt;run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;sox &lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;version&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s what you should see:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bce9ca5fd0a268619a9e5d80ca32b8ce/75a80/nodejs-audio-lesson-1-enter-the-mic-0.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 23.417721518987342%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAbklEQVR42sXKQQrDIBAFUGPGjYgGVEQ0KurK+x+wH0OhpQfoWwzzZz4bY6y15pytNcze+72VUjARU0oxxhBCrTXnfH1g3nuUnqtzzlqrtTbGIGJBVErhS0TsF65CCM65eKPt3J5FSokCysc39jcvSRgKWhnQFiUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;nodejs audio lesson 1 enter the mic 0&quot;
        title=&quot;&quot;
        src=&quot;/static/bce9ca5fd0a268619a9e5d80ca32b8ce/f058b/nodejs-audio-lesson-1-enter-the-mic-0.png&quot;
        srcset=&quot;/static/bce9ca5fd0a268619a9e5d80ca32b8ce/c26ae/nodejs-audio-lesson-1-enter-the-mic-0.png 158w,
/static/bce9ca5fd0a268619a9e5d80ca32b8ce/6bdcf/nodejs-audio-lesson-1-enter-the-mic-0.png 315w,
/static/bce9ca5fd0a268619a9e5d80ca32b8ce/f058b/nodejs-audio-lesson-1-enter-the-mic-0.png 630w,
/static/bce9ca5fd0a268619a9e5d80ca32b8ce/40601/nodejs-audio-lesson-1-enter-the-mic-0.png 945w,
/static/bce9ca5fd0a268619a9e5d80ca32b8ce/75a80/nodejs-audio-lesson-1-enter-the-mic-0.png 1134w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Installing Node.js 14.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can install Node.js in many ways, but if you are on mac, I suggest you to install `nvm` (&lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/nvm-sh/nvm&quot; title=&quot;https://github.com/nvm-sh/nvm&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/nvm-sh/nvm&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;is better if you read how to install nvm in the guide, but If you are on mac and you trust me, and run;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;install nvm&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;curl &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;o&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;https&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;githubusercontent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;nvm&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;sh&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;nvm&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;v0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;38.0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;install&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sh&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;https&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;raw&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;githubusercontent&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;com&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;nvm&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;sh&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;nvm&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;v0&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;38.0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;install&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sh&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; bash&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;open a new terminal and run &lt;code class=&quot;language-text&quot;&gt;nvm -v``. if this is not working be sure you have in your &lt;/code&gt;&lt;del&gt;/.zsrc&lt;code class=&quot;language-text&quot;&gt;or in your&lt;/code&gt;&lt;/del&gt;/.bashrc“the following lines:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NVM_DIR&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;$([ -z &quot;&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;XDG_CONFIG_HOME&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; ] &amp;amp;&amp;amp; printf %s &quot;&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nvm&lt;span class=&quot;token string&quot;&gt;&quot; || printf %s &quot;&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;XDG_CONFIG_HOME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;nvm&lt;span class=&quot;token string&quot;&gt;&quot;)&quot;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;s &lt;span class=&quot;token string&quot;&gt;&quot;$NVM_DIR/nvm.sh&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; \&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;$NVM_DIR/nvm.sh&quot;&lt;/span&gt; # This loads nvm&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;when added, open another shell and it should work.&lt;/p&gt;
&lt;p&gt;2. install node 14&lt;/p&gt;
&lt;p&gt;Once nvm is installed just run&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;nvm install &lt;span class=&quot;token number&quot;&gt;14.15&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;.0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and then &lt;code class=&quot;language-text&quot;&gt;node -v&lt;/code&gt; to confirm you have the right version&lt;/p&gt;
&lt;p&gt;You can probably use any other version of node, but if you want to minimize the risk of having this code not working, I suggest you to use exactly the same node.js version I’ve used.&lt;/p&gt;
&lt;h3&gt;Let’s start coding!&lt;/h3&gt;
&lt;p&gt;we are gonna do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create a new project&lt;/li&gt;
&lt;li&gt;install some dependencies&lt;/li&gt;
&lt;li&gt;access to our laptop mic, record 15 seconds of voice&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;create a new project&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;mkdir nodejs_audio_examples  
cd nodejs_audio_examples&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;npm init&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;respond to all of the questions leaving the default option.&lt;/p&gt;
&lt;p&gt;now let’s install this amazing library to access our mic:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;npm install &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;s mic&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;now let’s create our first file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;touch lesson_01__enter_the_mic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;here is the code we are gonna put there:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/95017681bd7a50748be3cbe0db68a161/d2433/nodejs-audio-lesson-1-enter-the-mic-1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 69.62025316455697%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAABPUlEQVR42pVSW26EMAzkIIQkdmI7S4Dw0qqt2t7/VnVgVW1/WmpZaLCY8dimKWVYlnXd1lImxACAV5JZInHjvPeSOedSMsfQXQhrHYRIRI1zDqXvyyYi3bWw1upTv28AIBBHTuCdFo0xV/ht2zJzo66pn9L9k/b3ftlV5dC9RgbwJKmfN6RkDkvG/N3+QcYQfGSfBuSEkRSLxCRRRX/RUHKduZ5HmfOdhln6DLeESfCWdZG/dFZdRKydneR6rSSgzaUHYuf8lbXVbfMwLa9v47ws05iFOx/0+CrePaY3Jz6yra/fZO2uBwos48vHfV/WnEYhVLJHC+gB1YUCVxMU2CdTJ7mLkqZtL+ONEFIMEcEGcpGRuPID16XWiqjKD7KOTUwq0RpzpjkdKmzbE5/lo/hkW/9RG0WXFCN2/4wvSzxub0r/SxcAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;nodejs audio lesson 1 enter the mic 1&quot;
        title=&quot;&quot;
        src=&quot;/static/95017681bd7a50748be3cbe0db68a161/f058b/nodejs-audio-lesson-1-enter-the-mic-1.png&quot;
        srcset=&quot;/static/95017681bd7a50748be3cbe0db68a161/c26ae/nodejs-audio-lesson-1-enter-the-mic-1.png 158w,
/static/95017681bd7a50748be3cbe0db68a161/6bdcf/nodejs-audio-lesson-1-enter-the-mic-1.png 315w,
/static/95017681bd7a50748be3cbe0db68a161/f058b/nodejs-audio-lesson-1-enter-the-mic-1.png 630w,
/static/95017681bd7a50748be3cbe0db68a161/40601/nodejs-audio-lesson-1-enter-the-mic-1.png 945w,
/static/95017681bd7a50748be3cbe0db68a161/78612/nodejs-audio-lesson-1-enter-the-mic-1.png 1260w,
/static/95017681bd7a50748be3cbe0db68a161/d2433/nodejs-audio-lesson-1-enter-the-mic-1.png 2600w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;find the full code here: &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_01__enter_the_mic.js&quot; title=&quot;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_01__enter_the_mic.js&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;https://github.com/jurgob/nodejs_audio_examples/blob/main/lesson_01__enter_the_mic.js&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Let’s try it&lt;/h3&gt;
&lt;p&gt;if you now run&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;node lesson_01__enter_the_mic&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;the program will run, starting to record for 15 seconds. once the program is done, you will see a file &lt;code class=&quot;language-text&quot;&gt;output.row&lt;/code&gt; that you can play with the command&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;play &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;b &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;e signed &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;c &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;r &lt;span class=&quot;token number&quot;&gt;16000&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;raw&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;here is a screenshot of what you should see after 15 secs:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/8c9eec303817fa774f9fc9c3655f7a7b/52ab5/nodejs-audio-lesson-1-enter-the-mic-2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.26582278481012%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA1klEQVR42pWRWQ6DMAwFE9YSIOw7QnD/S3bAUkUXUfE+ooll59mO6vt+nudlWay1cRxHUfQ4ZIwJw1BYgnJ6nqdeapqmbduu6yjWWjuOQw0ZgPorijGvqmoYBrgsS0CeS9MUf/GEgSAI8jyX+P46lCSJ7/s8xN11XU79pXNQeHemWzHEHDaH3ga70DiO67rS6rZtTKtuCUPG48Scke4VMzA/JP9kDxGhc67nCVkKwc9ifniaJszrupaFA3QBsFg2LGnUs8sfzuQVRUEqzWdZJv4AQeCi7ScxFBGzm2xWTgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;nodejs audio lesson 1 enter the mic 2&quot;
        title=&quot;&quot;
        src=&quot;/static/8c9eec303817fa774f9fc9c3655f7a7b/f058b/nodejs-audio-lesson-1-enter-the-mic-2.png&quot;
        srcset=&quot;/static/8c9eec303817fa774f9fc9c3655f7a7b/c26ae/nodejs-audio-lesson-1-enter-the-mic-2.png 158w,
/static/8c9eec303817fa774f9fc9c3655f7a7b/6bdcf/nodejs-audio-lesson-1-enter-the-mic-2.png 315w,
/static/8c9eec303817fa774f9fc9c3655f7a7b/f058b/nodejs-audio-lesson-1-enter-the-mic-2.png 630w,
/static/8c9eec303817fa774f9fc9c3655f7a7b/40601/nodejs-audio-lesson-1-enter-the-mic-2.png 945w,
/static/8c9eec303817fa774f9fc9c3655f7a7b/78612/nodejs-audio-lesson-1-enter-the-mic-2.png 1260w,
/static/8c9eec303817fa774f9fc9c3655f7a7b/52ab5/nodejs-audio-lesson-1-enter-the-mic-2.png 1420w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So congrats, you have successfully recorded and played your voice!.&lt;/p&gt;
&lt;h3&gt;What’s going on!?!&lt;/h3&gt;
&lt;p&gt;let’s explain some of the code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; audioConfig &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;rate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;16000&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; micInstance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mic&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;rate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; audioConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;rate&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; audioConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;channels&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;token literal-property property&quot;&gt;exitOnSilence&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;  
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;with this code we are instantiating the microphone, we are instructing it to take the audio to a sample rate of 16k and 1 channel. Those params are important, because when you are gonna play the file, you need to play the audio with into the speaker you will need to specify those params and they will need to be exactly the same.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; micInputStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; micInstance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAudioStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fileName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘output&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;raw’  
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; outputFileStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fileName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;micInputStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;outputFileStream&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is an important bit to understand. The audio coming from the microphone is a continuous flow of data. To operate in data flow, Node.js offers you an object called &lt;code class=&quot;language-text&quot;&gt;Stream&lt;/code&gt;. Streams are everywhere in Node.js, you use them when you write/read files, you use then when you send/ receive http requests. But usually, you are using simpler library on top of streams, because it is hard to reason in terms of streams and you don’t always need. &lt;br&gt;
But now the time has come, we can’t avoid using them, let’ see what those streams are.&lt;/p&gt;
&lt;p&gt;here is the stream documentation:&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://nodejs.org/docs/latest-v14.x/api/stream.html&quot; title=&quot;https://nodejs.org/docs/latest-v14.x/api/stream.html&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Stream | Node.js v16.6.1 Documentation_Almost all Node.js applications, no matter how simple, use streams in some manner. The following is an example of using…_nodejs.org&lt;/a&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://nodejs.org/docs/latest-v14.x/api/stream.html&quot; title=&quot;&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;here they are defined in this way: “A stream is an abstract interface for working with streaming data in Node.js. The &lt;code class=&quot;language-text&quot;&gt;stream&lt;/code&gt; module provides an API for implementing the stream interface.”.&lt;/p&gt;
&lt;p&gt;There are several type of stream but we are interested in just 2 types,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Writable Stream: streams to which data can be written&lt;/li&gt;
&lt;li&gt;Readable Stream: streams from which data can be read&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you can imagine, in our example, we are getting a readable stream from the microphone with micInstance.getAudioStream() , we are generating a writable stream for the file output.raw with fs.WriteStream(fileName) and finally, we are “writing” the audio coming from the microphone in the file stream, with micInputStream.pipe(outputFileStream)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;next lesson&lt;/strong&gt;: &lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-2-math-and-music-baudio-for-the-win-e3ad98abf044&quot; title=&quot;nodejs audio lesson 2: Ear your voice from your speakers&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;nodejs audio lesson 2: Ear your voice from your speakers&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Nodejs and Audio]]></title><description><![CDATA[Hello, I m Jurgo and I work as a node.js developer at Vonage. What I do there is this . Sometimes I describe it as “an API for doing your…]]></description><link>https://casual-programming.com/work-with-audio-in-node-js/</link><guid isPermaLink="false">https://casual-programming.com/work-with-audio-in-node-js/</guid><pubDate>Mon, 02 Aug 2021 19:19:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello, I m Jurgo and I work as a node.js developer at Vonage. What I do there is this &lt;a class=&quot;siteLink&quot; href=&quot;https://developer.nexmo.com/conversation/overview&quot; title=&quot;Conversation API&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Conversation API&lt;/a&gt;. Sometimes I describe it as &lt;strong&gt;“an API for doing your own slack”&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Because of this product, sometimes I have to deal with audio. I found that audio is a very scary topic in the beginning, mainly because of the lack of documentation.&lt;/p&gt;
&lt;p&gt;I m far from being an audio expert, but over the years I‘ve managed to make some working code using the few audio-related libraries you can find in NPM, so I’ve decided to share what I’ve learned in this series of articles.&lt;/p&gt;
&lt;p&gt;This is gonna be our journey:&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/nodejs-audio-lesson-1-enter-the-mic-9df64d0c1ad3&quot; title=&quot;Lesson 1: enter the mic&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Lesson 1: enter the mic&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/p/e3ad98abf044/edit&quot; title=&quot;Lesson 2: Ear your voice from your speakers&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Lesson 2: Ear your voice from your speakers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/p/a9a8d28ef0a5&quot; title=&quot;Lesson 3: Math and Music, baudio for the win&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Lesson 3: Math and Music, baudio for the win&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/lesson-4-apply-some-audio-effects-to-your-voice-617d5a1b714e&quot; title=&quot;Lesson 4: Apply some audio effects to your voice&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Lesson 4: Apply some audio effects to your voice&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;siteLink&quot; href=&quot;https://medium.com/@jurgo.boemo/lesson-5-make-a-phone-call-to-your-laptop-with-vonage-api-a5126c2198be&quot; title=&quot;Lesson 5 Make a phone call to your laptop with Vonage API&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;Lesson 5 Make a phone call to your laptop with Vonage API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Click&lt;/strong&gt; &lt;a class=&quot;siteLink&quot; href=&quot;https://github.com/jurgob/nodejs_audio_examples&quot; title=&quot;here&quot; target=&quot;_blank&quot; rel=&quot;noopener nofollow noreferrer&quot;&gt;here&lt;/a&gt; &lt;strong&gt;to go to the final Github repo with all the lessons&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Reduxerit — trying to reduce redux boilerplate]]></title><description><![CDATA[Basically, the idea is to easily create a reducer who expect an action with type [REDUCER_NAME]_SET_STATE. the payload of this action will…]]></description><link>https://casual-programming.com/reduxerit-trying-to-reduce-redux-boilerplate/</link><guid isPermaLink="false">https://casual-programming.com/reduxerit-trying-to-reduce-redux-boilerplate/</guid><pubDate>Sat, 16 Apr 2016 18:13:00 GMT</pubDate><content:encoded>&lt;p&gt;Basically, the idea is to easily create a reducer who expect an action with type [REDUCER_NAME]_SET_STATE. the payload of this action will be a partial state witch will be merged with the old state.&lt;/p&gt;
&lt;p&gt;The idea is trying to reduce the redux boilerplate as much as is possible.&lt;/p&gt;
&lt;p&gt;It’s still possible to enrich the reducer to use the classic approach for some actions.&lt;/p&gt;
&lt;h4&gt;WITHOUT REDUX UTILS:&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;reducers/index.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;actions/index.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;toogleEditorExpanded&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ACT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;LAYOUT_TOOGLE_EDITOR_EXPANDED&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;toogleLayoutDirection&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ACT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;LAYOUT_TOOGLE_DIRECTION&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;WITH UTILS:&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;reducers/index.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; layoutDefState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token literal-property property&quot;&gt;isEditorExpanded&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token literal-property property&quot;&gt;direction&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;horizontal&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; layout &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createBasicReducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;‘&lt;span class=&quot;token constant&quot;&gt;LAYOUT&lt;/span&gt;’&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;layoutDefState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;actions/index.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; createLayoutAction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createUpdateStateAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;‘&lt;span class=&quot;token constant&quot;&gt;LAYOUT&lt;/span&gt;’&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; getLayoutState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getReducerState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;store&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ‘&lt;span class=&quot;token constant&quot;&gt;LAYOUT&lt;/span&gt;’&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;toogleEditorExpanded&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isEditorExpanded &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLayoutState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEditorExpanded&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;updateLayoutState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  isEditorExpanded
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;toogleLayoutDirection&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; direction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getLayoutState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;direction &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vertical&apos;&lt;/span&gt;
   &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;horizontal&apos;&lt;/span&gt;
   &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vertical&apos;&lt;/span&gt;

 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createLayoutAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   direction
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;CONS:&lt;br&gt;
more responsability to the actions (is it a problem?)&lt;/p&gt;
&lt;p&gt;actions payload are bigger&lt;/p&gt;
&lt;p&gt;probably is harder to debug (e.g. in )&lt;/p&gt;
&lt;p&gt;PRO:&lt;/p&gt;
&lt;p&gt;you don’t need a lot of string constant for events name&lt;/p&gt;
&lt;p&gt;every time you add an action, you just modify one file, non need to modify&lt;/p&gt;
&lt;p&gt;the last point it will generate really less code. Imagine if you have to add the events “enable” and “disable” for both the property…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;the utils:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;js&quot;&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createReducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;initialState&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handlers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; initialState&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; handlers&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; action&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; state
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;createBasicReducer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;reducerName &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; initialState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 
 &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; _initialState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  …initialState&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  reducerName
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 
 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createReducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  _initialState&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;reducerName&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;’_SET_STATE’&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   …state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
   …action&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;state
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getReducerState&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;store&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reducerName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; globalState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; store&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stateReducerName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;globalState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; globalState&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reducerName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; reducerName &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; globalState&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;stateReducerName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;createUpdateStateAction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;reducerName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;reducerName&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;’_SET_STATE’&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  state
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item></channel></rss>