<?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: David Herbert💻🚀</title>
    <description>The latest articles on DEV Community by David Herbert💻🚀 (@daveyhert).</description>
    <link>https://dev.to/daveyhert</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%2F455980%2Fb63e9724-a26e-4cc2-99c6-f60b1ef7b2e4.jpg</url>
      <title>DEV Community: David Herbert💻🚀</title>
      <link>https://dev.to/daveyhert</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daveyhert"/>
    <language>en</language>
    <item>
      <title>Figma to React: How Kombai Finally Solved My Frontend Workflow</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Fri, 28 Nov 2025 15:11:06 +0000</pubDate>
      <link>https://dev.to/daveyhert/figma-to-react-how-kombai-finally-solved-my-frontend-workflow-9ol</link>
      <guid>https://dev.to/daveyhert/figma-to-react-how-kombai-finally-solved-my-frontend-workflow-9ol</guid>
      <description>&lt;p&gt;As a frontend developer, much of my job is converting Figma designs into React code—a process that’s both meticulous and repetitive. Every pixel, color, font weight, spacing, and padding has to match the designer’s intent exactly. It can be satisfying when it comes together, but it’s also a huge time sink.&lt;/p&gt;

&lt;p&gt;Naturally, to save time and speed up my workflow, I’ve tried out various tools that promise to automate the conversion from Figma to React. But most of them ended up creating more cleanup work than they saved. Then I tried &lt;strong&gt;Kombai&lt;/strong&gt; — and the difference was immediately clear.&lt;/p&gt;

&lt;p&gt;Unlike most generic code generators I’ve tried, Kombai is the only frontend-specific AI agent I can genuinely vouch for that actually understands frontend development and produces code I’d write myself, not code I need to rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Figma to React tools didn’t work for me&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s be honest, Figma-to-React tools have existed for years, but most can’t handle real-world frontend needs or the realities of production code. After trying most of the popular solutions available, some of the problems I consistently faced with these tools:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hardcoded &amp;lt;div&amp;gt;s everywhere&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This was the most frustrating issue I ran into. When a Figma design is given to these tools, they translate what’s visible literally. If your design shows 10 customer orders, you get code that hardcodes those 10 orders directly into the markup as &amp;lt;div&amp;gt;s.&lt;/p&gt;

&lt;p&gt;What I’d typically get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”orders-table”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”order-row”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”customer-name”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Gabriel Esu&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”order-id”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;#12345&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”price”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;$2,499.99&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”status”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Paid&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”order-row”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”customer-name”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Jane Smith&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”order-id”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;#12346&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”price”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;$29.99&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;”status”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Pending&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  {/* Every single row hardcoded like this... */}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything’s just baked into the component, including details that should typically come from an API, like payment info.&lt;/p&gt;

&lt;p&gt;This is fine for static mockups, but impractical for real production apps that need dynamic data. It also makes it impossible to reuse the component with different data. I’d end up spending hours refactoring everything to separate data from presentation—might as well code it from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bad component structure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;These tools organize components by Figma layer grouping, not logical boundaries or reusability. They just follow whatever layer grouping exists in Figma and generate component structures that don’t always translate well into logical component hierarchies.&lt;/p&gt;

&lt;p&gt;For example, a dashboard grouped in Figma as “&lt;strong&gt;Header&lt;/strong&gt;,” “&lt;strong&gt;Main Content&lt;/strong&gt;,” and “&lt;strong&gt;Sidebar&lt;/strong&gt;” becomes one giant monolithic component mirroring those groups—impossible to reuse or maintain.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Dashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="err"&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="cm"&gt;/* Everything dumped in one component */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="err"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;       &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;png&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;dropdown&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Profile&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Logout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cards&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="err"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="err"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="err"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="err"&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="cm"&gt;/* 50+ lines of table markup */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;pagination&lt;/span&gt;&lt;span class="err"&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;sidebar&lt;/span&gt;&lt;span class="err"&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="cm"&gt;/* Navigation, filters, etc. */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;It’s a nightmare: a 300-line component you can’t reuse or test in isolation. Any change means digging through hundreds of lines of code.&lt;/p&gt;

&lt;p&gt;What’s worse is that it didn’t even extract the most obvious reusable pieces. The stats cards are clearly the same component repeated three times with different data, but instead of creating a &lt;code&gt;&amp;lt;StatsCard /&amp;gt;&lt;/code&gt; component, the tool just copied and pasted the markup three times.&lt;/p&gt;

&lt;p&gt;The result: code that ignores React’s modularity is hard to maintain and impossible to reuse. A proper component tree separates reusable units, not just frame layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Didn’t follow tech stack-specific best practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most Figma-to-React generators are stack-agnostic: they ignore TypeScript types, prop definitions, naming patterns, and linting rules. They don’t know your preferred libraries, folder structure, coding conventions, or how your team handles props and state—so the code always feels generic and disconnected.&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="c1"&gt;// What you get from most tools&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘#&lt;/span&gt;&lt;span class="mi"&gt;0066&lt;/span&gt;&lt;span class="nx"&gt;FF&lt;/span&gt;&lt;span class="err"&gt;’&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// What you actually need&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;secondary&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;danger&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;sm&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;lg&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;onClick&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;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;children&lt;/span&gt; 
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; 
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`btn btn-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; btn-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;Proper TypeScript types and clear prop interfaces matter in real projects. Generic tools skip these entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Limited styling options&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most Figma-to-React code tools supported only a handful of styling options. Typically just CSS Modules and maybe Material-UI. That’s it. Want Tailwind, Styled Components, or Emotion? You’re out of luck. Even when a styling option is “supported,” the implementation is inconsistent. No shared theme, no design tokens, no variants—components are styled differently all over.&lt;/p&gt;

&lt;p&gt;The worst part was that my team already had established styling conventions. We used Tailwind with a custom theme configuration, specific utility patterns, and component variants. These tools ignored all of that, producing generic styles that don’t match our codebase.&lt;/p&gt;

&lt;p&gt;I’d spend hours replacing inline styles, fixing spacing, and restructuring components—work that should have been done automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;No reuse of existing repo components&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;These tools had zero awareness of my existing codebase. When they generated code for a new design, they’d create brand-new components from scratch. Meanwhile, my existing reusable components were sitting right there in the repo, unused.&lt;/p&gt;

&lt;p&gt;This happened with everything: we had a &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; component with variants, size options, and loading states; a custom &lt;code&gt;&amp;lt;Modal /&amp;gt;&lt;/code&gt; component with our company’s specific styling and focus management. But these tools didn’t reuse any of the existing components; they generated new ones with none of these functionalities.&lt;/p&gt;

&lt;p&gt;They weren’t aware of our design system either. We had design tokens for colors, spacing, typography, and shadows. Every component in our repo used these tokens. But the generated code would contain hard-coded values, resulting in massive inconsistencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bad Code Fidelity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;​​Almost every tool had code fidelity issues. The generated layout looked fine in the preview, but the underlying HTML structure made no semantic sense. You’d find nested containers wrapped around single elements for no reason, or siblings that should be grouped placed in different parent divs. The hierarchy often didn’t match the visual structure at all.&lt;/p&gt;

&lt;p&gt;This matters because a poorly structured DOM makes everything harder. Styling becomes a pain, and layouts break at different screen sizes. The biggest culprit was absolute positioning. Most tools default to positioning elements absolutely because it’s the easiest way to match pixel-perfect coordinates from Figma. They grab the x and y values from the design file and translate them directly into CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1440px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;900px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.sidebar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1190px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.main-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1190px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;820px&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;This might match the design at 1440px, but when you resize the window, everything overlaps or breaks because they’re locked to fixed positions. Modern CSS layouting techniques like flexbox and grid exist specifically to solve this problem, yet most tools ignore them completely.&lt;/p&gt;

&lt;p&gt;Typography inconsistencies were another constant headache. A design might specify Inter with a weight of 600 and a size of 16px, but the tool would pick a completely different font family, weight, and size because it couldn’t access the exact one from Figma.&lt;/p&gt;

&lt;p&gt;Colors were no different. The generated code would often be close enough that you might not notice immediately, but wrong on closer inspection. Images also presented their own set of problems; they often used the wrong images, placeholders, or were rendered at the wrong dimensions.&lt;/p&gt;

&lt;p&gt;Even when fidelity was good, code quality would be so poor that you risk breaking fidelity trying to fix it.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;No interactivity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most tools treat Figma designs like screenshots, translating the visuals to static code with no interactivity. A search bar would just be a div with an icon and some placeholder text. No input field. No onChange handler. Nothing is actually functional.&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="c1"&gt;// What gets generated&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SearchBar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Search&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;They don’t understand that a magnifying glass icon next to text is universally recognized as a search field, and can’t infer the role of UI elements from their visual appearance. They just reproduce rectangles, not functionality.&lt;/p&gt;

&lt;p&gt;Dropdowns are worse—the tools would see a button labeled “More Actions,” but the generated code would do nothing—no menu, no options, just a static button that looks interactive but isn’t. I’d end up rebuilding every interactive element myself, making the generated code just a wireframe that requires the same amount of work as coding it from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Friction in saving code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most Figma-to-React tools didn’t work inside my IDE. They ran as Figma plugins or in separate browser windows, which meant a tedious workflow just to get generated code into my project&lt;/p&gt;

&lt;p&gt;First, I’d generate the code, download a zip or copy to clipboard, navigate to the correct directory, create the file, paste, and save. Then I’d fix import issues manually, move any referenced images or icons to the right assets folder, and update all paths. A complex component could take 10-15 minutes to integrate.&lt;/p&gt;

&lt;p&gt;The constant context switching was the worst part. I’d be in my IDE, need a component from a design, switch to the browser, generate code, download it, switch back, navigate the file tree, paste, fix imports, move assets, fix paths, and test. Every new component meant repeating the entire cycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;General-purpose agents help, but&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;General-purpose AI agents like Claude and ChatGPT feel like they should solve these problems. They’re smarter, more flexible, and reason about code in ways Figma-to-code tools can’t. They do work better most of the time, but they still lack understanding of my codebase, so the outcome wasn’t as good as I expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bad Code Fidelity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;General-purpose AI agents avoid the worst offenses. They don’t spam absolute positioning or generate nonsensical div structures like generic Figma-to-React tools. But they still produce code that breaks on resize, with colors slightly off and fonts that don’t match.&lt;/p&gt;

&lt;p&gt;The issue shifts from “terrible structure” to “slightly wrong decisions.” An agent would use flexbox correctly but ignore responsiveness, or hallucinate aspects of the design entirely. It’d add proper semantic HTML but miss the exact border radius or shadow. Colors are close but not pixel-perfect. The layout works for specific viewport sizes.&lt;/p&gt;

&lt;p&gt;It’s less obviously broken, which makes it harder to catch. Everything looks good until you compare side-by-side with the design and notice the heading is 18px instead of 20px, the gap is 16px instead of 24px, and the card shadow is entirely different.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;No interactivity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Same problem. Agents treated Figma files like static screenshots. They could describe what they saw, but couldn’t infer that a magnifying glass icon meant a search input should actually search, or that a down arrow meant a dropdown should expand.&lt;/p&gt;

&lt;p&gt;When you look at a design, you intuitively understand the behavior. A hamburger icon opens a menu. A card with a hover state responds to mouse movement. But AI agents only see pixels and layers, so I still had to add all the interactivity myself or prompt separately outside the scope of the design.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Limited use of existing repo components&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is where AI agents should shine compared to Figma-to-code tools, and they do, but only barely. They have search tools and can find existing components in your codebase. But their understanding is shallow.&lt;/p&gt;

&lt;p&gt;They’d find my &lt;strong&gt;&amp;lt;Button /&amp;gt;&lt;/strong&gt; component and see that it exists with props like variant and size. But they don’t understand when to use it or that every button in the app should use this component.&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="c1"&gt;// My existing Button component&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SaveIcon&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&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;Save&lt;/span&gt; &lt;span class="nx"&gt;Changes&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// What the AI agent generates in the same file&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TrashIcon&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;Delete&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because agents don’t have the same intuition that a human developer builds over time through working in a codebase. A developer who’s worked in a codebase for a few weeks knows “we always use the Button component” or “we have a Card wrapper for everything.” They’ve internalized the patterns.&lt;/p&gt;

&lt;p&gt;AI agents search cold each time, trying to piece together what exists without understanding the intent behind your architecture. They treat each generation as an independent task and never build that cumulative understanding of “how we do things here.”&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Asset handling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is where things get messy, especially with Figma integrations. When using something like the Figma MCP server, the agent can access images from Figma files, but the implementation is problematic. It generates code with image sources pointing to localhost URLs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;”http://localhost:3000/figma-image-xyz.png”&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;”hero”&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works while developing locally with the MCP server running. But the moment I stop the server, push the code, or deploy to production, all images break. I’m left with broken references that need manual replacement.&lt;/p&gt;

&lt;p&gt;Even when images load locally, they often render at the wrong dimensions. The Figma design might show a 16:9 hero image, but the agent generates a fixed width and height, squashing it to 4:3. There’s also no consideration for asset organization. In a real project, icons go in an icons folder, images in public/images, or maybe through a CDN. The agent just dumps URLs inline wherever needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Kombai solved the pain points&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kombai.com/" rel="noopener noreferrer"&gt;Kombai&lt;/a&gt; was one of the last agents I tried, but it turned out to be the best. Unlike general-purpose AI models, Kombai is purpose-built for front-end engineers, and it felt like the first tool that understood what front-end development actually is.&lt;/p&gt;

&lt;p&gt;I first used Kombai while building an e-commerce application, then again for a job-application tracker. Despite the projects being completely different, my experience remained consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Proper data structures, not hardcoded markup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The first thing I noticed was that Kombai didn’t hardcode data into JSX. When I gave it a design with an orders table, it generated proper data structures and mapped over them.&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Paid&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Pending&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Cancelled&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;OrdersTable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="err"&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;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;order&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="err"&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;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="err"&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;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;The component was immediately reusable. I could pass any array of orders, and it would render them. No refactoring needed. The TypeScript interface was already defined, the data was properly typed, and the component expected props instead of having everything baked in.&lt;/p&gt;

&lt;p&gt;This extended to everything: product cards accepted product data, user profiles took user objects, stats dashboards mapped over metrics arrays. Every component was built from the start to handle dynamic data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Component structure that makes sense&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai didn’t just mirror the Figma layer structure. It actually thought about how components should be organized in React.&lt;/p&gt;

&lt;p&gt;For the job application portal, I gave it a waitlist Figma design to implement, instead of one massive component, Kombai broke it into logical, reusable pieces:&lt;/p&gt;

&lt;p&gt;Each component had a single responsibility and could be imported and used anywhere. The structure matched how I’d actually architect it myself, even down to how it implemented the route and separated the route content from regular component elements.&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%2F9odcbxvwrxnsychbaby5.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%2F9odcbxvwrxnsychbaby5.png" alt="Kombai component generated code" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also did the same in my e-commerce project:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createRoute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createRootRoute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Outlet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;tanstack&lt;/span&gt;&lt;span class="sr"&gt;/react-router’&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Group&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;mantine&lt;/span&gt;&lt;span class="sr"&gt;/core’&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Sidebar&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Sidebar&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Sidebar&lt;/span&gt;&lt;span class="err"&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;Header&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="err"&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;OrdersPage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;OrdersPage&lt;/span&gt;&lt;span class="err"&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;OrderDetailsPage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;OrderDetailsPage&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mockRootProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ordersMockData&lt;/span&gt;&lt;span class="err"&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;rootRoute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRootRoute&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="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Group&lt;/span&gt; &lt;span class="nx"&gt;gap&lt;/span&gt;&lt;span class="o"&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;align&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;wrap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;nowrap&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Sidebar&lt;/span&gt; &lt;span class="nx"&gt;teamMembers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mockRootProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;teamMembers&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt; 
          &lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mockRootProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
          &lt;span class="nx"&gt;userAvatar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mockRootProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Outlet&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Box&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Group&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;This is exactly how I would structure it myself. Clean, modular, and easy to understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Proper mock data separation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai created a dedicated file, mockData.ts, that stores all the mock data for the project based on the design’s raw data. It includes details such as mock user profiles, analytics data, payment info, application lists, and stats summaries.&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;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;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Stats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="err"&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;mockUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&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="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Snow&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;avatar&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;snow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;hasNotifications&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;mockStats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;totalApplications&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;totalApplicationsChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;totalInterviews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;totalInterviewsChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;2.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;responseRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;responseRateChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.7&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;mockApplications&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;jobTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="nx"&gt;Designer&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;companyName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Moniepoint&lt;/span&gt; &lt;span class="nx"&gt;MFB&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;companyLogo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jpg&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Remote&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;interviewing&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="na"&gt;T09&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="err"&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;jobTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Senior&lt;/span&gt; &lt;span class="nx"&gt;UX&lt;/span&gt; &lt;span class="nx"&gt;Designer&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;companyName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Moniepoint&lt;/span&gt; &lt;span class="nx"&gt;MFB&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;companyLogo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jpg&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;Remote&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;not_moving_forward&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="na"&gt;T09&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="c1"&gt;//  ...more mock applications&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This meant I could later connect the same UI to a real API by simply replacing the mock file. No UI logic needed to change. This is exactly how production-ready code should be structured.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Tech stack integrity, and follows React best practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai was able to scan my codebase and understand my tech stack, with the added flexibility to edit it or set it up myself.&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%2F750athet511c0dn761pw.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%2F750athet511c0dn761pw.png" alt="Kombai tech stack detection" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It generated proper TypeScript interfaces, followed React conventions, and produced code that looked like it belonged in my project.&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;secondary&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;danger&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;sm&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;lg&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;onClick&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;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;children&lt;/span&gt; 
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; 
      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`btn btn-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; btn-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&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;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Spinner&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;Proper TypeScript types. Sensible prop defaults. Even handling for loading states. This wasn’t generic code that needed cleanup; it was production-ready.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Styling flexibility&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai, let me choose how I want the styles generated. I could use Tailwind, CSS Modules, Styled Components, or even vanilla CSS. More importantly, it respected my existing styling conventions.&lt;/p&gt;

&lt;p&gt;When I selected Tailwind as my styling option, Kombai generated code using my project’s existing utility classes and design tokens:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;CardProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;rounded&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;lg&lt;/span&gt; &lt;span class="nx"&gt;border&lt;/span&gt; &lt;span class="nx"&gt;bg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;bg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;gray&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="nx"&gt;bg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="nx"&gt;shadow&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sm&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;lg&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;semibold&lt;/span&gt; &lt;span class="err"&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;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;mt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sm&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;gray&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="err"&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;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;The colors used are our existing Tailwind theme, and even the spacing values (p-6, mt-2) matched our design system. The component looked consistent with the rest of the codebase without any manual adjustments, which is more than I can say for most of the other Figma-to-React tools I’ve tried in the past.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Actually uses existing components&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This was the game-changer. Kombai understood my codebase and reused existing components instead of recreating them. When I asked it to build a new page or component, it searched my repo, found my &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; component, and used it consistently throughout:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;QuickSettings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Account&lt;/span&gt; &lt;span class="nx"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SaveIcon&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&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;Save&lt;/span&gt; &lt;span class="nx"&gt;Changes&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;secondary&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Cancel&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;danger&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TrashIcon&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&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;Delete&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;Every button used my existing &amp;lt;Button /&amp;gt; component. It recognized that my component handled icons through a prop, so it used that instead of creating inline button elements. It understood the variant system and picked appropriate variants for different actions.&lt;/p&gt;

&lt;p&gt;The same happened with other components. It found my &lt;code&gt;&amp;lt;Modal /&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Input /&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;Select /&amp;gt;&lt;/code&gt; components and used them properly. It felt like working with another developer who knew the codebase, not a tool that was seeing my project for the first time.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Interactivity built-in&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai didn’t treat designs as static screenshots. It inferred behavior from visual cues and added proper interactivity. That search bar I mentioned earlier? Here’s what Kombai generated for a page that had that, along with a date range picker filter:&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%2Ffm0olr27xog6ox1mzskk.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%2Ffm0olr27xog6ox1mzskk.png" alt="Kombai interactivity in components" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The search bar wasn’t just a div with placeholder text. It was a fully functional search component with debouncing, loading states, and proper result handling. Kombai recognized the visual pattern of a search interface and implemented the behavior that pattern implies.&lt;/p&gt;

&lt;p&gt;The &amp;lt;DateRangePicker/&amp;gt; worked the same way, with a fully functional date range picker, click-outside behavior, proper positioning, and keyboard navigation support. The kind of polish that usually requires multiple iterations to get right.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Code fidelity that actually matches&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The generated code matched the design pixel-perfectly. But unlike other tools, it did so using proper CSS techniques.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;DashboardLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;flex&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Sidebar&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;gray&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;flex&lt;/span&gt; &lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;col&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;gray&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;overflow&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;mx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nx"&gt;xl&lt;/span&gt;&lt;span class="err"&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;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;



&lt;p&gt;Flexbox for layout instead of absolute positioning. Proper responsive patterns. The layout worked across all screen sizes. Font weights, sizes, colors, spacing—everything matched the Figma design exactly as I wanted. There were a few instances I had to make a minor tweak or ask it to fix something, but fortunately, it does have the ability to track and autofix issues on its own.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Seamless workflow integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai worked directly in my IDE through its VS Code extension. No context switching, no downloading zip files, no manually fixing import paths.&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%2Fq3usl0wxs9413rkchfks.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%2Fq3usl0wxs9413rkchfks.png" alt="Kombai in VS Code" width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d select a Figma frame, run the Kombai command in VS Code, and the component appeared in my project with all imports already configured. If the component used icons or images, they were automatically saved to the correct directories with the correct paths.&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="c1"&gt;// All imports worked immediately&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/components/ui&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Modal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/components/ui&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Modal&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SearchIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/components/i&lt;/span&gt;&lt;span class="nx"&gt;cons&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useOrders&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/hooks/u&lt;/span&gt;&lt;span class="nx"&gt;seOrders&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component was also created in the right location, following my project’s folder structure. It respected my import aliases. It even used my existing custom hooks when appropriate. There was no friction between generating code and actually using it.&lt;/p&gt;

&lt;p&gt;After finishing the project, I asked Kombai to review the page’s performance and suggest improvements.&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%2Frim6600l1jjpjiyvci9t.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%2Frim6600l1jjpjiyvci9t.png" alt="Kombai performance audit" width="800" height="733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It identified key performance issues and recommended changes that significantly improved speed and responsiveness. The loading time improved by &lt;strong&gt;60%&lt;/strong&gt;, the bundle size dropped by &lt;strong&gt;52%&lt;/strong&gt;, and overall interactivity and rendering performance improved by roughly &lt;strong&gt;70–80%&lt;/strong&gt;. It also suggested additional ways to continue improving the performance of my web app.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How was Kombai able to perform better?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It wasn’t by accident that Kombai worked better than Figma-to-React tools or general-purpose agents. Kombai has implemented domain-level optimizations to fit into React developers’ workflows and generate the best React code from Figma designs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Human-tested RAG&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most AI agents rely on model-generated documentation extracts that miss common pitfalls. Kombai is powered by human-tested RAG, not the usual mix of scraped docs and guesswork most agents rely on. That means its generated code is based on real-world frontend patterns and version-specific best practices that developers have actually validated.&lt;/p&gt;

&lt;p&gt;It supports 30+ frontend libraries with a focus on the React ecosystem, including React 18 and 19, JavaScript and TypeScript, and common React stacks. You can combine React with Next.js and Tailwind, TanStack Router with MUI, or any other combination.&lt;/p&gt;

&lt;p&gt;What impressed me most was the flexibility. If you’re using a library Kombai doesn’t officially support, you can write custom rules for it, and the agent will follow your guidelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Figma interpretation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai doesn’t just read Figma files; it understands them the way a frontend developer would. Real-world Figma files are messy. Designers leave invisible elements, use incorrect grouping, have overlapping nodes, or add unintended fills and shadows. Most tools translate everything literally, including the mistakes.&lt;/p&gt;

&lt;p&gt;Kombai handles this gracefully. It recognizes invisible layers and excludes them, understands when grouping is just for designer organization rather than component structure, and filters out accidental styling properties. This interpretation engine is the next evolution of the Figma-to-code model that became Product Hunt’s top developer tool of 2023, built and refined based on how real teams design and ship products.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understands codebase like a human&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai takes a human-like approach to understanding codebases. It identifies key parameters for writing quality code in a given repository, then extracts necessary information like code files and configurations.&lt;/p&gt;

&lt;p&gt;In a codebase with a custom component library, Kombai understands each reusable component’s function, UI appearance, and required props, much like a developer onboarding to a new project. Its search and indexing tools are optimized for codebases, enabling it to find and reuse relevant code faster and more accurately than general-purpose agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Browser tool for preview, debugging, and performance improvements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kombai includes a browser tool that lets you preview the generated code, debug issues, and identify performance problems. You can see how your components render, check network requests, and spot layout issues before even opening your IDE.&lt;/p&gt;

&lt;p&gt;This is useful for various use cases. UI fixes, network errors, component refactoring, and performance improvements. You get a full development environment right inside Kombai.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For years, I tried to make Figma-to-React tools work. I wanted automation to handle the repetitive parts of frontend development so I could focus on interesting problems. But every tool created more work than it saved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kombai.com/" rel="noopener noreferrer"&gt;Kombai&lt;/a&gt; was different. It didn’t just convert designs to code; it understood what I was building and how I wanted to build it. It generated components I could actually use, worked with my existing codebase, and handled tedious parts while respecting my architecture decisions.&lt;/p&gt;

&lt;p&gt;The result is a tool that actually speeds up my workflow. I’m not spending hours refactoring generated code or manually adding interactivity. I’m building features faster, with fewer bugs, and with code that fits seamlessly into my project. That’s what I wanted from Figma-to-code automation all along.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>figma</category>
    </item>
    <item>
      <title>Enthusiast: The Open-Source Toolkit for Building RAG-Powered AI Agents for E-Commerce Workflows</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Wed, 29 Oct 2025 14:02:22 +0000</pubDate>
      <link>https://dev.to/daveyhert/enthusiast-the-open-source-toolkit-for-building-rag-powered-ai-agents-for-e-commerce-workflows-3o96</link>
      <guid>https://dev.to/daveyhert/enthusiast-the-open-source-toolkit-for-building-rag-powered-ai-agents-for-e-commerce-workflows-3o96</guid>
      <description>&lt;p&gt;When people talk about AI in e-commerce, the conversation often starts and ends with chatbots. Even then, these chatbots are usually built on shaky foundations: they deliver answers that feel generic, break whenever a prompt is worded differently, or fail outright if the underlying data isn’t structured correctly. &lt;/p&gt;

&lt;p&gt;The cracks only widen when your catalog involves complex product descriptions or categorizations, and a simple change to your catalog can often break these chatbots and internal training decks. Yet most retail problems go far beyond answering a few customer questions. &lt;/p&gt;

&lt;p&gt;Modern e-commerce teams juggle many moving parts: growing product catalogs, marketing campaigns, customer inquiries, and product knowledge scattered across tools, spreadsheets, PDFs, and support docs. The promise of AI in e-commerce isn’t just about automating responses; it’s about making your entire product data pipeline smarter with a RAG‑based agentic AI solution that speaks &lt;em&gt;your&lt;/em&gt; product language. That’s where &lt;strong&gt;Enthusiast&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Enthusiast?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://upsidelab.io/tools/enthusiast" rel="noopener noreferrer"&gt;Enthusiast&lt;/a&gt; is an open-source, production-ready agentic AI framework with pre-built agents and workflows designed to solve everyday challenges in e-commerce — built by UpsideLab. It leverages the power of retrieval-augmented generation (RAG) and large language models (LLMs) to create a self-hosted unified knowledge platform that supercharges your e-commerce operations and speaks your product’s language to both customers and team members. &lt;/p&gt;

&lt;p&gt;In simpler words, it connects to the systems your e-commerce business already uses, such as product databases, documentation repositories, and customer communication platforms, then turns this scattered data into a unified, searchable interface. Teams can then build and customize AI agents to not only automate tasks such as customer support, product search, marketing content creation, and internal knowledge management, but also empower developers, marketers, and support teams with an AI “teammate” that can search, reason, and respond instantly and factually.&lt;/p&gt;

&lt;p&gt;Unlike many SaaS products, Enthusiast is self-hostable and open-source. You can deploy it on your own servers or in the cloud and choose between proprietary models, such as OpenAI, or self-hosted models through Mistral or Ollama. The framework is built on familiar technologies: Python, Django, PostgreSQL, and React, allowing teams to easily extend it. And because it is open‑source, you have complete control over model prompts, agent workflows, and data, with no vendor lock‑in or hidden usage costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a RAG‑based AI Agent Matters in E-Commerce?
&lt;/h2&gt;

&lt;p&gt;Traditional chatbots often sound generic because they draw from a limited set of prompts and employ fuzzy keyword matching. In contrast, Enthusiast utilizes a Retrieval-Augmented Generation (RAG) engine at its core, which builds a &lt;strong&gt;vectorized index&lt;/strong&gt; of your content to perform contextual search and extract information relevant to a query. &lt;/p&gt;

&lt;p&gt;When a user asks a question, the agent retrieves relevant documents from your product catalog or knowledge base and feeds them into a language model, grounding the response in factual data rather than generic model knowledge. Enthusiast also includes layered evaluation and optional LLM‑based validation to reduce hallucinations and surface data inconsistencies.&lt;/p&gt;

&lt;p&gt;Simply put, using RAG, Enthusiast splits the problem into two steps: first, it fetches relevant facts from your own data sources to retrieve the proper context in real-time, and then crafts a response using the language model based on that context to generate accurate, human-like answers or recommendations. This approach addresses common pain points, such as inconsistent support answers, time-consuming content workflows, and sales teams lacking quick access to product data.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Enthusiast Tackles Real E-Commerce Problems
&lt;/h2&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%2Ffirkhzlanwcgtiwe33lk.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%2Ffirkhzlanwcgtiwe33lk.png" alt=" " width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enthusiast isn’t a monolithic AI product; the framework ships with plug-and-play agents tailored for common e-commerce workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customer Support
&lt;/h3&gt;

&lt;p&gt;The customer‑support agent connects directly to your product catalog and documentation to answer shopper enquiries. It retrieves precise answers from both structured and unstructured documentation, reducing ticket queues and improving first‑contact resolution. It also features an API layer that enables integration with helpdesk or CRM tools, allowing you and your team to deploy AI-powered support on the channels already in use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Marketing Content
&lt;/h3&gt;

&lt;p&gt;Marketing teams can use Enthusiast’s content‑generation agent to produce ads, newsletters, blog posts, and product descriptions. The agent is grounded in your product data and existing assets, mimicking your brand’s tone and style. And because Enthusiast runs locally or on your own servers, sensitive product data never leaves your infrastructure. The framework also supports multiple languages, making it easy to tailor campaigns for different regions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Knowledge Management and Search
&lt;/h3&gt;

&lt;p&gt;Teams often lose time digging through scattered docs and half-remembered links. Enthusiast brings that information together into a single, searchable hub where people can ask questions in plain language and get accurate answers. Enthusiast achieves this by ingesting existing data and integrating with your knowledge sources, such as manuals, PDFs, markdown files, Confluence, Notion, etc., and transforming them into a centralized, searchable knowledge-sharing portal.&lt;/p&gt;

&lt;p&gt;This allows teams to query complex, cross-functional information and get accurate answers to product-related questions in natural language. Responses are also evaluated through layered feedback combining user input, automated scoring, and optional LLM validation to ensure accuracy. And because it is self-hosted, sensitive data remains behind your firewall.&lt;/p&gt;

&lt;h3&gt;
  
  
  Product Recommendations
&lt;/h3&gt;

&lt;p&gt;Keyword searches and rigid filters often miss the subtleties of what shoppers are really looking for. Enthusiast approaches your catalog more like a teammate, able to field open-ended questions and still land on the right products. Ask, &lt;em&gt;“What’s a good waterproof jacket for spring hiking?”&lt;/em&gt; and it pulls the best matches straight from your catalog. You decide how the prompts are framed and how the workflow connects to your taxonomy, brand voice, or recommendation style.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Verification
&lt;/h3&gt;

&lt;p&gt;Before product descriptions or reviews go live, you want to have confidence that they align with your catalog data and house policies. Enthusiast can double-check that content for accuracy and consistency, saving your team from tedious manual reviews. Enthusiast’s content validation agent helps teams compare descriptions, reviews, and marketing copy against your product catalog and docs, flagging inconsistencies or areas that need improvement. The validation prompts and rules are fully customizable and can even be run automatically or on demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion - Is Enthusiast right for you?
&lt;/h2&gt;

&lt;p&gt;Enthusiast shows that AI in e-commerce doesn’t have to end with generic chatbots or an expensive SaaS subscription black box. Whether your team is exploring practical and flexible AI-powered solutions to optimize internal operations, improve customer experiences, or is frustrated by the limitations of closed SaaS solutions, Enthusiast is the right toolkit to innovate your e-commerce stack. &lt;/p&gt;

&lt;p&gt;Out of the box, it offers ready-made agents for common e-commerce problems, while still allowing you to shape the prompts, retrieval logic, and deployment environment to fit your specific needs. The payoff is practical: an accurate knowledge base assistant for team members, fewer repetitive support requests, a consistent brand voice across content, and a shopping experience that feels intuitive for customers.&lt;/p&gt;

&lt;p&gt;And the best part? Enthusiast is open source and built on a standard web stack, which keeps you free from vendor lock-in and API limits. You can start with OpenAI for simplicity, then grow into hosting your own Llama or Mistral model as your needs evolve. Ready to see what an open, flexible e-commerce agentic AI framework can do for your team? Try &lt;a href="https://upsidelab.io/tools/enthusiast" rel="noopener noreferrer"&gt;Enthusiast&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>rag</category>
      <category>ecommerce</category>
    </item>
    <item>
      <title>How Recast AI Improves Your Daily Reading Lifestyle and Boosts Productivity</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Fri, 20 Oct 2023 08:57:35 +0000</pubDate>
      <link>https://dev.to/daveyhert/how-recast-ai-improves-your-daily-reading-lifestyle-and-boosts-productivity-4no6</link>
      <guid>https://dev.to/daveyhert/how-recast-ai-improves-your-daily-reading-lifestyle-and-boosts-productivity-4no6</guid>
      <description>&lt;p&gt;As developers and tech enthusiasts, allocating time for self-improvement and keeping up with our myriad of interesting reads is often a wishful aspiration. Whether it's news articles, productivity hacks, blog posts on learning a skill, or keeping up with your favorite newsletters, finding the time to sit down and read through lengthy articles can be challenging, especially when juggling a busy schedule in a constantly moving world.&lt;/p&gt;

&lt;p&gt;Wouldn't it be cool if you could listen to these articles like podcasts? So I recently came across an app called "Recast AI," which is supposed to summarize articles into podcasts, offering a modern solution to traditional reading and transforming your reading routine into an engaging auditory experience, saving you time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly is Recast?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://LetsRecast.ai" rel="noopener noreferrer"&gt;LetsRecast.ai&lt;/a&gt;, or simply Recast, is an AI-powered app designed to take the articles you're keen on reading and brew them into short, lively podcast-style audio summaries, morphing a potentially time-consuming read into a brief, engaging listen. This is particularly handy for those bustling days when sitting down with a lengthy article is a far-off dream.&lt;/p&gt;

&lt;p&gt;Whether jogging in the park, driving to work, or tidying up at home, Recast ensures your thirst for knowledge remains quenched. It's like having a personal narrator who succinctly unfolds the essence of all your "want-to-read" articles to you, allowing you to soak in the knowledge without anchoring yourself to a text. This way, your reading list becomes a playlist, bridging the textual world with the auditory, making consuming your articles online more flexible and enjoyable.&lt;/p&gt;

&lt;p&gt;Recast is an ingenious way to enrich your reading experience and boost productivity, as it saves you time and helps you adapt to your bustling lifestyle. It's not just about saving time; it's about redefining how you interact with your reading list, turning the solitary act of reading into an interactive auditory session.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does Recast Sound Like?
&lt;/h2&gt;

&lt;p&gt;Unlike typical robotic text-to-speech voices, Recast employs a conversational tone, making it easier to grasp the key points of articles in a more meaningful and enjoyable way. There's just something about the chatty nature of these podcasts that makes them more appealing than traditional audio summaries.&lt;/p&gt;

&lt;p&gt;Think of a podcast series featuring two charming and smart hosts who read any topic you like and then discuss it in rich, beautiful voices. That's precisely how Recast sounds, and the voices are brought to life by Recast's powerful AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Recast?
&lt;/h2&gt;

&lt;p&gt;Recast promises to improve your life based on the following key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Saves you reading time&lt;/strong&gt;: Recast acts as your personal news summarizer, delivering the crux of articles in a nutshell. Imagine the time you'd save when, instead of sifting through lengthy paragraphs, you get the core message delivered to your ears. This is especially beneficial in a world where time is of the essence, and staying updated is crucial.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduces screen time&lt;/strong&gt;: In today's digital age, screen time has become synonymous with eye strain. Recast offers a refreshing break from the constant screen time by summarizing articles into podcasts. Now, mundane tasks like doing the dishes, commuting, or exercising become opportunities to catch up on the latest news or articles, all without having to stare at a screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gain Deeper Insight:&lt;/strong&gt; Recast's conversational tone is a game-changer. It's not just a robotic summary but an engaging narrative that explains the content to you in a way that enhances comprehension and retention of key information. This subtle shift from mere summarization to explanation is like having a knowledgeable friend explaining articles to you in a simple, digestible manner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discover interesting reads&lt;/strong&gt;: The platform isn't just a solitary experience but a community where you can see what others have recast, helping you discover intriguing stories or important news you might have missed. It's a modern way to expand your horizons and stay informed about diverse topics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear off your reading backlog&lt;/strong&gt;: If you have multiple tabs open with articles you plan to read "someday," Recast is your go-to solution. It helps declutter your life by converting those open tabs and backlogs rotting in your inboxes and read-later newsletters into delightful podcast summaries. Now, your reading list becomes a listening list, making it more manageable and less daunting to get through.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Available across platforms:&lt;/strong&gt; Recast is available as an iOS app, a feature-packed web app, and a Chrome extension for submitting articles.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Recast (How Does it Work)?
&lt;/h2&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%2F2t3mjzps9yc0nb4509ay.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%2F2t3mjzps9yc0nb4509ay.png" alt="How to Recast" width="651" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recasting is straightforward. You can recast things yourself or explore the countless great recasts made by others. Create a free Recast account at &lt;a href="http://letsrecast.ai" rel="noopener noreferrer"&gt;letsrecast.ai&lt;/a&gt; and download the app or install the Chrome browser add-on extension.&lt;/p&gt;

&lt;p&gt;Select any article you're curious about on the web (but have yet to read due to time constraints), or open a new tab and browse an interesting article. Click on the recast Chrome extension. Click on "recast it", and it'll do its little recasting magic, and in minutes, your Recast will be ready! Your unique recast conversation will pop up in both your app and inbox. It's truly hassle-free.&lt;/p&gt;

&lt;p&gt;The experience is even more convenient in the mobile app, where you can use the in-browser feature in the Recast app to surf the web for an article or share any article you're reading in other apps directly to the Recast app using your phone's in-app sharing capability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In conclusion, Recast seems to be a modern-day boon for those seeking to balance a busy life with the thirst for knowledge. It essentially molds itself around your lifestyle, ensuring that your quest for knowledge doesn't fall by the wayside amidst daily chores and responsibilities.&lt;/p&gt;

&lt;p&gt;Recast is especially great for those who prefer auditory learning or those with hectic schedules, allowing you to absorb crucial content without investing much time. By leveraging the power of AI technology, Recast transforms your traditional reading habit into a more convenient, engaging, and effective podcast learning experience.&lt;/p&gt;

</description>
      <category>letsrecast</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Implement and use Feature Flags in a Svelte Application</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Tue, 10 Jan 2023 17:49:10 +0000</pubDate>
      <link>https://dev.to/daveyhert/how-to-implement-and-use-feature-flags-in-a-svelte-application-bh1</link>
      <guid>https://dev.to/daveyhert/how-to-implement-and-use-feature-flags-in-a-svelte-application-bh1</guid>
      <description>&lt;p&gt;When deploying code, one of the best ways to ensure it's high quality, meets user or business requirements, and works as it should is by feature flagging it. Feature flags are a great way to control the release of new code or features in your software, as feature flags make it possible to test new code on specific users or a group of users before releasing them to everyone.&lt;/p&gt;

&lt;p&gt;Feature flagging allows you and your team to easily experiment with new features or make changes to existing ones without deploying a new software version. Furthermore, feature flags make it possible for you and your team to seamlessly execute trunk-based development by facilitating continuous deployments and ensuring code integration reliability.&lt;/p&gt;

&lt;p&gt;This guide will cover how we can use feature flags to introduce new features in a Svelte application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Svelte?
&lt;/h2&gt;

&lt;p&gt;Svelte is a JavaScript compiler and a frontend development tool similar to popular JavaScript frameworks like React, Angular, Vue, etc., for building small pieces or whole interfaces of single-page web applications. However, unlike these traditional frameworks, Svelte offers a refreshing outlook on building user interfaces by taking on a different and somewhat innovative approach to creating fast, slick, and reactive user interfaces.&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%2Ffg8ktwr8zh4ybig28kwg.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%2Ffg8ktwr8zh4ybig28kwg.png" alt="Cover Image" width="748" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In contrast to traditional frameworks, Svelte is a unique framework that compiles all its work when you build your application rather than doing it in the browser. As a result, it doesn't rely on a virtual DOM to update the DOM. Instead, it compiles your components into highly efficient JavaScript code that can surgically update the actual DOM whenever the application's state changes. Svelte converts your code into optimized JavaScript at build time instead of interpreting it at runtime. In other words, you won't pay the performance cost associated with traditional JavaScript framework abstractions, as no extra scripts or libraries are shipped to production.&lt;/p&gt;

&lt;p&gt;What makes Svelte even more awesome is that you can also use it to compile your favorite framework, as it has support for most of the popular frontend frameworks, making it ideal for JavaScript developers looking to get lighter builds from their favorite frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Advantages/Disadvantages of Svelte?
&lt;/h2&gt;

&lt;p&gt;When it comes to using Svelte, there are both benefits and drawbacks. On the plus side, Svelte is known for being fast and lightweight, allowing developers to quickly build fast web applications that are both lightweight and responsive. Additionally, the code compiled by Svelte is typically highly optimized and easy to read, making it easier to debug and work with compared to the layered abstractions in traditional frameworks. In addition, Svelte applications are typically smaller than those built with other frameworks in file size, further enhancing performance.&lt;/p&gt;

&lt;p&gt;However, one disadvantage to using Svelte is that it is a very new technology. As a result, there is less community support and fewer resources accessible compared to popular frameworks like Vue and React. Furthermore, because it is so lightweight, it may not be the ideal choice for more complicated projects as it might not be as flexible compared to other production-tested frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, these are technologies you should be familiar with and have installed on your local machine to be able to follow along this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTML&amp;amp; CSS knowledge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JavaScript knowledge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt; knowledge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; v8+ installed&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About Our Sample Svelte Application
&lt;/h2&gt;

&lt;p&gt;For our sample application, we will create a simple feature in a sample Svelte application that displays a random fact about cats each time a user visits or reloads the page. However, we will wrap this feature with a feature flag, so users can only see it when the feature flag is toggled on. Otherwise, we render a display message informing users of its unavailability when toggled off.&lt;/p&gt;

&lt;p&gt;If you want to follow along, you can find the source code on &lt;a href="https://github.com/configcat-labs/feature-flags-in-svelte-sample" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. To keep things straightforward, we will use ConfigCat's feature flag management service to control our feature from a remote dashboard. So, let’s get right to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Sample Svelte Application
&lt;/h3&gt;

&lt;p&gt;Let's start by quickly scaffolding a Svelte app using the create vite command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest myapp &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; svelte
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prompts us to choose our Svelte development environment or choose between the JavaScript and the various supported frontend frameworks we wish to work with. Afterwards, we run the install command to install all our dependency packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we can start our dev environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have a working Svelte demo 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%2Fdipy1tq49i9mwmcovdwa.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%2Fdipy1tq49i9mwmcovdwa.png" alt="Demo Svelte App" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Our Random Cat Fact Feature
&lt;/h2&gt;

&lt;p&gt;To keep things simple and straightforward, we’ll make use of a free &lt;a href="https://catfact.ninja/fact" rel="noopener noreferrer"&gt;Cat Fact API&lt;/a&gt; that returns an object containing a random fact about cats each time a call is made to it. We’ll simply render the returned fact in our markup.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&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="s2"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Fact object&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch data once the component mounts&lt;/span&gt;
  &lt;span class="nf"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://catfact.ninja/fact`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Random&lt;/span&gt; &lt;span class="nx"&gt;Fact&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="nx"&gt;Cats&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;Show&lt;/span&gt; &lt;span class="nx"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="nx"&gt;rem&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;lt;&lt;/span&gt;&lt;span class="sr"&gt;/style&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, our app is ready to be feature flagged.&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%2Fp2x8mz1bdbla1u8j4vln.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%2Fp2x8mz1bdbla1u8j4vln.png" alt="Random Cat Fact" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Feature Flag using ConfigCat
&lt;/h2&gt;

&lt;p&gt;As stated earlier, we will use Configcat's feature flagging service to toggle our feature on/off. So, sign into the &lt;a href="https://app.configcat.com/" rel="noopener noreferrer"&gt;ConfigCat Dashboard&lt;/a&gt; and create a new feature flag. Don't have an account? Quickly &lt;a href="https://app.configcat.com/signup" rel="noopener noreferrer"&gt;sign up&lt;/a&gt; for a free account.&lt;/p&gt;

&lt;p&gt;To create the new feature flag on ConfigCat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Log into the dashboard and navigate to the appropriate config.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can add a feature flag by clicking the 'Add feature flag' option and entering the necessary information.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Ftyjzr59iaeqj1jxcwbak.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%2Ftyjzr59iaeqj1jxcwbak.png" alt="Add Feature Flag" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For our Svelte app to be able to connect to our feature flag, we will need to copy the ConfigCat SDK Key.&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%2F2hf1qy2lyxifpmbophib.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%2F2hf1qy2lyxifpmbophib.png" alt="Copy SDK Key" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Connect our Svelte Application to ConfigCat?
&lt;/h2&gt;

&lt;p&gt;Now that we have created the feature flag, it’s time to integrate it with our Svelte application. Fortunately, ConfigCat provides a number of open-source client SDKs to facilitate seamless integration with their feature flagging services. For this guide, we’ll use the &lt;a href="https://configcat.com/docs/sdk-reference/js/" rel="noopener noreferrer"&gt;JavaScript SDK&lt;/a&gt; package.&lt;/p&gt;

&lt;p&gt;Installing the JavaScript client SDK is as simple as running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i configcat-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now import it into our app and initialize it using the provided SDK key associated with our ConfigCat Dashboard.&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&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;configcat&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;configcat-js&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onMount&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="s2"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Fact object&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&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;let&lt;/span&gt; &lt;span class="nx"&gt;featureFlag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch data once the component mounts&lt;/span&gt;
  &lt;span class="nf"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://catfact.ninja/fact`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Connect to ConfigCat client&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configCatClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configcat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fK7ZCApWbkaDu14njPKZQw/s9XWupU5K0KRp_9PvkU02g&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get feature flags value&lt;/span&gt;
    &lt;span class="nx"&gt;featureFlag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;configCatClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getValueAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;randomfactflag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&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;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Random&lt;/span&gt; &lt;span class="nx"&gt;Fact&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="nx"&gt;Cats&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;Show&lt;/span&gt; &lt;span class="nx"&gt;fact&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;flag&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;toggled&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;featureFlag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/if&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;Show&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;flag&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;toggled&lt;/span&gt; &lt;span class="nx"&gt;off&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;featureFlag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Ops&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;feature&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;currently&lt;/span&gt; &lt;span class="nx"&gt;unavailable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/if&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="nx"&gt;rem&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;lt;&lt;/span&gt;&lt;span class="sr"&gt;/style&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we toggle on the feature flag?&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%2Ffaj32362v49db8r8l4ga.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%2Ffaj32362v49db8r8l4ga.png" alt="Toggle On Feature Flag" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The feature is made available to our users.&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%2F6wqlfyb7xlfkvb079a1l.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%2F6wqlfyb7xlfkvb079a1l.png" alt="Feature Available" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, when the feature flag is toggled off?&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%2Ftwoqelafz9wb07kakpnc.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%2Ftwoqelafz9wb07kakpnc.png" alt="Toggle Off Feature Flag" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The feature is no longer available to users.&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%2Fkw7o4kvevcnwyec5wva0.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%2Fkw7o4kvevcnwyec5wva0.png" alt="Feature Unavailable" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source Code:&lt;/strong&gt; &lt;a href="https://github.com/configcat-labs/feature-flags-in-svelte-sample/" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you have seen, integrating feature flags into your Svelte app using &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; is pretty straightforward. With feature flags, you can clear up any questions when introducing changes to your application without affecting users' experience.&lt;/p&gt;

&lt;p&gt;Getting started with ConfigCat is easy thanks to its intuitive dashboard, easy-to-use SDKs, and well-organized docs. Visit this page to see other supported SDKs. Follow ConfigCat on &lt;a href="https://twitter.com/configcat" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/configcat/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/configcat" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to learn more about feature flagging and its associated benefits.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>svelte</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Short-lived or Long-lived Flags? Explaining Feature Flag lifespans</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Tue, 12 Jul 2022 21:52:32 +0000</pubDate>
      <link>https://dev.to/daveyhert/short-lived-or-long-lived-flags-explaining-feature-flag-lifespans-3l8l</link>
      <guid>https://dev.to/daveyhert/short-lived-or-long-lived-flags-explaining-feature-flag-lifespans-3l8l</guid>
      <description>&lt;p&gt;Feature flags (aka. feature toggles) are becoming increasingly relevant in software development as they provide the ability to toggle features on or off in production, perform a gradual rollout of features and enable A/B testing experiments.&lt;/p&gt;

&lt;p&gt;However, an often overlooked part of this feature flagging technique is that it introduces complexity and has inherent risks when said complexity isn't properly managed. As you're using more and more feature flags within your organization, it's important to understand that some of these flags are meant to last only for a short period and should, therefore, be removed from your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Flags Life Cycle (Longevity)
&lt;/h2&gt;

&lt;p&gt;Feature flag longevity, as the name suggests, has to do with the lifecycle of a feature flag and how long it should remain in the codebase. Since feature flags split your code paths into two or more paths, having too many feature flags for a long time can create additional complexity in your system and an overabundance of them can easily lead to cognitive overload.&lt;/p&gt;

&lt;p&gt;In addition, as with everything, when left unmanaged, feature flags can result in technical debt due to the presence of stale flags that no longer serve a purpose in your codebase. Having these stale flags can be a recipe for disaster as they can accidentally be toggled on. Thus, it is recommended that feature flags are kept as short-lived as possible and their number as low as only needed.&lt;/p&gt;

&lt;p&gt;For these reasons, it is, therefore, necessary to evaluate the purpose of a feature flag to determine its lifespan depending on its use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short-Term vs Long-Term Feature Flags
&lt;/h2&gt;

&lt;p&gt;The first step when considering a new feature flag or keeping your flags organized is to identify whether a flag is going to be a short-term or permanent feature flag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Short-Term Feature Flags
&lt;/h3&gt;

&lt;p&gt;A short-term or temporary flag has a limited lifespan and is often used for release management such as dark launching a new feature, performing experiments, canary rollouts, and tests. When you label a flag as short-term, you can then keep track of it for removal in the future. Once the flag has served its purpose, the application configuration and code are immediately cleaned up, and the flag removed since it no longer has a use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long-Term Feature Flags
&lt;/h3&gt;

&lt;p&gt;A permanent or long-term flag, on the other hand, provides certain control for an extended period, even after a feature is released. The flag might exist for as long as the feature does and is often used for things such as paywalls or entitlements, customizations, load shedding, or accessibility.&lt;br&gt;
Flags that are long-lived easily become part of your regular software operations, so you create them intending to keep them around indefinitely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different Types of Feature Flags and their Various Life Span
&lt;/h2&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%2Fu1s3phnannmv3nk5xh3u.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%2Fu1s3phnannmv3nk5xh3u.png" alt="Types of Feature Flags" width="800" height="405"&gt;&lt;/a&gt;&lt;br&gt;
There are different types of Feature Flags, and they are categorized according to their life span and use case:&lt;/p&gt;

&lt;h3&gt;
  
  
  Release toggles
&lt;/h3&gt;

&lt;p&gt;Release Toggles are usually short-term flags used to slowly expose new features to users and also make it possible to keep certain functionalities hidden from some or all users while iterating on them. These types of Feature Flags make it possible for teams to continuously integrate new features into production without having to worry about the associated risks of continuous deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ops toggles
&lt;/h3&gt;

&lt;p&gt;Ops or Operations toggles usually serve as “circuit breakers” to protect the system when integrating it with new features or functionalities to accommodate for potential issues. Ops flags are also short-term flags that are often used to determine the impact of a new microservice or infrastructure component on a system by monitoring it for possible unexpected errors such as CPU spikes or memory leaks. The ops flag can then be used to disable the new component for further troubleshooting if things don't go as planned.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment toggles
&lt;/h3&gt;

&lt;p&gt;Experiment toggles are short-term feature flags that are used for performing tests and experiments in a bid to collect data from real live users in production, such as carrying out A/B testing to decide between two or more implementation ideas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permission toggle
&lt;/h3&gt;

&lt;p&gt;Permission toggles are usually flags that are used to customize the product experience of your users. This is done by limiting certain features to only a subset of users based on user entitlement or privileges such as subscription level or authentication status. We may, for instance, have a set of "premium" features that are available only to subscribers or paying customers. Unlike other toggles, permission toggles are usually long-term.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dangers of Technical Debt and the Importance of Retiring Flags
&lt;/h2&gt;

&lt;p&gt;Technical debt is a debt a company will have to pay later in the future for choosing a simpler, faster, but less reliable option today. And like all forms of debt, technical debt accumulates interest if not handled properly. This compromise can lead to a substantial amount of work and potential costs in the future.&lt;/p&gt;

&lt;p&gt;As the popular saying states, "With great power comes great responsibility". One argument against using feature flags is that they contribute to technical debt. This is an understandable argument since you can quickly end up with several unused feature flags if you don't pay attention to your flags and conduct regular cleanups or reviews. In the absence of a removal plan, they will become obsolete and add technical debt and complexity. Having these stale flags in your application can adversely affect its reliability and increase development costs down the line.&lt;/p&gt;

&lt;p&gt;Eventually, this technical debt accumulates and stays in your application for years and nobody is sure what a flag does. These flags can become tangles of conditional logic in your code which becomes challenging to manage in the future as your team will end up having to waste actual development time dealing with potential issues that might arise from stale flags.&lt;/p&gt;

&lt;p&gt;It is therefore necessary to retire unused flags to avoid the technical debt associated with stale flags. Adopting a third-party feature flag management system such as &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; can be sensible since the platform has built-in solutions such as tracking of stale flags and scheduled reports on your flags usage. This makes it easy to eliminate the technical debt associated with having stale flags in your source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Feature flagging is a very useful technique to have in your deployment toolbox for continuous integration and feature delivery in our application. Feature flags allow companies to ship more frequently, minimize risk, increase productivity, and even target users and perform A/B tests to determine which features are more popular with these users.&lt;/p&gt;

&lt;p&gt;However, like so many techniques in software development, it also requires proper management and organization to avoid falling into technical debt as a result of misuse or mismanagement.&lt;/p&gt;

&lt;p&gt;Having too many stale or long-lived flags adds complexity that accumulates into technical debt. Hence, the lifecycle of feature flags should be understood and properly managed by teams for the best results. Cleaning up stale flags and keeping the number of feature flags modest and as short-lived as possible becomes key in maintaining a sane and healthy codebase.&lt;/p&gt;

&lt;p&gt;Be sure to check out &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat's&lt;/a&gt; Feature Management service to discover how you can mitigate the frustrations of managing all your feature flags and you can also follow ConfigCat for more on &lt;a href="https://www.linkedin.com/company/configcat/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Eliminating Traditional Feature Release Anxieties</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Tue, 21 Jun 2022 10:14:16 +0000</pubDate>
      <link>https://dev.to/daveyhert/eliminating-traditional-feature-release-anxieties-3gil</link>
      <guid>https://dev.to/daveyhert/eliminating-traditional-feature-release-anxieties-3gil</guid>
      <description>&lt;p&gt;As developers, we spend countless hours building new features and having them pass through rigorous QA tests. However, despite experience and all preparations made, there's always that dreaded feeling you get in the pit of your stomach when you know it's time for deployment. What if something goes wrong in production and your feature doesn't function as expected?&lt;/p&gt;

&lt;p&gt;As software engineers, we are constantly faced with a variety of challenges. These challenges range from developing innovative features based on constantly changing requirements, to deploying these features to production and releasing them to users with the hopes that they work as intended.&lt;/p&gt;

&lt;p&gt;Anyone that has been actively involved in software development is familiar with the stress and anxiety that is caused by deployment and feature release. There's always the constant worry over whether things will go smoothly as planned when these changes are pushed to users.&lt;/p&gt;

&lt;p&gt;That’s why the most important investment a team can make in a company is helping engineers overcome this constant fear of failure associated with feature releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Anxiety and Pain of Traditional Big Bang Feature Releases
&lt;/h2&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%2F7bt7dthvfxf5smbztavv.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%2F7bt7dthvfxf5smbztavv.png" alt="Traditional Big Bang Feature Releases" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the past, deployments were done using what's known as a big-bang approach, where all features are released in one go. This results in a single major release with lots of changes and feature releases bundled into it, which is problematic in at least two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Bundling up lots of changes and new features into one big bang release makes the release more complicated. The complexity of such a release opens up a lot of possibilities for release failure since things could go wrong in a lot of ways. As a result, most engineers and everyone involved in the process in such organizations or companies don't like release day due to the risks and anxiety that come along with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secondly, another problem with this big bang release approach is that most organizations are typically structured to have a fixed release schedule that is infrequent, such as one in every 3 months or thereabouts. This makes delivering changes, fixes, and new feature updates to customers slower, which results in users of the service not being able to access new features or improvements quickly enough. This could negatively impact the user experience of the service.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, traditional big bang feature releases are much slower and riskier because there is a lot more at stake with each deployment if things don't go as planned, which causes greater anxiety and fear of failure for anyone involved in the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separating Code Deployment from Feature Releases with Feature Flags
&lt;/h2&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%2Fh29z33skisovtbt17mx3.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%2Fh29z33skisovtbt17mx3.png" alt="Separating Code Deployment from Feature Releases with Feature Flags" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Releasing feature updates comes with many risks, so it would be prudent to try to minimize these risks by separating deployments from feature releases. This approach allows for a safer and more flexible release strategy, as it is typically safer to make these release changes incrementally.&lt;/p&gt;

&lt;p&gt;This incremental strategy means that the risks associated with traditional deployments and feature releases are minimal and better managed. Also, priority features can get delivered as soon as they become available for user consumption.&lt;/p&gt;

&lt;p&gt;However, the question you might have if you are new to the world of modern DevOps is what is the difference between deployment and feature release as these terms are often used interchangeably.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deployment typically involves moving software changes from one controlled environment to another, usually from a development environment to a live or production environment. The fact that these changes are in the user's environment does not necessarily mean they are available to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feature releases describe the rollout of features and updates to users. In other words, a release gives users access to these new changes and features by making them available to the users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the most effective and easiest ways to separate your deployments from your feature releases is by using feature flags.&lt;/p&gt;

&lt;p&gt;Feature flags determine whether a piece of code or functionality wrapped within it is active or not. Like conditional if/then statements, you can put your updates and features behind a feature flag that hides them after deployment until it’s ready to be released. This means you can continually ship value while avoiding unnecessary risks and anxieties.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benefits of Using Feature Flags
&lt;/h2&gt;

&lt;p&gt;Whenever you are releasing new features and updating your product, it is easier to have a continuous delivery pipeline which allows you to push these updates incrementally as quickly as possible while also safeguarding your customers in the event that any unexpected issue arises. You should be able to roll these updates back out of production as quickly as possible to avoid negatively impacting users.&lt;/p&gt;

&lt;p&gt;With feature flags, it is possible to create a continuous delivery pipeline that allows for both feature addition and risk reduction. Feature flags allow deployments of features to be decoupled from their releases. As a result, you can easily roll out new features without releasing them immediately to the public and easily roll back these features if the need arises.&lt;/p&gt;

&lt;p&gt;Fortunately, there are several feature flag management services such as &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; that offer feature flags as a service. A good feature flag configuration management service comes equipped with key feature flag functionalities and tools to help you and your team leverage the power of feature flags such as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User Segmentation&lt;/strong&gt;: Feature flags can be used to segment your users into subgroups and to test and release features to them based on attributes assigned to different user segments such as location, geography, gender, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A/B Testing&lt;/strong&gt;: By using Feature Flags, you or your Product/Marketing teams can test alternative ideas on your users before proceeding to final implementation based on the feedback from these tests. By doing this you are able to offer the most satisfying customer experience by pushing only the most performant ideas to your users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Progressive Delivery&lt;/strong&gt;: Feature flags enable you to implement your feature releases gradually to help minimize the negative effects of continuous product iteration. The advantage of releasing in smaller chunks regularly is that it's much easier to observe the effect of each change, and if anything goes wrong, quickly roll back the changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kill Switch for Easy Rollback&lt;/strong&gt;: In the event that your feature release doesn't work correctly in production, the change can be rolled back immediately from production via a kill switch option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Intuitive UI Dashboard&lt;/strong&gt;: Remotely manage all of your feature flags from an intuitive dashboard without having to redeploy code when changes need to be made to the flags' configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SDK Integration&lt;/strong&gt;: Simple SDK for easy integrations with various apps and platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In today's rapidly changing world, if you don't improve, you get worse. The success of a development team ultimately depends on how frequent and successful their releases are. However, traditional deployment comes with a lot of release anxiety from the fact that release day is made into a major event.&lt;/p&gt;

&lt;p&gt;Feature flags play a prominent role in making releases as uneventful as possible by providing key functionalities that give you fine-tune control over the exposure of your feature releases. By using feature flags, you can decouple your feature releases from deployment to create a continuous delivery pipeline that enables you to continuously ship value without risking unnecessary exposure.&lt;/p&gt;

&lt;p&gt;For more information on feature flags and how they help ease deployment-related anxiety, follow ConfigCat on &lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;, &lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.linkedin.com/company/configcat/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>featureflag</category>
      <category>deployment</category>
    </item>
    <item>
      <title>Decoupling Feature Releases from Deployment Using Feature Flags</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Fri, 17 Jun 2022 16:08:41 +0000</pubDate>
      <link>https://dev.to/daveyhert/decoupling-feature-releases-from-deployment-using-feature-flags-3oh5</link>
      <guid>https://dev.to/daveyhert/decoupling-feature-releases-from-deployment-using-feature-flags-3oh5</guid>
      <description>&lt;p&gt;In a traditional software development workflow, whenever there are updates or feature releases to be made, they are typically tied to a single major deployment to production. As a result, the frequency of feature delivery is slower and a lot riskier because there’s a lot more at stake with each deployment if things don't go as planned.&lt;/p&gt;

&lt;p&gt;That is to say that releases should not be tied to deployments but rather, decoupled from them. Due to this reason, in a continuous delivery environment, it is considered best practice to decouple feature releases from deployments as it allows for more incremental releases.&lt;/p&gt;

&lt;p&gt;Hence, understanding the concept of decoupling releases from deployment and how feature flags can make that possible is a key for any team.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Difference Between Deployment and Feature Release
&lt;/h2&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%2Fd1rekn72oga5xcqin6x5.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%2Fd1rekn72oga5xcqin6x5.png" alt="Difference between deployment and feature release" width="800" height="385"&gt;&lt;/a&gt;&lt;br&gt;
We must have a clear understanding of the difference between deployment and feature release before proceeding further because these terms are often used interchangeably but are not the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment:&lt;/strong&gt; When we refer to "deployment" we mean the action of pushing code from a development environment to the production environment or a certain part of our infrastructure. This deployed code could contain one or more updates, features or functionalities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release:&lt;/strong&gt; When we refer to "release" we mean the actual act of enabling or exposing a change, feature, or functionality to our end-users.&lt;/p&gt;

&lt;p&gt;The difference between both is that when a feature is deployed, it does not necessarily mean the end-user now has access to it. No! It simply means the feature has been pushed to the end-users environment (i.e. production environment), whereas, releasing the feature is the action of exposing or turning it on, so it is available and accessible to the end-user.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Concept of Decoupling Feature Release from Deployment
&lt;/h2&gt;

&lt;p&gt;The typical development workflow involves collaborating in teams on any given product or feature where each team member works on a different feature branch. However, when collaborating in parallel it’s often not feasible to wait until every developer has completed their work before making a deployment.&lt;/p&gt;

&lt;p&gt;Sometimes certain features may be ready before others are, or may need testing on users in a live environment so as to gain immediate feedback to aid iteration and modification.&lt;/p&gt;

&lt;p&gt;Ideally, you want to be able to push these features when they are ready for release or live testing into production and expose some users to them. At its core, the reason for decoupling releases from deployment is to be able to deliver new features to users faster while mitigating some deployment risks and without compromising on software quality.&lt;/p&gt;

&lt;p&gt;Decoupling releases from deployment gives you control over when and how a release is made even after deploying to production. Should something go wrong with a release, you only need to "un-release" these changes rather than having to do a full rollback to the previous version or having to hastily build a potentially buggy patch.&lt;/p&gt;

&lt;p&gt;Imagine for a second, that you are the owner or manager of a retail store where thousands of customers shop daily. When your supplier or manufacturer supplies you with a new range of products, and you move them from the warehouse to the store (i.e. deployment).&lt;/p&gt;

&lt;p&gt;You don't just throw everything on the shelves so that people can buy them (i.e. release). You may choose to put only a few on store shelves to test them out and to see how customers interact with them. That is the same as decoupling your releases from deployment to perform a selective release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Feature Flags to Decouple Releases from Deployments
&lt;/h2&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%2Fx5a5ffjstomw1vt60cjj.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%2Fx5a5ffjstomw1vt60cjj.png" alt="illustration of feature flags in action" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feature flags (also called feature toggles) play a key role in continuous delivery, specifically in the concept of decoupling feature releases from deployment as they make it possible to deploy code behind conditional flags, and then only toggling them on/off to expose or hide said code from users as the need arises.&lt;/p&gt;

&lt;p&gt;Feature flags provide several interesting features that facilitate decoupling and testing in production, such as being able to target a specific subset of users or user groups, or a percentage (portion) of your traffic, as well as providing accompanying kill switches for easy rollbacks.&lt;/p&gt;

&lt;p&gt;By feature flagging, you can safely push code to production without immediately exposing it to users, experiment with A/B tests, release by user segmentation, reduce the risk associated with deployment by making incremental updates and be able to turn a resource or feature on/off at will.&lt;/p&gt;

&lt;p&gt;Luckily you don’t need to worry about building or managing your own feature flags as there are companies such as &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; that offer feature flags as a service, making it easy to integrate a feature flag management system into your releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Release with Phased Rollout
&lt;/h2&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%2Fe89ncv97jssh1h1akboi.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%2Fe89ncv97jssh1h1akboi.png" alt="Illustration of phased rollouts" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you release an update or a feature to production, phased rollout enables you to implement your release in stages via user segmentation. Phase rollout lets you break your releases into stages by targeting only a subset or percentage of users at a time. This lets you gradually ramp up the number of users exposed to your release until the release is made available to all of your users.&lt;/p&gt;

&lt;p&gt;You can start by releasing it to the first 1% or 5%, then ramp it up to 10%, 20%, 50%, 75%, and finally 100%. This strategy lets you control the blast radius (limit the scope of potential issues) of a release and makes it possible to test and gain immediate feedback early on from your users. For example, if a release performs poorly or is buggy, it's better if only 5% of users experience this rather than your entire user base.&lt;/p&gt;

&lt;p&gt;Furthermore, staged rollouts are also useful for experimenting with new features, such as doing A/B testing. Instead of pushing out releases to all users simultaneously, you can use controlled, measurable feedback to determine what's working in a phased rollout release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Release with Dark Launch
&lt;/h2&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%2Feu9maviyeklpa5j2usbk.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%2Feu9maviyeklpa5j2usbk.png" alt="illustration of dark launch" width="738" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the name implies, a dark launch is usually not publicized, but rather rolled out stealthily by first releasing to a subset of users before a full release to see how they perform. Usually, users are unaware they are testing out the new feature or functionality; rarely will the new feature be announced or highlighted until it’s ready for full release.&lt;/p&gt;

&lt;p&gt;As a result, development teams can get early feedback from users, test bugs, and even stress test infrastructure performance. This allows for faster, iterative releases, and ensures that application performance is not affected, and the release is well received by users.&lt;/p&gt;

&lt;p&gt;This release method was popularized by major tech companies such as Facebook and Google to test upcoming features by pushing them out to a subset of users before an all-out release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Decoupling Feature Release from Deployment
&lt;/h2&gt;

&lt;p&gt;Decoupling releases from deployments using feature flags has several key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Get Code to Production faster&lt;/strong&gt; - Decoupling your feature releases from your deployment makes it possible to release more frequently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk Mitigation&lt;/strong&gt; - Easily control the blast radius of your releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Targeting&lt;/strong&gt; - Through user segmentation, the visibility of features can be targeted to certain users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A/B Testing&lt;/strong&gt; - Easily run A/B tests of features to see which performs better.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Percentage Rollouts&lt;/strong&gt; - Release features incrementally to your users to gain feedback early on that can be used to improve it further.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trunk Release&lt;/strong&gt; - You can release parts of the code and push them into production even if some features are not yet ready for deployment by keeping them toggled off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kill Switch&lt;/strong&gt; - Quickly roll back a feature when it is performing poorly or is buggy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Branching and Merging&lt;/strong&gt; - Rather than having to keep maintaining separate feature branches for a new feature, you can avoid potential merge conflicts using feature flags to conditionally enable features when they're ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The idea behind decoupling releases from deployment with feature flags is to maintain a fast, continuous integration feedback loop. This makes it possible to rapidly deliver updates to production and test new features without impacting your infrastructure or disrupting your user experience.&lt;/p&gt;

&lt;p&gt;Decoupling your releases from your deployments gives you greater control over your feature releases. As a result, you can push code anywhere and at any time without exposing your users to deployment risks.&lt;/p&gt;

&lt;p&gt;To learn more about using feature flags to decouple releases you can follow ConfigCat on &lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt; and &lt;a href="https://www.linkedin.com/company/configcat/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>deployment</category>
      <category>webdev</category>
      <category>featureflag</category>
    </item>
    <item>
      <title>Feature Flag Rollbacks for Product Managers</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Mon, 09 May 2022 19:58:31 +0000</pubDate>
      <link>https://dev.to/daveyhert/feature-flag-rollbacks-for-product-managers-g34</link>
      <guid>https://dev.to/daveyhert/feature-flag-rollbacks-for-product-managers-g34</guid>
      <description>&lt;p&gt;Product managers are responsible for deciding what products to develop that align with the company's goals and also satisfy the needs of the customers. To be a successful product manager, you have to start by defining what a winning product looks like and iterate over it until it's right. To do so, you have to understand that at its core, a product is broken down into its features and quality of user experience.&lt;/p&gt;

&lt;p&gt;However, when developing these features, even after thoroughly testing them in your development environment for potential bugs and issues that may negatively impact user experience, it may not always be sufficient to ensure a successful release to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Feature Rollback?
&lt;/h2&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%2F0o88e4gj634nxx3apfwy.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%2F0o88e4gj634nxx3apfwy.png" alt="An illustration of a feature rollback" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to feature delivery, things don't always go according to plan. A feature may work perfectly fine when tested in development, but may not function as expected or may receive poor user acceptance when it hits production or gets released to users.&lt;/p&gt;

&lt;p&gt;A feature rollback is a way to quickly undo a feature rollout (release) by reverting the code changes back to the previous state without the feature's release – In other words, it is the action of “un-releasing” or “rolling back” the feature from production back to development and undoing access to it, so users are no longer exposed to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is Feature Rollback Important to Product Managers?
&lt;/h2&gt;

&lt;p&gt;Nowadays, software development is about speed and efficiency when it comes to feature releases, UI improvements, and bug fixes. It is ultimately a product manager's responsibility to manage a product throughout its lifecycle from the stages of developing, testing, deploying, to finally rolling out features to users.&lt;/p&gt;

&lt;p&gt;Feature rollback is critical whenever these changes are pushed into production or a feature is released to users because unexpected behaviors can still occur, which could negatively impact users and even lead to service disruption.&lt;/p&gt;

&lt;p&gt;When issues are detected during a feature release or the feature is not well received, a rollback workflow is needed to immediately safeguard your users and their experience by quickly rolling back the feature while you iterate or figure out the root cause of the problem.&lt;/p&gt;

&lt;p&gt;A feature rollback is therefore essential to product managers in preparation for situations where things don't go as planned because it helps ensure a swift response to detected issues and quick resolution without having to worry about its disruption to production operations which could lead to unexpected costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case Scenarios for Feature Rollback Strategy
&lt;/h2&gt;

&lt;p&gt;There are several case scenarios where having a rollback strategy in your development workflow and release cycle can be the right solution:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Feature Performs Poorly After its Release
&lt;/h3&gt;

&lt;p&gt;Despite the fact that we might like to believe our users are like us, they are not. We might speculate that we understand our users and what they want as customers. However, every decision to develop a feature is at best, a guess and without actual real-world feedback, a likely shot in the dark at what these users want.&lt;/p&gt;

&lt;p&gt;Suppose you develop a new feature based on this assumption, and then, after it is released, you discover that it’s performing poorly because users do not like it. Where do you go from there?&lt;/p&gt;

&lt;p&gt;You may want to perform a feature rollback so as to "un-release" this feature from its live environment back to its development environment and gather as much real-world user feedback as you can from this release.&lt;/p&gt;

&lt;p&gt;You can then iterate with the newly acquired data to make improvements to the feature or come up with a better initiative, so user expectations are better met.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Feature Bug sneaks its way onto Production
&lt;/h3&gt;

&lt;p&gt;Imagine you developed a new messaging feature and before releasing it to users, it passes through several rigorous QA and internal testing processes. This testing helps uncover bugs and potential problems in the newly developed feature that are later resolved before it is deployed to production.&lt;/p&gt;

&lt;p&gt;However, after releasing this messaging feature to users, a strange bug is encountered that prevents users from sending messages. In such unexpected situations where a feature behaves differently in production as a result of bugs or other technical issues. In order to fix it, you will likely have to roll back the feature.&lt;/p&gt;

&lt;p&gt;A rollback option gives you a near-real-time response to major problems such as these that occur during a feature release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing a Rollback Option Using Feature Flags
&lt;/h2&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%2F7tsesgetwkv3dgeqd3xa.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%2F7tsesgetwkv3dgeqd3xa.png" alt="Feature flags for product managers" width="734" height="370"&gt;&lt;/a&gt;&lt;br&gt;
A feature flag is a simple way to toggle on or off certain functionality for some or all of your users. This toggling can be done without the active participation of your development team via a user interface provided by companies that offer feature flags as a service. Thus, giving not just developers, but also non-technical members of a product control access to run tests, and experiments or incrementally roll out a feature to users.&lt;/p&gt;

&lt;p&gt;Feature flags control who sees and has access to a feature and can be used to break your feature release into incremental rollouts through user segmentation. This is done by first exposing the feature to only a few of your users, such as your internal users or beta testers in production. After gathering feedback from these initial users, you can then gradually roll it out to the rest of your users until every user has access.&lt;/p&gt;

&lt;p&gt;Most importantly, feature flags come with kill switches to facilitate a quick rollback of a feature at any time if things don't go as planned. This empowers you as a product manager and your development team with the flexibility to adapt to unexpected changes as the need arises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Feature Flags to Perform A/B Tests and Experiments
&lt;/h2&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%2Fc76m8xlcmwxgztkpz1p3.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%2Fc76m8xlcmwxgztkpz1p3.png" alt="A/B testing using feature flags" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A product manager is constantly tasked with adding value to products and delivering new customer experiences by bringing their best ideas to life. This is done by conducting user experiments and market research to gain insight into what product ideas would perform as planned or even better before making a final decision on what to move forward with.&lt;/p&gt;

&lt;p&gt;Feature flags include powerful custom targeting functionalities that give you, your engineers and marketing teams control access to perform real-world experiments to better understand your users. In addition, testing more features with more people early in its development cycle helps you decrease certain risks while also gaining business insights before making final rollout decisions.&lt;/p&gt;

&lt;p&gt;With feature flags, you can build quality into your product delivery by running live A/B tests on users to experiment with your ideas in order to find out which idea performs better with users. This ensures that your ideas match both customer expectations and your company's objective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The deployment process is inherently risky, and there can be many unforeseen pitfalls. However, you still have to add new features to your products to keep your customers happy. Having a feature flag rollback option in a development workflow allows you to test new features in a real-world environment earlier on in their development circle while avoiding the most common risks of deployment and reducing risks of failure, which allows you to better serve users.&lt;/p&gt;

&lt;p&gt;By making it easier for product managers to choose which ideas and features to release or roll back; to whom and when; feature flags help bridge the gap between continuous innovation and frequent deployments to production. Product managers are able to set their companies apart from competitors by orchestrating unique user experiences that drive long-term success with this level of control provided by feature flags.&lt;/p&gt;

&lt;p&gt;Most importantly, you don’t have to burden your engineers with the task of building homemade feature flags as there are companies such as &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; that conveniently offer feature flags as a service – making configuring and managing your flags a dashboard away.&lt;/p&gt;

&lt;p&gt;To learn more about becoming a better product manager using feature flags, you can follow ConfigCat on &lt;a href="https://www.linkedin.com/company/configcat/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>product</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Implementing Feature Flags in a Next.js Application</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Thu, 28 Apr 2022 13:14:49 +0000</pubDate>
      <link>https://dev.to/daveyhert/implementing-feature-flags-in-a-nextjs-application-191h</link>
      <guid>https://dev.to/daveyhert/implementing-feature-flags-in-a-nextjs-application-191h</guid>
      <description>&lt;p&gt;Our job as developers often involves releasing new features regularly. However, how can we ensure that these features work properly in production before safely releasing them to all users? It's easy, by feature flagging!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Feature Flagging?
&lt;/h2&gt;

&lt;p&gt;Many companies struggle to roll out new features and functionalities in an incremental way. Feature flagging is a mechanism used to control access to certain features with simple switches called feature flags, feature toggles or feature switches.&lt;/p&gt;

&lt;p&gt;Through feature flagging, anyone can safely test code in production, perform canary releases, conduct A/B testing, and many other unique uses. You can deliver different content and functionalities to targeted users through user segmentation based on a feature flag’s value and its associated config rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly are Feature Flags?
&lt;/h2&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%2F83giqa42y05zeeeg9dp7.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%2F83giqa42y05zeeeg9dp7.png" alt="illustration of feature flags in action" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feature flags are conceptually based on being able to encapsulate sections of your code into conditional statements that can be switched on and off depending on your needs.&lt;/p&gt;

&lt;p&gt;Similarly to an if/else statement, these flags return true/false boolean values based on the state of the feature flags (whether they are toggled on or off) and are implemented directly inside your source code to check these external conditions before executing the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Flag Use Case in a Next.js Application
&lt;/h2&gt;

&lt;p&gt;Consider this scenario: Suppose we implemented a new feature in a Next.js application that allowed us to generate random user profiles with every page load or reload, and we wanted to roll this out to our user base.&lt;/p&gt;

&lt;p&gt;As you may have guessed already, wrapping this feature in a feature flag would give us the perfect control needed to plan a feature release to our users either through incremental roll-out via user segmentation or performing an all-out release.&lt;/p&gt;

&lt;p&gt;We will examine how we can accomplish this by creating a Next.js application that incorporates the aforementioned feature with a feature flag in a step by step process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You’ve local installation of &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node&lt;/a&gt; and &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create a New Feature Flag Using a Feature Flagging Service
&lt;/h2&gt;

&lt;p&gt;Rather than going through the hassle of building and managing an actual feature flag from scratch, I’ll be using &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; – a company that offers feature flags as a service – to create and remotely manage our feature flag from its dashboard.&lt;/p&gt;

&lt;p&gt;So quickly jump to ConfigCat and create a free account, then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to your dashboard.&lt;/li&gt;
&lt;li&gt;Click the ‘Add feature flag’ option and provide the required details about the flag.&lt;/li&gt;
&lt;li&gt;Copy the ConfigCat SDK Key (this will be needed to enable us to connect our Next.js app to our feature flag).
&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%2F4zx2h77gsw34v674bj5b.gif" alt="A screencast illustrating how to create a feature flag and copying the SDK key" width="720" height="320"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Configure and Set Targeting Rules for the Feature Flag
&lt;/h2&gt;

&lt;p&gt;As a feature flag management service, ConfigCat provides multiple ways to target your users with feature flags to achieve a controlled feature release. This can be done by targeting a certain percentage of your traffic allocation or through user segmentation where you can specify the target audience for your feature release based on a list of predefined (or custom) shared attributes such as location, gender, age, etc.&lt;/p&gt;

&lt;p&gt;To keep things simple, I'll be using the default settings – which is to target all users.&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%2Fqafgasv29giftuk31u0o.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%2Fqafgasv29giftuk31u0o.png" alt="random user feature flag toggle" width="800" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Creating the Base Version of the Next.js App
&lt;/h2&gt;

&lt;p&gt;Now that we have our feature flag ready, It’s time for us to create our Next.js application. We’ll start by running create-next-app in the command line to quickly bootstrap a Next.js application for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    npx create-next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterwards, we run the following command to launch our dev environment and have our starter template demo page ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F8av2il7pcwgglfjanls4.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%2F8av2il7pcwgglfjanls4.png" alt="demo of Next.js app" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create Random User Generator Feature in Next.js Application
&lt;/h2&gt;

&lt;p&gt;There are two ways that Next.js pre-renders web pages: Static Generation and Server-side Rendering. In Static Generation, the pages are generated at build time while in Server-side rendering, the page is generated on the server on each request before being sent to the client.&lt;/p&gt;

&lt;p&gt;We will be taking the Server-side rendering route because we will be using a third party &lt;a href="https://randomuser.me/documentation" rel="noopener noreferrer"&gt;Random User API&lt;/a&gt; to get new random user data on each user request (whenever the page is loaded/reloaded).&lt;/p&gt;

&lt;p&gt;Let’s get to it.&lt;/p&gt;

&lt;p&gt;I’ll start by emptying the root index.js file responsible for the home page of our demo application and then creating an export &lt;code&gt;getServerSideProps&lt;/code&gt; function that would be responsible for making requests on the server before the page is generated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // This runs on the server on each request
    export async function getServerSideProps() {
      // Fetch random user data from external API
      const res = await fetch("https://randomuser.me/api/");
      const data = await res.json();

      // Return data to page via props
      return { props: { data: data.results } };
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This random user API returns an array containing an object of randomly generated user details:&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%2F316kc2ijg7xkvqhjzhn3.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%2F316kc2ijg7xkvqhjzhn3.png" alt="random user api response" width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After making the request on the server, the next step is to make use of the data in our component’s template and render the required user details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Page Component
    export default function Home({ data }) {
      // Extract the required user details
      const firstName = data[0].name.first;
      const lastName = data[0].name.last;
      const image = data[0].picture.large;
      const gender = data[0].gender;
      const location = data[0].location.country;

      // Generated page Template
      return (
        &amp;lt;div className='card'&amp;gt;
          &amp;lt;img src={image} class={gender} /&amp;gt;
          &amp;lt;h2&amp;gt;{`${firstName} ${lastName}`}&amp;lt;/h2&amp;gt;
          &amp;lt;p&amp;gt;&amp;lt;span&amp;gt;Gender: &amp;lt;/span&amp;gt; {gender}&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;&amp;lt;span&amp;gt;Location: &amp;lt;/span&amp;gt;{location}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      );
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we have a Next.js app that generates random user details on each page load/reload:&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%2Ft2mce1oa93yutexy3how.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%2Ft2mce1oa93yutexy3how.png" alt="random user generator page" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s pretty much it, we now have a fully working random user generator feature in our Next.js application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Connecting the Next.js Application to ConfigCat and Integrating the Feature Flag
&lt;/h2&gt;

&lt;p&gt;Now that we have our feature ready, it’s time to connect our Next.js application to our feature flagging service provider, before proceeding to integrate the random user generator feature with our feature flag.&lt;/p&gt;

&lt;p&gt;Since we intend to use ConfigCat, I will start by installing their &lt;a href="https://configcat.com/docs/sdk-reference/js-ssr/" rel="noopener noreferrer"&gt;JavaScript (SSR) SDK&lt;/a&gt; via NPM - this is required to connect our application to ConfigCat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    npm i configcat-js-ssr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterwards, I’ll import the installed package into our root index.js component and refactor our &lt;code&gt;getServerSideProps&lt;/code&gt; function by initializing the package using the SDK key copied from the dashboard (i.e. connect our application to ConfigCat using the SDK key):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import * as configcat from "configcat-js-ssr";

    // This runs on the server on each request
    export async function getServerSideProps() {
      // Initialize ConfigCatClient with your SDK Key:
      const configCatClient = configcat.createClient(
        "fK7ZCApWbkaDu14njPKZQw/vBw-jxALN0eiWNilfwboGA");

      // Check the state of the feature flag
      const randomUserFlag = await configCatClient.getValueAsync(
        "randomuserflag", false);

      // Fetch random user data from external API
      const res = await fetch("https://randomuser.me/api/");
      const data = await res.json();

      // Return flag's state and dat to page via props
      return { props: { randomUserFlag, data: data.results } };
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to refactor the template to only render the random profile card if the feature flag is toggled on, and to otherwise render a different message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Page Component
    export default function Home({ data, randomUserFlag }) {
      // Extract the required user details
      const firstName = data[0].name.first;
      const lastName = data[0].name.last;
      const image = data[0].picture.large;
      const gender = data[0].gender;
      const location = data[0].location.country;

      // Page Template
      return (
        &amp;lt;&amp;gt;
          {randomUserFlag &amp;amp;&amp;amp; (
            &amp;lt;div className='card'&amp;gt;
              &amp;lt;img src={image} class={gender} /&amp;gt;
              &amp;lt;h2&amp;gt;{`${firstName} ${lastName}`}&amp;lt;/h2&amp;gt;
              &amp;lt;p&amp;gt;&amp;lt;span&amp;gt;Gender: &amp;lt;/span&amp;gt; {gender}&amp;lt;/p&amp;gt;
              &amp;lt;p&amp;gt;&amp;lt;span&amp;gt;Location: &amp;lt;/span&amp;gt;{location}&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
          )}
          {!randomUserFlag &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Feature has been toggled off&amp;lt;/p&amp;gt;}
        &amp;lt;/&amp;gt;
      );
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that final touch, our feature flag now has control over our random profile card. If we toggle on the feature flag:&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%2F5vkcqury612wn0kz08t2.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%2F5vkcqury612wn0kz08t2.png" alt="feature flag toggled on" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our users would have access to the random profile card generator:&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%2Fn72c9hxcex9hr9zb1fpl.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%2Fn72c9hxcex9hr9zb1fpl.png" alt="feature enabled" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But when the feature flag is toggled off:&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%2Fw1rg45ergzu446ngki1o.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%2Fw1rg45ergzu446ngki1o.png" alt="feature flag toggled off" width="800" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our users have no access to the feature:&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%2Fcyvsunnrw9fgaskuzmwq.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%2Fcyvsunnrw9fgaskuzmwq.png" alt="feature disabled" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;We have seen how feature flagging takes a simple concept - choosing between different code paths at runtime - to help teams introduce features in a controlled manner while in production.&lt;/p&gt;

&lt;p&gt;Through feature flagging, you can ship code more frequently, test in production, perform canary deployment and master feature releases to deliver high-quality software while also reducing some of the risks that come with continuous deployment.&lt;/p&gt;

&lt;p&gt;You may find the following links helpful if you'd like to explore further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/configcat-labs/feature-flags-in-nextjs-sample" rel="noopener noreferrer"&gt;Source code for sample application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://configcat.com/docs/" rel="noopener noreferrer"&gt;ConfigCat Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://configcat.com/blog" rel="noopener noreferrer"&gt;ConfigCat Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information about ConfigCat can be found on its &lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;, &lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.linkedin.com/company/configcat/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; pages.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>devops</category>
      <category>configcat</category>
    </item>
    <item>
      <title>Using Feature Flags in a Remix Application</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Tue, 05 Apr 2022 06:36:52 +0000</pubDate>
      <link>https://dev.to/daveyhert/using-feature-flags-in-a-remix-application-2hb</link>
      <guid>https://dev.to/daveyhert/using-feature-flags-in-a-remix-application-2hb</guid>
      <description>&lt;p&gt;&lt;a href="https://remix.run/" rel="noopener noreferrer"&gt;Remix&lt;/a&gt;, the React-based full-stack framework for building server-rendered applications, has been generating a lot of buzz lately, especially since it was open-sourced. Remix is a dedicated Server-Side Rendering (SSR) framework for building web applications that are rendered on the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Flag Basics
&lt;/h2&gt;

&lt;p&gt;Fundamentally, a feature flag is nothing more than a simple variable that can be remotely set to true or false. It is mostly used as feature switches to toggle on/off a section of a piece of code, usually a functionality or feature that is wrapped in a conditional if statement that uses the feature flag's value for its logic.&lt;/p&gt;

&lt;p&gt;Here's a generic code snippet that demonstrates how a feature flag works in its simplest form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theFeatureFlag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theFeatureFlag&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// execute the code here i.e enable this functionality&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than doing a risky all-out deployment or launch, feature flags allow you to slowly roll out features through user segmentation and easily decouple code from deployment, which can be extremely helpful in a production environment when used in continuous integration and continuous delivery cycle. They also have a lot of other use cases, outside of just these.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Hacker News Trending Feed with Remix
&lt;/h2&gt;

&lt;p&gt;To demonstrate how we can use feature flags in a Remix application, we will start by building a simple Remix app that pulls trending news stories from the popular Hacker News &lt;a href="https://news.ycombinator.com/" rel="noopener noreferrer"&gt;website&lt;/a&gt; using the unofficial Hacker News &lt;a href="https://hn.algolia.com/api" rel="noopener noreferrer"&gt;Search API&lt;/a&gt; on Algolia.&lt;/p&gt;

&lt;p&gt;The idea is to create a news feed that displays the top 20 trending news and then proceed to wrap this feed functionality in a feature flag that is hosted on ConfigCat. Whenever the flag is toggled on, the user visiting the site is shown the top 20 trending news. When the flag is toggled off the user is unable to see this trending news feed.&lt;/p&gt;

&lt;p&gt;Let’s get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://remix.run/" rel="noopener noreferrer"&gt;Remix&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Local installation of &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; and &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A ConfigCat account which will be used to create the feature flag. &lt;a href="https://app.configcat.com/" rel="noopener noreferrer"&gt;Register now&lt;/a&gt; – It’s free.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initializing our Remix App for our Feature Flag
&lt;/h2&gt;

&lt;p&gt;Here is the source code to the sample Remix app on &lt;a href="https://github.com/configcat-labs/feature-flags-in-remix-js-sample-application" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; if you want to follow along. We’ll start by quickly spinning up a working Remix demo app using the create remix command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-remix@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would present us with an interactive welcome screen prompting us to select where and what should be included in our demo app. In the end, we’d be prompted to run &lt;code&gt;npm install&lt;/code&gt; to install all of our dependencies.&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%2Fmmk6t5s1rpmk5wefzik8.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%2Fmmk6t5s1rpmk5wefzik8.png" alt="Remix demo app for our feature flag" width="800" height="347"&gt;&lt;/a&gt;&lt;br&gt;
Now that we have a working demo Remix app, let’s proceed to build our Hacker News feed for our feature flag. We’ll start by creating a loader function in our Remix root component that runs on the server - this allows us to make API calls on the server before the app is rendered.&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;import&lt;/span&gt; &lt;span class="nx"&gt;styleURL&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~/styles/global.css&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLoaderData&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="s2"&gt;remix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Runs on the server - for api calls&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;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="c1"&gt;// fetch stories from HN&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://hn.algolia.com/api/v1/search?tags=front_page&lt;/span&gt;&lt;span class="dl"&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;newsFeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// return stories to App component&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newsFeed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hits&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;We have successfully created a fetch request that pulls in the desired stories from Hacker News and returns it as an array of news stories. Next, we’ll proceed to create our actual HTML template where we will loop through this returned array and render the news as ordered list items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// get access to the stories in the loader function created above&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newsFeed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charSet&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'UTF-8'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'X-UA-Compatible'&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'IE=edge'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'viewport'&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'width=device-width, initial-scale=1.0'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'stylesheet'&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styleURL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Demo Feature Flag&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Trending Hacker News Feed&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newsFeed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;story&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&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;



&lt;p&gt;With that we should now have a working Hacker News Feed that renders the top 20 trending news stories as shown below.&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%2F8i4fk9pu766wdc4dwws1.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%2F8i4fk9pu766wdc4dwws1.png" alt="Remix Hacker News Feed clone" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a Feature Flag on ConfigCat's Dashboard
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;To create a new feature flag, sign in to your &lt;a href="https://app.configcat.com/" rel="noopener noreferrer"&gt;ConfigCat dashboard&lt;/a&gt;. In the upper-left corner of your dashboard you can create a new config file or use the default ‘main’ config.&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%2Fr3mhr0fe4aqy4kaq6875.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%2Fr3mhr0fe4aqy4kaq6875.png" alt="ConfigCat feature flag setup dashboard" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After which, select the ‘Add Feature Flag’ option that allows you create new feature switches and give your flag a name and key value that would be used to access the flag in your application code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F8q0505btgb4qhiy6330w.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%2F8q0505btgb4qhiy6330w.png" alt="Add New Feature Flag or feature toggle" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lastly, copy the SDK key as it would be needed to connect your application to the dashboard.&lt;/li&gt;
&lt;/ol&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%2Fk4qyue80w6wi6wubvngx.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%2Fk4qyue80w6wi6wubvngx.png" alt="Feature flag SDK Key" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also &lt;a href="https://configcat.com/blog/2022/02/09/How-to-do-Canary-Release-Progressive-Delivery-with-ConfigCat/" rel="noopener noreferrer"&gt;targeting options&lt;/a&gt; to configure how to serve the feature flag through user segmentation, but to keep things simple we will only be using the default settings - which is to target all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing the Feature Flag Service SDK in Our Remix App
&lt;/h2&gt;

&lt;p&gt;Feature flag management solutions rely on SDKs. The SDK is installed into your application code where it communicates with the feature flag management service to determine what state the feature flags are in and checks the configuration rules for how they are to be served, i.e what users to target. Additionally, some companies' SDKs like that of ConfigCat are generally open source and safe, but this is not the same for all companies.&lt;/p&gt;

&lt;p&gt;To use the ConfigCat Feature Flagging service, we have to install the ConfigCat SSR Package in our application via NPM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i configcat-js-ssr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will now import the package into our root App component and then initialize it in our loader function with the SDK key that we copied earlier. This would connect our Remix application to our ConfigCat dashboard.&lt;/p&gt;

&lt;p&gt;So, let’s refactor our initial loader function to include just that.&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;import&lt;/span&gt; &lt;span class="nx"&gt;styleURL&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~/styles/global.css&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLoaderData&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="s2"&gt;remix&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;configCat&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;configcat-js-ssr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Runs on the server - for api calls&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;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="c1"&gt;// Connect to your ConfigCat's dashboard&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configCatClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configCat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fK7ZCApWbkaDu14njPKZQw/vBw-jxALN0eiWNilfwboGA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Check and store status of feature flag&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newsFeedFlag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;configCatClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getValueAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;newsfeedfeatureflag&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch stories from Hacker News&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://hn.algolia.com/api/v1/search?tags=front_page&lt;/span&gt;&lt;span class="dl"&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;newsFeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// return stories and status of the feature flag to App component&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newsFeed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newsFeedFlag&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;h2&gt;
  
  
  Controlling the News Feed Functionality with a Feature Flag
&lt;/h2&gt;

&lt;p&gt;Now that we have access to the status of the feature flag in our ConfigCat dashboard, let’s refactor our initial HTML template using a ternary operator to condition whether the news feed is visible or not, depending on the state of the feature flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Get access to the stories and state of feature flag in the loader function created above&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newsFeed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newsFeedFlag&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charset&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'UTF-8'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'X-UA-Compatible'&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'IE=edge'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'viewport'&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'width=device-width, initial-scale=1.0'&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'stylesheet'&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styleURL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Demo Feature Flag&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Trending Hacker News Feed&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newsFeedFlag&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newsFeed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;story&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Ops! News Feed unavailable&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&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;



&lt;p&gt;We can now control our news feed feature from our ConfigCat dashboard using feature toggles. When the feature flag is toggled off, the news feed would be disabled and the user won’t have access to it as shown below.&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%2Fp8ahudgwp0zxwcxe95jk.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%2Fp8ahudgwp0zxwcxe95jk.png" alt="Disabled Feature flag or feature toggle" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But when the feature is toggled back on, the user is given access to the news feed.&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%2Fvlwunjr3le0tx1pe6zaa.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%2Fvlwunjr3le0tx1pe6zaa.png" alt="Feature flag enabled" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Remix sample app on &lt;a href="https://github.com/configcat-labs/feature-flags-in-remix-js-sample-application" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;As seen in the Remix application built above, feature flags make it rather easy to remotely control or release features in your application. With feature flags developers, testers, and IT personnel can basically turn on or off certain functionality and perform targeted releases through user segmentation without affecting the existing application infrastructure.&lt;/p&gt;

&lt;p&gt;However, it is not your team's core competency to build a feature flagging system as it may distract them from their main development process. The need for a feature flag management service is therefore essential as feature flags help you take control of your future releases.&lt;/p&gt;

&lt;p&gt;For more, you can follow ConfigCat on &lt;a href="https://www.facebook.com/configcat" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;, &lt;a href="https://twitter.com/ConfigCat" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.linkedin.com/company/configcat" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>react</category>
    </item>
    <item>
      <title>How to do Canary Release / Progressive Delivery with ConfigCat</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Wed, 16 Feb 2022 10:42:51 +0000</pubDate>
      <link>https://dev.to/daveyhert/how-to-do-canary-release-progressive-delivery-with-configcat-h5l</link>
      <guid>https://dev.to/daveyhert/how-to-do-canary-release-progressive-delivery-with-configcat-h5l</guid>
      <description>&lt;p&gt;In this post, we’ll look at how we can easily implement a canary release of a feature in 7 steps using ConfigCat’s feature flagging service through its provided dashboard.&lt;/p&gt;

&lt;p&gt;This step-by-step guide will showcase how we can release a new feature incrementally, by first exposing it to low-risk user groups (e.g. team members and possibly friends), and then gradually releasing it to a larger audience - using &lt;a href="https://configcat.com" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt;, a feature flag service to implement everything.&lt;/p&gt;

&lt;p&gt;So let’s get right to it. The assumption is that we have logged into our ConfigCat’s dashboard and successfully implemented an instance of a feature flag named “Facebook Sharing Enabled” in our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 - Unreleased State
&lt;/h2&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%2Fcr980fjqt0d3835paubb.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%2Fcr980fjqt0d3835paubb.png" alt="Unreleased State" width="800" height="115"&gt;&lt;/a&gt;&lt;br&gt;
We’ll take it from the start, where we have our feature flag set up and initially toggled off for all users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Releasing Only to Team Members
&lt;/h2&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%2F6xdliixi5d7wtwywyljw.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%2F6xdliixi5d7wtwywyljw.png" alt="Releasing to Team" width="800" height="144"&gt;&lt;/a&gt;&lt;br&gt;
Following that, we need to release the feature to only team members. This allows you to get immediate feedback from your team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Releasing to Team Members and Friends
&lt;/h2&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%2Fs6tuf0vjuxhhgrfwj92e.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%2Fs6tuf0vjuxhhgrfwj92e.png" alt="Releasing to team and friends" width="800" height="183"&gt;&lt;/a&gt;&lt;br&gt;
Afterwards, we proceed to include friends or people in your circle that you have a good relationship with in the feature’s release by having it available to only team members and these people. This allows you to get feedback from real users who will be cooperative with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 - Releasing to 1% of Users - But No Sensitive Users
&lt;/h2&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%2F6j1ctdz0h074hynam6no.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%2F6j1ctdz0h074hynam6no.png" alt="Releasing to 1%" width="800" height="287"&gt;&lt;/a&gt;&lt;br&gt;
If more feedback is needed, the next step would be to have it released to random people, say 1% of users - making sure to exclude the most risky users (i.e those with high expectations and a lot of money). In the screenshot, we’ve targeted those users from the United States as our sensitive users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 - Releasing to 5% of Users - But No Sensitive Users
&lt;/h2&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%2Fjco0oyexss6xp3nrjvzz.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%2Fjco0oyexss6xp3nrjvzz.png" alt="Releasing to 5%" width="800" height="286"&gt;&lt;/a&gt;&lt;br&gt;
Now, we proceed to release it to even more random people - say 5% of users, but still excluding any sensitive users. Now we have our feature available to team members, friends, and 5% of our user base - excluding sensitive users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 - Releasing to Everyone Except Sensitive Users
&lt;/h2&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%2Fg6u08octgj4y57z5gscc.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%2Fg6u08octgj4y57z5gscc.png" alt="Releasing to everyone but sensitive users" width="800" height="146"&gt;&lt;/a&gt;&lt;br&gt;
The next step is to have the feature available to everyone except our sensitive users. At this point, enough confidence has been gained from the received feedback to test it on everyone. The next step is to have the feature available to everyone except our sensitive users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7 - Releasing to Everyone
&lt;/h2&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%2F3lws5pfkwksfdhczteqe.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%2F3lws5pfkwksfdhczteqe.png" alt="Releasing to everyone" width="800" height="109"&gt;&lt;/a&gt;&lt;br&gt;
If all errors have been fixed, UI-glitches corrected, and all the test users are happy with the feature then it’s finally safe to release it to our entire user base - including the sensitive users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we have seen, implementing a canary feature release is no rocket science, especially when using &lt;a href="https://configcat.com" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; as it provides a feature management service, with an easy to use dashboard that makes it convenient and intuitive to do just that. Even a non-technical team member can handle canary releases with ConfigCat’s 10 minutes trainable feature flag and configuration management service.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>configcat</category>
      <category>featureflag</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How To Use Feature Flags in Vue.JS</title>
      <dc:creator>David Herbert💻🚀</dc:creator>
      <pubDate>Sun, 30 Jan 2022 13:44:57 +0000</pubDate>
      <link>https://dev.to/daveyhert/how-to-use-feature-flags-in-vuejs-2apm</link>
      <guid>https://dev.to/daveyhert/how-to-use-feature-flags-in-vuejs-2apm</guid>
      <description>&lt;p&gt;Feature flags have made it easier than ever to continuously test and integrate new features in our applications with confidence, even while in a production environment without having to worry about deployment risks like downtimes or bugs that could greatly impact the experience of the entire user base.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Feature Flags?
&lt;/h2&gt;

&lt;p&gt;Feature Flags are conditional statements like an if/else block of code that provides the ability to switch certain functionalities or features on/off in an application. They return a boolean value that you or anyone else from your team is able to remotely set from the ConfigCat dashboard without deploying code. This feature flagging technique allows logic to be provided only to certain groups or subsets of users at a time by building conditional feature branches into deployed code. During runtime, the code is executed if the flag is toggled on, but is skipped if the flag is off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use feature flags?
&lt;/h2&gt;

&lt;p&gt;Features flags can be applied to a wide variety of use-cases, ranging from the simplest to the most advanced scenarios in the modern software development workflow. But to list a few that reflect their usefulness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Facilitates Beta testing &amp;amp; A/B testing.&lt;/li&gt;
&lt;li&gt;Easily rollback a feature using kill switch.&lt;/li&gt;
&lt;li&gt;Decouple new features from deployment without deploying new code.&lt;/li&gt;
&lt;li&gt;Allows non-technical people to manage feature releases.&lt;/li&gt;
&lt;li&gt;Facilitate subscription/membership-based access to features.&lt;/li&gt;
&lt;li&gt;Safely push to production more often with a shorter release cycle.&lt;/li&gt;
&lt;li&gt;Mitigates typical deployment risks like bugs and downtimes.&lt;/li&gt;
&lt;li&gt;Useful for special use case scenarios - like enabling/disabling maintenance mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, there are a lot of benefits associated with feature flags and why you’d want to use them in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  How To Use Feature Flags in VueJS
&lt;/h2&gt;

&lt;p&gt;Now that we know what feature flags are, and why we’d want to use them. Let’s jump right to how we can use these feature flags in a VueJS application. For this, we’ll be using &lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt;’s feature flagging service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://configcat.com/" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; allows you to manage features in your application without needing to redeploy code. These features can be rolled-out in batches to certain percentages of users and provide the ability to target specific user groups based on user profile attributes such as geo-location or other custom attributes. All of this is also provided on a web-based interface where feature flags can be toggled on/off which is very convenient for non-technical people as there is no need to edit config files. Everything in the ConfigCat dashboard can also be accessed programmatically through the &lt;a href="https://configcat.com/docs/advanced/public-api" rel="noopener noreferrer"&gt;public management API &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Application
&lt;/h2&gt;

&lt;p&gt;To keep things simple and straightforward, we will be creating a calculateAge Feature in a simple VueJS Application that allows users to calculate their age. This &lt;a href="https://github.com/DaveyHert/Vue-feature-flagging" rel="noopener noreferrer"&gt;sample app&lt;/a&gt; would have a form that receives a users birth year and returns the calculated age. However, this feature would only be made available to users when we toggle the feature on from our ConfigCat dashboard. So let’s get to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic understanding of &lt;a href="https://vuejs.org/v2/guide/" rel="noopener noreferrer"&gt;VueJS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/v2/guide/" rel="noopener noreferrer"&gt;NodeJS and NPM&lt;/a&gt; installed.&lt;/li&gt;
&lt;li&gt;Code Editor&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a VueJS Application
&lt;/h2&gt;

&lt;p&gt;Let’s jump right into our code editor and start by first installing the VueJS CLI - which provides some Vue commands which makes it easy to quickly scaffold a demo app in VueJS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g vue@cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we’ll create a new VueJS application from the command line using the Vue create command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue create my-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This quickly spins up a “my-project” directory with a VueJs demo app environment setup. After choosing the default setup, it’ll install the necessary dependencies for our application. With that out of the way, we are going to install a &lt;code&gt;configcat-js&lt;/code&gt;package that would enable us to be able to use ConfigCat in our VueJS application - while we are at it, we would also install a “dotenv” package because we would be needing it to store our ConfigCat SDK key in a .env file (environment variables file).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install configcat-js dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we launch our app in the browser by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Feature Flag
&lt;/h2&gt;

&lt;p&gt;That’s it, everything is up and running in the browser. To create a feature flag, let's head over to &lt;a href="https://configcat.com" rel="noopener noreferrer"&gt;ConfigCat&lt;/a&gt; - if you don’t already have an account, quickly sign up for one. We’ll be using a free account for this demo. Next, log in to your account to get access to the dashboard as shown below.&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%2Fpoccfsjuwnsrggvr4rnb.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%2Fpoccfsjuwnsrggvr4rnb.png" alt="dashboard.png" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once on the dashboard, click on “add feature flag” and provide a name for the feature flag you want to be created and toggle on the values for the environment you want to use this feature flag in (for this demo, we’ll toggle on the test mode).&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%2Fa5x5lni9q2uqwh3rk8l6.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%2Fa5x5lni9q2uqwh3rk8l6.png" alt="feature-flag.png" width="684" height="643"&gt;&lt;/a&gt;&lt;br&gt;
After saving it, we can go back to our dashboard and toggle on this feature flag, or even customize it to target specific users based on predefined or custom attributes.&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%2Fhzyot3kb0w1lf8fjge4z.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%2Fhzyot3kb0w1lf8fjge4z.png" alt="feature-toggle.png" width="800" height="227"&gt;&lt;/a&gt;&lt;br&gt;
To get the SDK key, you can click the view SDK key at the top right of your dashboard or scroll to the bottom of the dashboard where you’re shown how to connect your application to ConfigCat.&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%2Fwym1eusu5denebzunt03.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%2Fwym1eusu5denebzunt03.png" alt="sdk-key.png" width="800" height="312"&gt;&lt;/a&gt;&lt;br&gt;
Copy the code as it would be needed to get access to this account - go ahead and store this in your “.env” file in the VueJS application.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a Feature and Connecting it to ConfigCat
&lt;/h2&gt;

&lt;p&gt;Now let’s jump back to our VueJS application and create a simple VueJS template consisting of a form that lets users calculate their age in the root App.vue directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;div id="app"&amp;gt;
        &amp;lt;button class='btn' @click='getUserAgeFeatureStatus'&amp;gt;
            Calculate Age
        &amp;lt;/button&amp;gt;

        &amp;lt;p v-if='!userAgeFeature &amp;amp;&amp;amp; !loading' class='text'&amp;gt;Sorry, This feature has been disabled by the Admin&amp;lt;/p&amp;gt;
        &amp;lt;p v-else-if="error"&amp;gt;{error}&amp;lt;/p&amp;gt;

        &amp;lt;div v-else-if='userAgeFeature'&amp;gt;
            &amp;lt;p class='text'&amp;gt;Calculate your age below by providing your year of birth&amp;lt;/p&amp;gt;
            &amp;lt;input
                type='number'
                v-model='birthYear'
            /&amp;gt;
            &amp;lt;button class='btn btn-calculate' @click='calcAge'&amp;gt;
                Calculate
            &amp;lt;/button&amp;gt;

            &amp;lt;p v-if='age'&amp;gt;You are {{ age }} years old&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this sample example, we have designed a template with just a button indicating the feature. If the feature has been turned off, it should display a message to the user showing the feature is not accessible but if the feature is available for the user, there should be an input field and button for the user to calculate age.&lt;/p&gt;

&lt;p&gt;Next, we would need to import ConfigCat where we need to use it like in the below snippet.&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%2Fh2cetnv6icaoj26p5vbz.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%2Fh2cetnv6icaoj26p5vbz.png" alt="import-configcat.png" width="800" height="244"&gt;&lt;/a&gt;&lt;br&gt;
Then create a &lt;code&gt;configcat.client()&lt;/code&gt; object and pass it the SDK key we got from our dashboard.&lt;/p&gt;

&lt;p&gt;Also, we are going to add some states to the data property to be able to keep track of their values. We would have the userAgeFeature which would help us to know the state of the feature, the error to keep track of any error that occurs, the birthYear and age to keep track of the birthYear and age of the user respectively.&lt;/p&gt;

&lt;p&gt;Lastly, we would then create the getUserAgeFeatureStatus method to check for the state of the feature in ConfigCat.&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%2For8wpe9lkts31hgrm2qm.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%2For8wpe9lkts31hgrm2qm.png" alt="code-snippet.png" width="800" height="1127"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/DaveyHert/Vue-feature-flagging/blob/main/src/App.vue" rel="noopener noreferrer"&gt;Source file&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To reiterate what we just did, firstly, an instance of the client is created with the client SDK detail which is being stored in a variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try {
                let configCatClient = configCat.createClient(
                    process.env.VUE_APP_CONFIGCAT_SDK
                );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK key has been stored in the .env file in the base directory for security purposes. To avoid errors, please make sure you use the same name as your .env file after process.env.&lt;/p&gt;

&lt;p&gt;Then, we await the response from getting the status of a particular feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const res = await configCatClient.getValueAsync(
                    "isMyFirstFeatureEnabled",
                    false
                );
                this.userAgeFeature = res
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first argument is the feature flag’s name on the ConfigCat dashboard while the second argument is the default value. The response returned is a boolean, either true or false. This response is then saved in the userAgeFeature state.&lt;/p&gt;

&lt;p&gt;Lastly, we check if there was an error - which is handled by the error state that receives the error message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;} catch (err) {
                this.error = err.message
            }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The getUserAgeFeatureStatus is then bound to the HTML by an on click event as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button class='btn' @click='getUserAgeFeatureStatus'&amp;gt;
            Calculate Age
 &amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the state of the feature in the dashboard, if the Calculate Age Button is clicked, it checks the status of the feature on the client ConfigCat’s dashboard. If it is false i.e turned off, a message is displayed to notify the user that the feature is currently disabled.&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%2F9e2q25dzvmcqps7oumry.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%2F9e2q25dzvmcqps7oumry.png" alt="disabled-feature-flag.png" width="800" height="367"&gt;&lt;/a&gt;&lt;br&gt;
But if it is true i.e turned on, the user is able to use the calculateAge feature to calculate their age.&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%2Fgm0k6ox8vrhd9egsi59n.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%2Fgm0k6ox8vrhd9egsi59n.png" alt="enabled-feature-flag.png" width="800" height="365"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/DaveyHert/Vue-feature-flagging" rel="noopener noreferrer"&gt;Source Code&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you aren't using feature flags, you're probably missing out on the perfect tool for mastering your development cycles and feature releases. As you have seen, it’s quite easy to implement feature flags in your VueJS application using ConfigCat’s feature flagging service.&lt;/p&gt;

&lt;p&gt;In just 10 minutes of training, even team members who are not technically inclined can learn and use ConfigCat's feature flag solution to gain control over feature releases. You can learn more on their &lt;a href="https://configcat.com/architecture/" rel="noopener noreferrer"&gt;How it Works&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;If you found this article interesting, you can also checkout how to implement ConfigCats's feature flag in &lt;a href="https://configcat.com/blog/2021/12/13/feature-flags-in-react" rel="noopener noreferrer"&gt;React&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
