<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Florian Klenk</title>
    <description>The latest articles on DEV Community by Florian Klenk (@flodev).</description>
    <link>https://dev.to/flodev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F793375%2Fbfb68e6d-1bf2-478e-becd-f533afc0e414.jpeg</url>
      <title>DEV Community: Florian Klenk</title>
      <link>https://dev.to/flodev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/flodev"/>
    <language>en</language>
    <item>
      <title>Svelte reactive $state recursive classes</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Fri, 21 Mar 2025 14:19:52 +0000</pubDate>
      <link>https://dev.to/flodev/svelte-reactive-state-recursive-classes-3ei6</link>
      <guid>https://dev.to/flodev/svelte-reactive-state-recursive-classes-3ei6</guid>
      <description>&lt;p&gt;In my &lt;a href="https://github.com/flodev/percenty" rel="noopener noreferrer"&gt;new learning project&lt;/a&gt; I have a recursive data structure that looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CategoryType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;percentages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}[];&lt;/span&gt;
    &lt;span class="nl"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CategoryType&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Categories might have an array of more Categories which might have other categories again and so on.&lt;/p&gt;

&lt;p&gt;Now I want to achieve that when I add a new category to the $state that a new category component gets rendered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sns53eg3y3453z9a824.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sns53eg3y3453z9a824.png" alt="Image description" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/flodev/percenty/commit/ceb6904" rel="noopener noreferrer"&gt;This commit does not work&lt;/a&gt; as expected. Svelte detects when I add something to the root categories. If I add a category to a root category the view won't update as you can see:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZCcjWJXxj48"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This is mainly due to the fact that I'm using classes in my state and these classes don't have reactive properties.&lt;br&gt;
After reading &lt;a href="https://joyofcode.xyz/how-to-share-state-in-svelte-5" rel="noopener noreferrer"&gt;this article&lt;/a&gt; which I can highly recommend I know now that I can also use the $state rune within my class.&lt;/p&gt;

&lt;p&gt;All I need to do is to rename the existing file where I defined my category class to &lt;code&gt;category.svelte.ts&lt;/code&gt; so that svelte detects I'm using some svelte magic in that file.&lt;br&gt;
Then I can start defining my properties as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$state&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;percent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$state&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$state&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="nx"&gt;percentages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$state&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PercentageSchemaType&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$state&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Category&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>svelte</category>
      <category>programming</category>
    </item>
    <item>
      <title>Recursive components</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Sat, 08 Mar 2025 21:59:52 +0000</pubDate>
      <link>https://dev.to/flodev/recursive-components-4jp5</link>
      <guid>https://dev.to/flodev/recursive-components-4jp5</guid>
      <description>&lt;p&gt;Given the recursive structure of my project I have to render the Category multiple times calling itself.&lt;br&gt;
Fortunately in svelte that is not a problem.&lt;br&gt;
My component file is called &lt;code&gt;category.svelte&lt;/code&gt; and the only thing I need to do is importing category.svelte from within category.svelte again. I named the component &lt;code&gt;CategoryComponentRecursive&lt;/code&gt; as you can see below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Card&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$lib/components/ui/card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CategoryComponentRecursive&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./category.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Category&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../schemas/category&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Category&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;Card.Root&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Card.Header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Card.Title&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/Card.Title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Card.Header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Card.Content&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#each&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;childCategory&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;CategoryComponentRecursive&lt;/span&gt; &lt;span class="na"&gt;category=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;childCategory&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/each&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Card.Content&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Card.Root&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have a category component which is a shadcn svelte card and this calls itself if child categories where detected.&lt;br&gt;
You can look up the &lt;a href="https://github.com/flodev/percenty/blob/main/src/routes/category/category.svelte" rel="noopener noreferrer"&gt;category component&lt;/a&gt; in the &lt;a href="https://github.com/flodev/percenty" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>webdev</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Zod and Data modelling</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Tue, 25 Feb 2025 20:13:17 +0000</pubDate>
      <link>https://dev.to/flodev/zod-and-data-modelling-1i2e</link>
      <guid>https://dev.to/flodev/zod-and-data-modelling-1i2e</guid>
      <description>&lt;p&gt;My plan is to develop that app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvzw30dwytitmhpiimz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvzw30dwytitmhpiimz1.png" alt="Image description" width="674" height="1322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has a hierarchic data structure.&lt;br&gt;
Zod should validate the data. To model the data in zod we need to create a recursive structure as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseCategorySchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;gte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;percentages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentageSchema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CategoryType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;baseCategorySchema&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CategoryType&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;categorySchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ZodType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CategoryType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;baseCategorySchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;categorySchema&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With z.lazy() I can access the categorySchema even though it's not yet initialised.&lt;/p&gt;

&lt;p&gt;Now I can do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CategorySchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;categorySchema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CategorySchemaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CategorySchema&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CategorySchemaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;risk part&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ETFs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
          &lt;span class="na"&gt;percentages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sustainable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
          &lt;span class="na"&gt;percentages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ETF sustainable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;commondities&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
          &lt;span class="na"&gt;percentages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ETF commodities&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;percentages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;low risk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;percentages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;government bond&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>zod</category>
      <category>svelte</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Svelte Shadcn Forms, Superforms, Formsnap, zod</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Mon, 24 Feb 2025 20:55:15 +0000</pubDate>
      <link>https://dev.to/flodev/svelte-shadcn-forms-superforms-formsnap-zod-3030</link>
      <guid>https://dev.to/flodev/svelte-shadcn-forms-superforms-formsnap-zod-3030</guid>
      <description>&lt;p&gt;I want to start with a simple form. svelte Shadcn has a whole lineup of tools which suppose to work together seamlessly.&lt;br&gt;
After copying the example from the &lt;a href="https://www.shadcn-svelte.com/docs/components/form" rel="noopener noreferrer"&gt;svelte-shadcn page&lt;/a&gt; the form didn't work at first. Mainly my fault. The filenames were not setup properly.&lt;/p&gt;

&lt;h1&gt;
  
  
  Superforms, Formsnap, zod
&lt;/h1&gt;

&lt;p&gt;svelte-shadcn is using formsnap which is using superforms for handling the forms.&lt;br&gt;
zod is being used for validation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Gotcha: +page.server.ts vs +page.ts
&lt;/h1&gt;

&lt;p&gt;There seems to be a difference between those files. I think +page.ts is more SPA and +page.server.ts supports more doing in the backend e.g. backend rendering.&lt;br&gt;
Found this example in &lt;a href="https://superforms.rocks/concepts/spa#using-pagets-instead-of-pageserverts" rel="noopener noreferrer"&gt;superforms docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>webdev</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Diving into svelte</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Thu, 20 Feb 2025 18:30:04 +0000</pubDate>
      <link>https://dev.to/flodev/diving-into-svelte-2b5p</link>
      <guid>https://dev.to/flodev/diving-into-svelte-2b5p</guid>
      <description>&lt;p&gt;Hi there,&lt;/p&gt;

&lt;p&gt;I'm going to learn svelte now and like to invite all interested people to join me on my journey.&lt;br&gt;
Ok lets get started.&lt;br&gt;
At first I discovered that svelte has a nice &lt;a href="https://svelte.dev/tutorial" rel="noopener noreferrer"&gt;interactive tutorial&lt;/a&gt; that lets you do learning by coding.&lt;br&gt;
I want to test svelte on a specific app I thought about recently.&lt;/p&gt;
&lt;h1&gt;
  
  
  The App
&lt;/h1&gt;

&lt;p&gt;So I thought about implementing a simple percentage calculator where I can manage categories and split them up into percentages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mqs9kcr6x53dwfkqxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mqs9kcr6x53dwfkqxr.png" alt="Image description" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The Stack (subject to changes)
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;svelte&lt;/li&gt;
&lt;li&gt;sveltekit&lt;/li&gt;
&lt;li&gt;svelte-shadcn&lt;/li&gt;
&lt;li&gt;tailwind&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I like the concept of shadcn. It's basically a low dependency lib ... no actually its not a lib. It's more a bunch of tailwind components.&lt;br&gt;
Now the special thing about shadcn is that you add each component to your very own source code (instead of adding npm dependency) which gives you full ownership about it. It comes with a slick cli so I just had to execute a few commands.&lt;/p&gt;
&lt;h1&gt;
  
  
  What I did so far
&lt;/h1&gt;

&lt;p&gt;Aside from creating a concept I've basically executed a series of commands.&lt;/p&gt;
&lt;h2&gt;
  
  
  To create the app
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;npx sv create percenty&lt;/code&gt;&lt;br&gt;
(I had to answer a few questions, basically the answers were typescript, playwright, lint and prettier)&lt;/p&gt;
&lt;h2&gt;
  
  
  To add svelte-shadcn and tailwind (not in that order)
&lt;/h2&gt;

&lt;p&gt;This step turned out trickier than expected given my lack of tailwind experience.&lt;br&gt;
First tailwind needs to be added.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx sv add tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far so good. I still had to do some stuff described in the official &lt;a href="https://tailwindcss.com/docs/installation/framework-guides/sveltekit" rel="noopener noreferrer"&gt;svelte tailwind installation guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then I initialised svelte-shadcn with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx shadcn-svelte@latest init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding a shadcn button failed ungracefully because I didn't have a &lt;code&gt;tailwind.config.js&lt;/code&gt;.&lt;br&gt;
I've added a basic config.&lt;/p&gt;

&lt;p&gt;Then again the command for adding a shadcn button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx  shadcn-svelte@latest add button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Github repo
&lt;/h1&gt;

&lt;p&gt;I've created a &lt;a href="https://github.com/flodev/percenty" rel="noopener noreferrer"&gt;github repo&lt;/a&gt; which I'm going to update corresponding to blog posts.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Introducing remotify.place</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Mon, 23 May 2022 09:58:25 +0000</pubDate>
      <link>https://dev.to/flodev/introducing-remotifyplace-22p9</link>
      <guid>https://dev.to/flodev/introducing-remotifyplace-22p9</guid>
      <description>&lt;p&gt;Hi, I think it's time to properly introduce my side project which is open source and can be found on &lt;a href="https://github.com/flodev/remotify" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;br&gt;
I mentioned it in my articles and by now it has reached MVP status and can be tried out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.remotify.place%2Fassets%2Fworking_example.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.remotify.place%2Fassets%2Fworking_example.gif" alt="Image" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation and purpose
&lt;/h2&gt;

&lt;p&gt;Going to the office can be fun. You meet others in person. You can talk. Drink coffee. You can also do lot's of fun stuff.&lt;br&gt;
At least where I was working there was always at least one gaming option available in the office. Most often it was a kicker table (I love it but I suck). Sometimes people had nerv guns and were chasing each other. Another time they had table tennis.&lt;br&gt;
And this is where remotify comes into play.&lt;br&gt;
Remotify is targeted is to catch the fun part of going to an office and provides it virtually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;display a room and people&lt;/li&gt;
&lt;li&gt;let different users join a room using invitation links&lt;/li&gt;
&lt;li&gt;users can walk the room by tapping somewhere&lt;/li&gt;
&lt;li&gt;enable camera and microphone and display the picture as peoples heads&lt;/li&gt;
&lt;li&gt;edit the room and draw walls anywhere&lt;/li&gt;
&lt;li&gt;place desks or toilets somewhere&lt;/li&gt;
&lt;li&gt;use desks&lt;/li&gt;
&lt;li&gt;assign desks to users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It provides a virtual place where you can meet and have fun. It's a mix between a game and an online webRTC conference where you can see each other.&lt;/p&gt;

</description>
      <category>sideprojects</category>
      <category>javascript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Use tilt to provide easy to setup development environments</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Mon, 24 Jan 2022 11:58:18 +0000</pubDate>
      <link>https://dev.to/flodev/use-tilt-to-provide-easy-to-setup-development-environments-4n9d</link>
      <guid>https://dev.to/flodev/use-tilt-to-provide-easy-to-setup-development-environments-4n9d</guid>
      <description>&lt;p&gt;You might know it. You just want to start working on an existing project be it in a company or on github. You just want to do the frontend part. Only the frontend which is usually super easy to setup. Just a quick &lt;code&gt;npm install&lt;/code&gt; and &lt;code&gt;npm start&lt;/code&gt; respectively yarn. But of course you need to run the whole project on your local machine to be independent. &lt;/p&gt;

&lt;h1&gt;
  
  
  Just install a few backend tools quick and easy ... so they said
&lt;/h1&gt;

&lt;p&gt;So you get in touch with the backend folks and they tell you "yeah no problem, suuper easy, you just have to install this and that, then have this config and add this repository URL and install this database and apply that db dump and now it's working. Ah I forgot the message queue. Ah you are using MacOS, let's quickly recompile it and then have these certificates and..." and it goes on and on and on...&lt;br&gt;
I have to say I'm a little frontend biased because of the complexity most backends have... sure frontend also has complexity but it's usually easy to setup.  &lt;/p&gt;

&lt;p&gt;I'd like to show you a tool which set's up kubernetes pods and services fast and also watches your changes during development. The target is to have all your projects run by &lt;a href="//tilt.dev"&gt;tilt&lt;/a&gt; in a container even the frontend.&lt;/p&gt;

&lt;p&gt;This will speed up the setup of new dev environments and fasten the onboarding process for new people.&lt;/p&gt;

&lt;p&gt;There are a few prerequisites to install first.&lt;/p&gt;
&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;install docker (&lt;a href="https://www.docker.com/get-started" rel="noopener noreferrer"&gt;https://www.docker.com/get-started&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;install minikube (&lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;https://minikube.sigs.k8s.io/docs/start/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;install kubctl (&lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/tools/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;install helm chart (&lt;a href="https://helm.sh/docs/intro/install/" rel="noopener noreferrer"&gt;https://helm.sh/docs/intro/install/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;install tilt (&lt;a href="https://docs.tilt.dev" rel="noopener noreferrer"&gt;https://docs.tilt.dev&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For macOS I recommend you use homebrew to install minikube, kubectl, helm and tilt. &lt;/p&gt;
&lt;h1&gt;
  
  
  Create a Tiltfile
&lt;/h1&gt;

&lt;p&gt;In the root of your project you can now create a &lt;code&gt;Tiltfile&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
For remotify I've created the following.&lt;br&gt;
Please note that the &lt;code&gt;Tiltfile&lt;/code&gt; has to have this exact name in order to be detected by tilt.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now let's examine whats going on.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;define the minikube context that has to be used using &lt;code&gt;allow_k8s_contexts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;load helm remote extension&lt;/li&gt;
&lt;li&gt;define a db password&lt;/li&gt;
&lt;li&gt;setup each app&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My project consists of postgresql db, hasura graphql, hasura migration, backend auth and the app frontend.&lt;/p&gt;

&lt;p&gt;All of these projects are setup by almost the same schema. &lt;br&gt;
First load the helm chart. Second define how the projects will be accessed using &lt;code&gt;k8s_resource&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Note how all projects after postgres define &lt;code&gt;resource_deps&lt;/code&gt;. The projects will wait for the defined dependencies until they are up and running.&lt;/p&gt;

&lt;p&gt;For the app project I've set trigger mode to manual which means that it won't automatically update the project when a file change is detected. The frontend just takes too long to build. On my macbook it's 1 minute 30 seconds.&lt;/p&gt;

&lt;h1&gt;
  
  
  Run tilt
&lt;/h1&gt;

&lt;p&gt;Now that you have defined your projects in the Tiltfile you can navigate to the respective directory using the command line and run &lt;code&gt;tilt up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiz2hxjsbkx8y50tchk4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feiz2hxjsbkx8y50tchk4.png" alt="tilt after executing tilt up" width="682" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tilt gives you hints how to proceed. I'm always opening the browser using space since I really like the UI of tilt. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq077ut51d1gw8zmtbgld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq077ut51d1gw8zmtbgld.png" alt="Tilt UI" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By clicking on the project name (for example &lt;code&gt;app&lt;/code&gt;) you can get into a detail view where to console output is shown. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7m061kao0c5c9pgzq7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7m061kao0c5c9pgzq7u.png" alt="tilt detail project view" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To switch back just click on the tilt logo in the upper left corner (took me a while to figure that out ☺️).&lt;/p&gt;

&lt;h1&gt;
  
  
  Fazit
&lt;/h1&gt;

&lt;p&gt;So far I love tilt. The UI is quite cool. It does what it's meant to do. Refreshes the pod after an update is detected.&lt;br&gt;
Only thing is for me that the frontend takes very long to bundle the file but that is only for me because I happen to have large dependencies. &lt;br&gt;
The Tiltfile is easy to write, the docs are quite good. &lt;br&gt;
Check out how everything works and maybe try setting up &lt;a href="https://github.com/flodev/remotify" rel="noopener noreferrer"&gt;remotify&lt;/a&gt; using tilt.&lt;/p&gt;

&lt;p&gt;If one could just setup the infrastructure on AWS using a simple Tiltfile ... that would be too good to be true 😊&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Ways to inject variables into kubernetes deployment configs using hasura</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Fri, 21 Jan 2022 07:54:04 +0000</pubDate>
      <link>https://dev.to/flodev/ways-to-inject-variables-into-kubernetes-deployment-configs-for-hasura-4agd</link>
      <guid>https://dev.to/flodev/ways-to-inject-variables-into-kubernetes-deployment-configs-for-hasura-4agd</guid>
      <description>&lt;p&gt;In this post I want to discuss ways to inject variables into kubernetes deployment condigs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do you need that?
&lt;/h2&gt;

&lt;p&gt;Well it starts with version control. You certanly dont want to have sensitive information like passwords in your repository.&lt;br&gt;
Or consider different system environments like dev, test, stage or prod. Each of them will have slightly different variables and settings.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;I'm going to use the hasura deployment config used for remotify in this example.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;It has a few variables that have to be replaced depending to which environment the pod will be deployed:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$HASURA_GRAPHQL_DATABASE_URL&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$HASURA_GRAPHQL_ADMIN_SECRET&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$HASURA_GRAPHQL_JWT_SECRET&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To have a complete example I also have the service config for hasura but there are no variables to inject here. Nevertheless I'm going to use it later with helm so here it is:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Inject variables using envsubst
&lt;/h2&gt;

&lt;p&gt;The first and certainly easiest way is to create env files next to the deployment config and substitute them with the ones used in the deployment config. The folder structure in my case looks the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fkeia8dnd4pte4mocpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fkeia8dnd4pte4mocpq.png" alt="Image description" width="538" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The .env file contains the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export HASURA_GRAPHQL_JWT_SECRET='{"type":"RS256", "key": "super secret key"}'
export HASURA_GRAPHQL_ADMIN_SECRET="super secret admin secret"
export HASURA_GRAPHQL_DATABASE_URL="postgres://postgres:testpassword@postgresql/remotify"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then I navigate to the &lt;code&gt;hasura&lt;/code&gt; directory using the command line and execute the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;source .env &amp;amp;&amp;amp; envsubst &amp;lt; deployment.yaml | kubectl apply -f -&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;And done.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a helm chart
&lt;/h2&gt;

&lt;p&gt;The next method wasn't quite so obvious to me. I was using helm charts before by executing a simple command e.g. for installing a postgres pod. I've never spend a second thought how it works. Under the hood it's very simple and offers exactly what I needed: Configurable kubernetes templates.&lt;/p&gt;

&lt;p&gt;Let's get back to our example. I do have the kubernetes config for hasura. Now I want to inject the mentioned variables. &lt;/p&gt;

&lt;p&gt;In order to do that with helm chart navigate to a directory where you plan to create the chart on the command line and execute &lt;code&gt;helm create hasura&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwxzn5g8sfzsbh93f4of.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwxzn5g8sfzsbh93f4of.png" alt="command line create hasura command" width="560" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now what the command does is that it creates template files for your deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F894qrvruc9vgazic5xzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F894qrvruc9vgazic5xzu.png" alt="folder overview after creating template files" width="724" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For my example I don't need all of these files. So I'm going to delete all files in the template folder since I have my own configs already:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyc4ecl2nkfyuiowdp14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyc4ecl2nkfyuiowdp14.png" alt="folder overview after cleaning up templates folder" width="308" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next I copy my own hasura configs service.yaml and deployment.yaml into the templates folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvqb81bbl7hg8mg6hrqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvqb81bbl7hg8mg6hrqz.png" alt="Chart folder overview after copying own template files into templates folder" width="324" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I declare the variables that I need to inject in the values.yaml&lt;br&gt;
Here is my example values yaml:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Helm uses mustache templates (I guess 🤥) so I cannot let the variables look like in the gist of the deployment yaml on the top. I have to change the deployment variables to the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HASURA_GRAPHQL_DATABASE_URL&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Values.deployment.databaseUrl&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HASURA_GRAPHQL_ADMIN_SECRET&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Values.deployment.adminSecret&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HASURA_GRAPHQL_ENABLE_CONSOLE&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HASURA_GRAPHQL_JWT_SECRET&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Values.deployment.jwt&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can test the chart using &lt;code&gt;helm install hasura --dry-run --debug ./hasura&lt;/code&gt; and it will output the successfully replaced configs.&lt;br&gt;
With helm you can also utilise the &lt;code&gt;--set&lt;/code&gt; parameter so that you override the values in declared in values.yaml&lt;/p&gt;

&lt;h2&gt;
  
  
  Fazit
&lt;/h2&gt;

&lt;p&gt;Even though the helm chart method takes a lot more space in this article (which is due to the images ☺️) it's not complicated and I really would always prefer the helm approach over the envsubst. Helm is no magic trick and pretty easy once understood.&lt;br&gt;
Do you now other methods for replacing variables and which would you prefer?&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>How to create your project docs using storybook and host it with github pages</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Tue, 18 Jan 2022 15:55:32 +0000</pubDate>
      <link>https://dev.to/flodev/how-to-create-your-project-docs-using-storybook-and-host-it-with-github-pages-3gfi</link>
      <guid>https://dev.to/flodev/how-to-create-your-project-docs-using-storybook-and-host-it-with-github-pages-3gfi</guid>
      <description>&lt;p&gt;I'm a big fan of automatically generated documentation.&lt;br&gt;
Today I want to show you storybook docs. Storybook is great because it let's you develop independently in a sandbox. No dependencies. No more waiting for the backend. Just the code. It is also a good documentation. It can show product managers which components are available for use so that they won't reinvent the wheel for each mockup.&lt;/p&gt;

&lt;p&gt;All the mentioned code can be found in my &lt;a href="https://github.com/flodev/remotify" rel="noopener noreferrer"&gt;remotify repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup storybook
&lt;/h2&gt;

&lt;p&gt;That's easy: execute &lt;code&gt;npx sb init&lt;/code&gt; in the project root.&lt;br&gt;
Additionally I recommend to install storybook essentials (&lt;code&gt;npm i -D @storybook/addon-essentials&lt;/code&gt;) which bundles all relevant addons.&lt;br&gt;
Now you need to navigate to the &lt;code&gt;.storybook/main.js&lt;/code&gt; file and add the essentials addon so that it looks similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/**/*.stories.mdx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/**/*.stories.@(js|jsx|ts|tsx)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addon-essentials&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now execute &lt;code&gt;npm run storybook&lt;/code&gt; and see the results in the browser. You should have a few pre-generated stories already.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure for TypeScript docs
&lt;/h2&gt;

&lt;p&gt;As of version 6 of Storybook zero configuration is needed. &lt;br&gt;
This is the way :)&lt;/p&gt;

&lt;p&gt;The only thing you should taking care of is to declare the component in the default export.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EditToolbar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;decorators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ComponentDecorator&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EditToolbar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- important&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure storybook docs
&lt;/h2&gt;

&lt;p&gt;If you don't have it already in your package.json add the following lines within the "scripts" part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"storybook-docs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"start-storybook --docs --no-manager-cache"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build-storybook-docs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build-storybook --docs -o ./docs"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;storybook-docs&lt;/code&gt; is for development in the browser (similar to &lt;code&gt;npm run storybook&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build-storybook-docs&lt;/code&gt; is for building the docs. For getting github pages to work using this example I defined the output to &lt;code&gt;&amp;lt;project_root&amp;gt;/docs&lt;/code&gt; folder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now start storybook docs with &lt;code&gt;npm run storybook-docs&lt;/code&gt;. The browser should open and you should see some stories.&lt;/p&gt;

&lt;p&gt;Since I already have a few stories in my remotify project it looks this way for me:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgn4k2w5owv68lmthyuxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgn4k2w5owv68lmthyuxx.png" alt="Storybook docs" width="800" height="1015"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now run the second command to build the docs. Then commit the files and push them to github.&lt;/p&gt;

&lt;h2&gt;
  
  
  Activate Github pages
&lt;/h2&gt;

&lt;p&gt;Open your github project in the browser and navigate to Settings -&amp;gt; Pages. There activate github pages and select your main branch and the &lt;code&gt;docs&lt;/code&gt; folder you have previously generated and pushed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafstijbqpcwug48xmp0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafstijbqpcwug48xmp0e.png" alt="github pages" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you should be able to see the docs in your browser. &lt;br&gt;
For remotify you can find the docs &lt;a href="https://flodev.github.io/remotify" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
I've also activated a custom domain right under the branch selection which I've named &lt;a href="http://docs.remotify.place" rel="noopener noreferrer"&gt;docs.remotify.place&lt;/a&gt;.&lt;br&gt;
Happy storybuilding :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>github</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>My personal package bundler odyssey</title>
      <dc:creator>Florian Klenk</dc:creator>
      <pubDate>Fri, 14 Jan 2022 08:56:34 +0000</pubDate>
      <link>https://dev.to/flodev/my-personal-package-manager-odyssey-557e</link>
      <guid>https://dev.to/flodev/my-personal-package-manager-odyssey-557e</guid>
      <description>&lt;h2&gt;
  
  
  From parcel
&lt;/h2&gt;

&lt;p&gt;For my project I used &lt;a href="https://parceljs.org" rel="noopener noreferrer"&gt;parcel bundler&lt;/a&gt; version 1.x from the beginning and was quite happy with it.&lt;br&gt;
Zero configuration was great and I'm a supporter of smaller more innovative projects that do something different than the big players (e.g. trello &amp;gt; jira, pixelmator &amp;gt; photoshop).&lt;/p&gt;
&lt;h2&gt;
  
  
  To rollup
&lt;/h2&gt;

&lt;p&gt;One day I've got an issue that a react file couldn't get loaded because of an svg that was imported. So as usual I want to dig into the manual to solve the problem. Thing was that the manual wasn't there anymore and replaced with parcel v2.&lt;br&gt;
Well ok I thought when they ditch the old version and manual v2 must be stable enough. So I did the switch and discovered that at this time peerDependencies couldn't get resolved.&lt;/p&gt;

&lt;p&gt;Being kind of a burned child with webpack spending to many hours in configuration I still wasn't ready for it. So I switched to rollup and had some nice rollup config.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/flodev/remotify/blob/5355e32b5860cb1594b41d672232a39c8a492ff5/packages/app/rollup.config.js" rel="noopener noreferrer"&gt;original repo file&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not quite zero configuration but I rather read code than configuration options. The build worked. Problem was that it took ages to build :(&lt;/p&gt;

&lt;h2&gt;
  
  
  To webpack
&lt;/h2&gt;

&lt;p&gt;Long story short I've ended up using webpack and it wasn't so worse how I imagined in the first place.&lt;br&gt;
I used create-react-app to setup an empty project. Then I did eject (of course). Afterwards I've copied package.json typescript config and all other relevant config files into my project. It works flawlessly and I had zero configuration (by not looking at it :).&lt;/p&gt;

&lt;p&gt;Checkout &lt;a href="https://github.com/flodev/remotify" rel="noopener noreferrer"&gt;remotify&lt;/a&gt; to see how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fazit
&lt;/h2&gt;

&lt;p&gt;I wouldn't got that far to recommend a solution that works for everything. There are use cases for all bundlers and I still love the zero configuration approach (who doesn't?).&lt;br&gt;
But for my project webpack currently works best.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webpack</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
