<?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>Forem: Shanu Kumawat</title>
    <description>The latest articles on Forem by Shanu Kumawat (@shanu-kumawat).</description>
    <link>https://forem.com/shanu-kumawat</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%2F1265123%2Fbb6b4d40-2083-4c8a-a5ed-d48eeb5040ed.jpg</url>
      <title>Forem: Shanu Kumawat</title>
      <link>https://forem.com/shanu-kumawat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shanu-kumawat"/>
    <language>en</language>
    <item>
      <title>Creating Custom, Reusable Animations in Flutter That Don't Kill Performance</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Tue, 04 Mar 2025 12:06:04 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/creating-custom-reusable-animations-in-flutter-that-dont-kill-performance-3c7</link>
      <guid>https://forem.com/shanu-kumawat/creating-custom-reusable-animations-in-flutter-that-dont-kill-performance-3c7</guid>
      <description>&lt;p&gt;If you've ever tried to add animations to your Flutter app, you know there's a fine line between delightful user experience and watching your app's performance graph take a nosedive. After spending countless hours debugging janky animations and memory leaks, I've compiled my hard-earned lessons into this guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Animation Problem
&lt;/h2&gt;

&lt;p&gt;Flutter offers incredible animation capabilities out of the box, but there's a catch: poorly implemented animations can destroy your app's performance. The biggest culprits I've encountered are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rebuilding entire widget trees during animation&lt;/li&gt;
&lt;li&gt;Running too many simultaneous animations&lt;/li&gt;
&lt;li&gt;Using complex animations on low-end devices&lt;/li&gt;
&lt;li&gt;Failing to dispose of animation controllers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These issues become especially problematic when you're trying to create reusable animation components. Let's fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting With the Basics: Animation Controllers
&lt;/h2&gt;

&lt;p&gt;Every good Flutter animation starts with proper controller management. Here's my go-to pattern for creating a reusable, performance-friendly animated widget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OptimizedAnimatedWidget&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;OptimizedAnimatedWidget&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_OptimizedAnimatedWidgetState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_OptimizedAnimatedWidgetState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_OptimizedAnimatedWidgetState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OptimizedAnimatedWidget&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;SingleTickerProviderStateMixin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="n"&gt;AnimationController&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="n"&gt;Animation&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_animation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;_controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AnimationController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;vsync:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;duration:&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CurvedAnimation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;parent:&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;curve:&lt;/span&gt; &lt;span class="n"&gt;Curves&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;easeInOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// This is crucial!&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;AnimatedBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;animation:&lt;/span&gt; &lt;span class="n"&gt;_animation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;child&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="n"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;scale:&lt;/span&gt; &lt;span class="n"&gt;_animation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;child&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="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// This is our performance trick!&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The secret sauce here is passing the &lt;code&gt;child&lt;/code&gt; to &lt;code&gt;AnimatedBuilder&lt;/code&gt;. This prevents Flutter from rebuilding the child on every animation frame, which is a common performance killer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technique #1: RepaintBoundary for Complex Animations
&lt;/h2&gt;

&lt;p&gt;When your animations involve complex widgets, wrap them in a &lt;code&gt;RepaintBoundary&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="nd"&gt;@override&lt;/span&gt;
&lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;AnimatedBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;animation:&lt;/span&gt; &lt;span class="n"&gt;_animation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;child&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="n"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;scale:&lt;/span&gt; &lt;span class="n"&gt;_animation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;RepaintBoundary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;child&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="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a new "layer" for Flutter's rendering engine, preventing the entire widget tree from repainting on each animation frame.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technique #2: Custom Tween Classes for Reusability
&lt;/h2&gt;

&lt;p&gt;To make animations truly reusable, I create custom Tween classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShakeTween&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Tween&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ShakeTween&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;begin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;begin:&lt;/span&gt; &lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;lerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Custom shake animation&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.25&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;-&lt;/span&gt;&lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.75&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="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.75&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.33&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;-&lt;/span&gt;&lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can reuse this shake animation anywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Animation&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_shakeAnimation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ShakeTween&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Technique #3: Composable Animation Widgets
&lt;/h2&gt;

&lt;p&gt;For truly reusable animations, I build composable widgets that can be stacked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FadeScale&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;FadeScale&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isActive&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="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;TweenAnimationBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;tween:&lt;/span&gt; &lt;span class="n"&gt;Tween&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;begin:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="n"&gt;isActive&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;duration:&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;curve:&lt;/span&gt; &lt;span class="n"&gt;Curves&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;easeOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;child&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="n"&gt;Opacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;opacity:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;scale:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// This prevents unnecessary rebuilds&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can now use this anywhere in my app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FadeScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;isActive:&lt;/span&gt; &lt;span class="n"&gt;_isVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;MyExpensiveWidget&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;
  
  
  Performance Testing Tips
&lt;/h2&gt;

&lt;p&gt;After implementing these patterns, I always test animations on real devices (especially low-end Android phones) using the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Timeline View&lt;/strong&gt;: Enable "Track widget builds" in Flutter DevTools to see if widgets are rebuilding unnecessarily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overlay&lt;/strong&gt;: Add &lt;code&gt;MaterialApp(showPerformanceOverlay: true)&lt;/code&gt; to check for dropped frames.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory Profiling&lt;/strong&gt;: Watch memory usage during animations to catch leaks from undisposed controllers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real-World Example: A Reusable "Heart Beat" Animation
&lt;/h2&gt;

&lt;p&gt;Here's a complete example of a performance-optimized, reusable heart beat animation I use in production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HeartBeat&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isAnimating&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HeartBeat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;milliseconds:&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnimating&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="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_HeartBeatState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_HeartBeatState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_HeartBeatState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HeartBeat&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;SingleTickerProviderStateMixin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="n"&gt;AnimationController&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="n"&gt;Animation&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_scaleAnimation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;_controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AnimationController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;vsync:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;duration:&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;_scaleAnimation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TweenSequence&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;([&lt;/span&gt;
      &lt;span class="n"&gt;TweenSequenceItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;tween:&lt;/span&gt; &lt;span class="n"&gt;Tween&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;begin:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nl"&gt;weight:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;TweenSequenceItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;tween:&lt;/span&gt; &lt;span class="n"&gt;Tween&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;begin:&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nl"&gt;weight:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;TweenSequenceItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;tween:&lt;/span&gt; &lt;span class="n"&gt;Tween&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;begin:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="mf"&gt;1.15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nl"&gt;weight:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;TweenSequenceItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;tween:&lt;/span&gt; &lt;span class="n"&gt;Tween&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;begin:&lt;/span&gt; &lt;span class="mf"&gt;1.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nl"&gt;weight:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;TweenSequenceItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;tween:&lt;/span&gt; &lt;span class="n"&gt;Tween&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nl"&gt;begin:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;end:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nl"&gt;weight:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CurvedAnimation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;parent:&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;curve:&lt;/span&gt; &lt;span class="n"&gt;Curves&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;easeInOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnimating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repeat&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="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;didUpdateWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HeartBeat&lt;/span&gt; &lt;span class="n"&gt;oldWidget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;didUpdateWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldWidget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnimating&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;oldWidget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnimating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnimating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;AnimatedBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;animation:&lt;/span&gt; &lt;span class="n"&gt;_scaleAnimation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;child&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="n"&gt;Transform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;scale:&lt;/span&gt; &lt;span class="n"&gt;_scaleAnimation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;child&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="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;After implementing these techniques in multiple apps, I've seen dramatic performance improvements, especially on older devices. The key takeaways are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prevent unnecessary rebuilds by using the &lt;code&gt;child&lt;/code&gt; parameter in &lt;code&gt;AnimatedBuilder&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create custom Tweens for complex motion&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;RepaintBoundary&lt;/code&gt; for complex widgets&lt;/li&gt;
&lt;li&gt;Always dispose your controllers&lt;/li&gt;
&lt;li&gt;Test on real, low-end devices&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What animation challenges have you faced in your Flutter projects? I'd love to hear about them in the comments below!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>android</category>
      <category>animation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Do You Build Scalable Apps in Flutter? 🚀</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Thu, 16 Jan 2025 17:25:21 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/how-do-you-build-scalable-apps-in-flutter-3jg3</link>
      <guid>https://forem.com/shanu-kumawat/how-do-you-build-scalable-apps-in-flutter-3jg3</guid>
      <description>&lt;p&gt;As Flutter apps scale, maintaining a clean, manageable codebase is essential. One of my best practices is embracing immutability—keeping data structures immutable to avoid unexpected side effects and simplify debugging. 🔒&lt;/p&gt;

&lt;p&gt;What are your best practices for large-scale Flutter app development?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do you structure your code as the app grows?&lt;/li&gt;
&lt;li&gt;What tools or patterns do you use to maintain code quality?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking forward to hearing your thoughts and tips! 💬&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>discuss</category>
      <category>designpatterns</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>How to Work with State in Flutter 🛠️📱</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Thu, 16 Jan 2025 17:08:16 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/how-to-work-with-state-in-flutter-21l0</link>
      <guid>https://forem.com/shanu-kumawat/how-to-work-with-state-in-flutter-21l0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let’s talk about state in Flutter. If you’ve ever been puzzled by terms like "stateless" and "stateful," don’t worry—you’re not alone. When I started with Flutter, understanding state management felt like deciphering a secret code. But here’s the thing: mastering state is crucial if you want your app to behave the way users expect.&lt;/p&gt;

&lt;p&gt;In this blog, I’ll walk you through the basics of state in Flutter, share a few "aha" moments from my own journey, and show you how to manage it like a pro. Let’s dive in!&lt;/p&gt;




&lt;h2&gt;
  
  
  What is State, and Why Does It Matter?
&lt;/h2&gt;

&lt;p&gt;In simple terms, state is just data that changes over time. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The text inside a search bar is state—it changes as the user types.&lt;/li&gt;
&lt;li&gt;A button’s color when toggled is state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flutter apps are reactive, meaning they rebuild parts of the UI when state changes. This is super powerful because you don’t have to manually update the UI—it just works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stateless vs. Stateful Widgets
&lt;/h2&gt;

&lt;p&gt;When I first saw these terms, I thought, Great, more jargon. But it’s actually pretty straightforward:&lt;/p&gt;

&lt;p&gt;Stateless Widgets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These don’t hold any state. They’re immutable.&lt;/li&gt;
&lt;li&gt;Use them when the UI doesn’t need to change after it’s built.&lt;/li&gt;
&lt;li&gt;Example: A static Text widget or an icon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stateful Widgets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These can change! They have a lifecycle and can rebuild when the state updates.&lt;/li&gt;
&lt;li&gt;Use them when you need interactivity or dynamic content.&lt;/li&gt;
&lt;li&gt;Example: A counter app where a button increments a value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Start with a &lt;code&gt;StatelessWidget&lt;/code&gt; if you’re unsure and switch to &lt;code&gt;StatefulWidget&lt;/code&gt; only if needed. This keeps things clean and simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing State with &lt;code&gt;setState&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The simplest way to manage state is with &lt;code&gt;setState&lt;/code&gt;. Here’s an example from the classic counter app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_CounterAppState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_CounterAppState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_CounterAppState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CounterApp&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;incrementCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;counter&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&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="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="s"&gt;"Text('Counter App')),"&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;mainAxisAlignment:&lt;/span&gt; &lt;span class="n"&gt;MainAxisAlignment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&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="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'You have pressed the button this many times:'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;$counter&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;style:&lt;/span&gt; &lt;span class="n"&gt;TextStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fontSize:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;floatingActionButton:&lt;/span&gt; &lt;span class="n"&gt;FloatingActionButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="n"&gt;incrementCounter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the button is pressed, the UI updates because &lt;code&gt;setState&lt;/code&gt; tells Flutter to rebuild.&lt;/p&gt;

&lt;h2&gt;
  
  
  When &lt;code&gt;setState&lt;/code&gt; Isn’t Enough
&lt;/h2&gt;

&lt;p&gt;In small apps, &lt;code&gt;setState&lt;/code&gt; is fine. But as your app grows, managing state with &lt;code&gt;setState&lt;/code&gt; can get messy. Imagine a to-do list app with hundreds of widgets. Keeping track of all those states can become a nightmare.&lt;/p&gt;

&lt;p&gt;That’s where state management solutions like Provider, Riverpod, or BLoC come into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  State Management Insights
&lt;/h2&gt;

&lt;p&gt;Here’s what I learned from experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start simple. Use setState to understand the basics.&lt;/li&gt;
&lt;li&gt;Gradually introduce a state management package as your app grows.&lt;/li&gt;
&lt;li&gt;Learn one tool deeply. I started with Provider—it’s beginner-friendly yet powerful.&lt;/li&gt;
&lt;li&gt;Debugging state changes is easier if you structure your app well. Avoid putting too much logic in widgets.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;State is the heart of your Flutter app. Start small, experiment, and don’t be afraid to refactor as you learn. Once you’ve mastered the basics, tools like Provider or BLoC will make more sense, and you’ll wonder how you ever lived without them!&lt;/p&gt;

&lt;p&gt;Have questions or tips of your own? Drop a comment below—I’d love to hear from you.&lt;/p&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;Hi, I'm Shanu Kumawat, a Flutter developer passionate about crafting seamless and beautiful mobile applications. Currently, I'm diving deeper into expanding my tech stack by learning Rust.  &lt;/p&gt;

&lt;p&gt;When I'm not coding, I enjoy exploring innovative technologies and sharing knowledge with the community. Connect with me on &lt;a href="https://github.com/Shanu-Kumawat" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://twitter.com/Shanu_Kumawat01" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://linkedin.com/in/shanu-kumawat01" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to collaborate and grow together!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Unlocking the Power of Elixir Phoenix and Rust: A Match Made for High-Performance Web Applications ⚡🔧</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Tue, 24 Dec 2024 13:16:38 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/unlocking-the-power-of-elixir-phoenix-and-rust-a-match-made-for-high-performance-web-applications-58gf</link>
      <guid>https://forem.com/shanu-kumawat/unlocking-the-power-of-elixir-phoenix-and-rust-a-match-made-for-high-performance-web-applications-58gf</guid>
      <description>&lt;p&gt;As developers, we’re always on the lookout for tools and technologies that enable us to build faster, more efficient, and scalable applications. Enter the dynamic duo of &lt;strong&gt;Elixir Phoenix&lt;/strong&gt; and &lt;strong&gt;Rust&lt;/strong&gt;, two technologies that, when combined, can take web application development to the next level. &lt;/p&gt;

&lt;p&gt;In this article, we’ll explore why pairing Elixir Phoenix and Rust is a game-changer and how you can leverage their strengths to build robust, high-performance applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Elixir Phoenix?
&lt;/h2&gt;

&lt;p&gt;Elixir Phoenix is known for its &lt;strong&gt;real-time capabilities&lt;/strong&gt;, &lt;strong&gt;fault-tolerance&lt;/strong&gt;, and &lt;strong&gt;concurrency&lt;/strong&gt;. Built on top of the Erlang VM (BEAM), it’s perfect for creating highly concurrent and low-latency web applications. Some standout features of Phoenix include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Channels&lt;/strong&gt;: Seamless real-time communication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Easily handle millions of connections simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fault-Tolerance&lt;/strong&gt;: The BEAM’s process model ensures system reliability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Phoenix is a powerhouse for web applications, but it’s not optimized for computationally intensive tasks. That’s where Rust comes in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Rust?
&lt;/h2&gt;

&lt;p&gt;Rust is a systems programming language that combines &lt;strong&gt;memory safety&lt;/strong&gt; with &lt;strong&gt;blazing-fast performance&lt;/strong&gt;. Unlike traditional systems languages, Rust ensures safety without compromising on speed, making it perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Computationally heavy tasks.&lt;/li&gt;
&lt;li&gt;Building high-performance APIs.&lt;/li&gt;
&lt;li&gt;Memory-critical operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rust’s ecosystem, including libraries like &lt;strong&gt;Actix&lt;/strong&gt; and &lt;strong&gt;Tokio&lt;/strong&gt;, is tailored for high-performance tasks, making it the ideal companion to Elixir Phoenix.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Perfect Combo: Elixir Phoenix + Rust
&lt;/h2&gt;

&lt;p&gt;Combining Phoenix and Rust enables developers to use the best of both worlds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Web Framework + High Performance&lt;/strong&gt;: Use Phoenix for handling web requests and real-time updates, while offloading heavy computations or performance-critical logic to Rust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices Architecture&lt;/strong&gt;: Integrate Rust services with your Phoenix application for computationally intensive operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability and Speed&lt;/strong&gt;: Handle millions of connections in Phoenix while leveraging Rust for low-latency computations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This combination is particularly beneficial in applications requiring both scalability and high performance, such as &lt;strong&gt;real-time analytics dashboards&lt;/strong&gt;, &lt;strong&gt;game backends&lt;/strong&gt;, or &lt;strong&gt;IoT platforms&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Integrate Phoenix and Rust
&lt;/h2&gt;

&lt;p&gt;Integrating Phoenix and Rust involves creating a seamless communication pipeline between the two technologies. Here’s a basic approach:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Rust NIFs (Native Implemented Functions)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rust NIFs allow you to write computationally heavy functions in Rust and call them directly from Elixir code using libraries like &lt;a href="https://github.com/rusterlium/rustler" rel="noopener noreferrer"&gt;&lt;code&gt;Rustler&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Rustler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;otp_app:&lt;/span&gt; &lt;span class="ss"&gt;:my_app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;crate:&lt;/span&gt; &lt;span class="ss"&gt;:my_rust_crate&lt;/span&gt;

  &lt;span class="c1"&gt;# Function defined in Rust&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;heavy_computation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nif_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:not_implemented&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;JSON APIs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can create a Rust-based microservice (e.g., using Actix Web) and have Phoenix communicate with it via HTTP or gRPC.&lt;/p&gt;

&lt;p&gt;Example Rust API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Responder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[get(&lt;/span&gt;&lt;span class="s"&gt;"/compute"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"Rust-powered computation result"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phoenix can then fetch results using an HTTP client like Tesla or HTTPoison.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Message Queues&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more decoupled communication, you can use a &lt;br&gt;
message queue like RabbitMQ or Kafka to send tasks to Rust workers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Real-Time Dashboards: Use Phoenix for real-time updates and Rust for processing data streams.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Video/Audio Processing: Handle user interactions in Phoenix while using Rust for encoding or transcoding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IoT Platforms: Phoenix can manage devices and connections, while Rust processes sensor data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set up Phoenix: Follow the &lt;a href="https://hexdocs.pm/phoenix/installation.html" rel="noopener noreferrer"&gt;Phoenix installation guide&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learn Rust Basics: Start with the official &lt;a href="https://doc.rust-lang.org/book/" rel="noopener noreferrer"&gt;Rust book&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose Your Integration Method: Decide between NIFs, APIs, or queues based on your project requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Elixir Phoenix and Rust are a match made in heaven for developers building scalable, high-performance applications. By combining Phoenix’s concurrency and real-time capabilities with Rust’s raw power, you can create systems that are both efficient and resilient.&lt;/p&gt;

&lt;p&gt;Start experimenting with this powerful combo and unlock new possibilities in your web development journey!&lt;/p&gt;




&lt;p&gt;What do you think of this combination? Have you tried integrating Phoenix with Rust? Share your experiences in the comments below!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>rust</category>
      <category>backend</category>
      <category>phoenix</category>
    </item>
    <item>
      <title>How to Set Up Kanata on NixOS: A Step-by-Step Guide 🖥️</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Wed, 18 Dec 2024 09:50:07 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/how-to-set-up-kanata-on-nixos-a-step-by-step-guide-1jkc</link>
      <guid>https://forem.com/shanu-kumawat/how-to-set-up-kanata-on-nixos-a-step-by-step-guide-1jkc</guid>
      <description>&lt;p&gt;This guide is a follow-up to my previous blog on setting up Kanata on Linux. If you're using NixOS, here's how you can configure Kanata seamlessly.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;NixOS Installed:&lt;/strong&gt; Make sure you have NixOS up and running on your system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kanata Knowledge:&lt;/strong&gt; Familiarity with Kanata and its use cases will be helpful. If you’re new to Kanata, check out my &lt;a href="https://dev.to/shanu-kumawat/boost-your-linux-productivity-remapping-useless-keys-with-kanata-3ih5"&gt;previous blog&lt;/a&gt; on setting it up on Linux.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Add the following configuration to your NixOS configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;pkgs&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="c"&gt;# Enable the uinput module&lt;/span&gt;
  &lt;span class="nv"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;kernelModules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"uinput"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c"&gt;# Enable uinput&lt;/span&gt;
  &lt;span class="nv"&gt;hardware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;uinput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&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="c"&gt;# Set up udev rules for uinput&lt;/span&gt;
  &lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;udev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;extraRules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  ''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;# Ensure the uinput group exists&lt;/span&gt;
  &lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;groups&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;uinput&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="c"&gt;# Add the Kanata service user to necessary groups&lt;/span&gt;
  &lt;span class="nv"&gt;systemd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;kanata-internalKeyboard&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;serviceConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;SupplementaryGroups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"input"&lt;/span&gt;
      &lt;span class="s2"&gt;"uinput"&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;kanata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;enable&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="nv"&gt;keyboards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;internalKeyboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="c"&gt;# Replace the paths below with the appropriate device paths for your setup.&lt;/span&gt;
          &lt;span class="c"&gt;# Use `ls /dev/input/by-path/` to find your keyboard devices.&lt;/span&gt;
          &lt;span class="s2"&gt;"/dev/input/by-path/platform-i8042-serio-0-event-kbd"&lt;/span&gt;
          &lt;span class="s2"&gt;"/dev/input/by-path/pci-0000:00:14.0-usb-0:3:1.0-event-kbd"&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;extraDefCfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"process-unmapped-keys yes"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          (defsrc&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           caps tab d h j k l&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          )&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          (defvar&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           tap-time 200&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           hold-time 200&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          )&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          (defalias&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           caps (tap-hold 200 200 esc lctl)&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           tab (tap-hold $tap-time $hold-time tab (layer-toggle arrow))&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           del del  ;; Alias for the true delete key action&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          )&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          (deflayer base&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           @caps @tab d h j k l&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          )&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          (deflayer arrow&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;           _ _ @del left down up right&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          )&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&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;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explanation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;uinput Module:&lt;/strong&gt; Ensures the kernel module is loaded for user input devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Udev Rules:&lt;/strong&gt; Configures permissions for the &lt;code&gt;uinput&lt;/code&gt; device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kanata Service:&lt;/strong&gt; Defines Kanata keyboard mappings and layers with specific devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing the Configuration
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Rebuild your system configuration:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;nixos-rebuild switch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Identify your keyboard devices:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;ls&lt;/span&gt; /dev/input/by-path/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;devices&lt;/code&gt; paths in the configuration with the relevant paths for your setup.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify that the &lt;code&gt;uinput&lt;/code&gt; group exists:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   getent group uinput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Ensure Kanata is running and working as expected with your keyboard mappings.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;That's it! You now have Kanata set up and running on NixOS. If you encounter any issues or have suggestions for improvement, feel free to leave a comment or reach out.&lt;/p&gt;

&lt;p&gt;Happy typing!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>nixos</category>
      <category>productivity</category>
      <category>keyboard</category>
    </item>
    <item>
      <title>Easy Way to Set Up Flutter Development Environment on NixOS without Flakes or Dev-Shell 🔧</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Wed, 11 Dec 2024 09:23:33 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/setting-up-flutter-development-environment-on-nix-6pk</link>
      <guid>https://forem.com/shanu-kumawat/setting-up-flutter-development-environment-on-nix-6pk</guid>
      <description>&lt;h2&gt;
  
  
  Why I Wrote This Article
&lt;/h2&gt;

&lt;p&gt;As a developer, I've often found the lack of beginner-friendly documentation and updated guides for setting up Flutter on Nix to be a significant hurdle. This article addresses that gap by providing a detailed guide on how to configure Flutter for development on Nix. I use this setup personally, and I'll keep this article updated as I refine my configuration.&lt;/p&gt;

&lt;p&gt;You can find the repository for my Nix configuration here:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/Shanu-Kumawat/nix-config" rel="noopener noreferrer"&gt;My Nix Config Repository&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This guide demonstrates how to configure Flutter as a Nix module. If you'd prefer, you can also adapt it into a &lt;code&gt;devshell&lt;/code&gt; setup. We'll begin by creating a &lt;code&gt;flutter.nix&lt;/code&gt; file and importing it into your &lt;code&gt;configuration.nix&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating the &lt;code&gt;flutter.nix&lt;/code&gt; File
&lt;/h2&gt;

&lt;p&gt;Start by creating a &lt;code&gt;flutter.nix&lt;/code&gt; file. Here's the configuration I use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pkgs&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="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;flutter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;androidComposition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;androidenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;composeAndroidPackages&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;toolsVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"26.1.1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;platformToolsVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"35.0.1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;buildToolsVersions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"30.0.3"&lt;/span&gt;
      &lt;span class="s2"&gt;"33.0.1"&lt;/span&gt;
      &lt;span class="s2"&gt;"34.0.0"&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;platformVersions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"31"&lt;/span&gt;
      &lt;span class="s2"&gt;"33"&lt;/span&gt;
      &lt;span class="s2"&gt;"34"&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;abiVersions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"x86_64"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;includeEmulator&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="nv"&gt;emulatorVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"35.1.4"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;includeSystemImages&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="nv"&gt;systemImageTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"google_apis_playstore"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;includeSources&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="nv"&gt;extraLicenses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"android-googletv-license"&lt;/span&gt;
      &lt;span class="s2"&gt;"android-sdk-arm-dbt-license"&lt;/span&gt;
      &lt;span class="s2"&gt;"android-sdk-license"&lt;/span&gt;
      &lt;span class="s2"&gt;"android-sdk-preview-license"&lt;/span&gt;
      &lt;span class="s2"&gt;"google-gdk-license"&lt;/span&gt;
      &lt;span class="s2"&gt;"intel-android-extra-license"&lt;/span&gt;
      &lt;span class="s2"&gt;"intel-android-sysimage-license"&lt;/span&gt;
      &lt;span class="s2"&gt;"mips-android-sysimage-license"&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nv"&gt;androidSdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;androidComposition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;androidsdk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;buildToolsVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"33.0.1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;flutter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;mkEnableOption&lt;/span&gt; &lt;span class="s2"&gt;"Flutter development environment"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;addToKvmGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;mkEnableOption&lt;/span&gt; &lt;span class="s2"&gt;"Add user to KVM group for hardware acceleration"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;enableAdb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;mkEnableOption&lt;/span&gt; &lt;span class="s2"&gt;"Enable ADB and add user to adbusers group"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;mkOption&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Username for Flutter development"&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="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;mkIf&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;systemPackages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nv"&gt;flutter&lt;/span&gt;
      &lt;span class="nv"&gt;androidSdk&lt;/span&gt;
      &lt;span class="c"&gt;# android-studio&lt;/span&gt;
      &lt;span class="nv"&gt;jdk17&lt;/span&gt;
      &lt;span class="nv"&gt;firebase-tools&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nv"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;variables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;ANDROID_SDK_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;androidSdk&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/libexec/android-sdk"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;ANDROID_HOME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;androidSdk&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/libexec/android-sdk"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;JAVA_HOME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;jdk17&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;GRADLE_OPTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-Dorg.gradle.project.android.aapt2FromMavenOverride=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;androidSdk&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/libexec/android-sdk/build-tools/34.0.0/aapt2"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;android_sdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;accept_license&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="nv"&gt;allowUnfree&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="nv"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;shellInit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;      export PATH=$PATH:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;androidSdk&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/libexec/android-sdk/platform-tools&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;      export PATH=$PATH:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;androidSdk&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/libexec/android-sdk/cmdline-tools/latest/bin&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;      export PATH=$PATH:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;androidSdk&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/libexec/android-sdk/emulator&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;      export PATH="$PATH":"$HOME/.pub-cache/bin"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    ''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;adb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enableAdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;extraGroups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;optional&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;addToKvmGroup&lt;/span&gt; &lt;span class="s2"&gt;"kvm"&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="nv"&gt;optional&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enableAdb&lt;/span&gt; &lt;span class="s2"&gt;"adbusers"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to modify it according to your needs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Importing into &lt;code&gt;configuration.nix&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Once you have the flutter.nix file, import it into your configuration.nix like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;imports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="sx"&gt;./path/to/flutter.nix&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace ./path/to/flutter.nix with the actual path to your flutter.nix file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Configuration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enable the Flutter module in your `configuration.nix`:&lt;/span&gt;
&lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;flutter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;enable&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="nv"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-username"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;# Replace with your actual username&lt;/span&gt;
  &lt;span class="nv"&gt;enableAdb&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="c"&gt;# Enable ADB for Android debugging&lt;/span&gt;
  &lt;span class="nv"&gt;addToKvmGroup&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="c"&gt;# Add to KVM group for hardware acceleration&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Things to Note
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This configuration assumes you're using flakes and the unstable branch of Nixpkgs. If you're facing issues, ensure that flakes are enabled in your setup.&lt;/li&gt;
&lt;li&gt;If you're unsure about any step or encounter errors, feel free to reach out or ask in the comments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Need More Tutorials?
&lt;/h2&gt;

&lt;p&gt;If you'd like more tutorials on Nix, Flutter, or anything else, let me know! I’m happy to explore and write on topics that help the community.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;Hi, I'm Shanu Kumawat, a Flutter developer passionate about crafting seamless and beautiful mobile applications. Currently, I'm diving deeper into expanding my tech stack by learning Elixir and Phoenix, embracing the world of functional programming and scalable web development.  &lt;/p&gt;

&lt;p&gt;When I'm not coding, I enjoy exploring innovative technologies and sharing knowledge with the community. Connect with me on &lt;a href="https://github.com/Shanu-Kumawat" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://twitter.com/Shanu_Kumawat01" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://linkedin.com/in/shanu-kumawat01" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to collaborate and grow together!&lt;/p&gt;

</description>
      <category>nix</category>
      <category>flutter</category>
      <category>tutorial</category>
      <category>development</category>
    </item>
    <item>
      <title>Cloudflare’s Latest Update: A Builder’s Paradise</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Thu, 03 Oct 2024 18:14:58 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/cloudflares-latest-update-a-builders-paradise-56ml</link>
      <guid>https://forem.com/shanu-kumawat/cloudflares-latest-update-a-builders-paradise-56ml</guid>
      <description>&lt;p&gt;Cloudflare's Builder Day 2024 was packed with excitement as they announced 18 big updates to their Workers platform, all inspired by direct feedback from developers. If you're a developer or tech enthusiast, this update makes Cloudflare the go-to place for building scalable, fast, and secure applications. Let’s dive into some of the juiciest new features, changes, and improvements!&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview: What’s New?
&lt;/h2&gt;

&lt;p&gt;Cloudflare continues to push the envelope with updates that touch every aspect of the developer experience. From improved Node.js compatibility to persistent logging and free image optimization, Cloudflare is reshaping what’s possible on its platform. Here are the highlights:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Persistent Logs&lt;/strong&gt;: Keep your Worker logs, and search, filter, or query them directly from the Cloudflare dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hyperdrive&lt;/strong&gt;: Securely connect Workers to private databases using Cloudflare Tunnels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static Asset Hosting&lt;/strong&gt;: Serve static HTML, CSS, and JavaScript right from your Workers, and deploy popular frameworks like Next.js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improved Node.js Compatibility&lt;/strong&gt;: Use more NPM packages with improved support for Node.js APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare Queues&lt;/strong&gt;: Now in GA with higher throughput and more concurrency limits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare Images&lt;/strong&gt;: Image optimization now free for all, with up to 5,000 transformations a month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gradual Deployments&lt;/strong&gt;: Slowly roll out your updates, minimizing downtime risk.&lt;/p&gt;

&lt;p&gt;Let’s break down some of these game-changing updates!&lt;/p&gt;




&lt;h2&gt;
  
  
  Persistent Logs: Track Everything with Ease
&lt;/h2&gt;

&lt;p&gt;Logging is a crucial part of troubleshooting and performance tuning, and Cloudflare is making it easier than ever. Persistent Logs allow you to retain logs from your Workers and view them directly on your dashboard.&lt;/p&gt;

&lt;p&gt;Now, with just two lines in your wrangler.toml, you can have full visibility into your Worker’s behavior, errors, and more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[observability]
enabled = true

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

&lt;/div&gt;



&lt;p&gt;This is a huge leap forward for building smarter, data-driven applications on the platform. You can even filter logs based on specific events or errors, helping you spot problems faster!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hyperdrive: Connecting to Private Databases
&lt;/h2&gt;

&lt;p&gt;Ever wanted to connect your Worker to a private, VPC-isolated database? Hyperdrive is here to save the day! Cloudflare Tunnels and Access now let you securely connect Workers to databases hidden in private networks.&lt;/p&gt;

&lt;p&gt;Whether you're using Amazon RDS, Google Cloud SQL, or Azure Database, you can accelerate queries using Cloudflare’s network—without sacrificing security. This is perfect for developers building full-stack applications, bringing regional databases closer to end users and optimizing connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js on Workers: Unleashing OpenNext
&lt;/h2&gt;

&lt;p&gt;Cloudflare’s collaboration with OpenNext means you can now deploy Next.js apps directly on Workers. Powered by the new Node.js compatibility layer, this update is a game-changer for web developers. It supports Incremental Static Regeneration (ISR), custom error pages, and more!&lt;/p&gt;

&lt;p&gt;No longer tied to specific platforms, you now have the freedom to deploy across any cloud provider using this open-source framework. Talk about flexibility!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloudflare Queues: Event-Driven Just Got Faster
&lt;/h2&gt;

&lt;p&gt;Queues have officially gone GA (General Availability), and they're better than ever! With new higher throughput (5,000 messages per second!) and up to 250 concurrent consumers, Queues allow you to create event-driven applications that scale seamlessly. You can decouple microservices, improving performance and making your systems more fault-tolerant.&lt;/p&gt;

&lt;p&gt;Want to schedule delayed messages or optimize API rate limits? Cloudflare Queues make this possible, all while reducing invocation costs. Now you can create efficient workflows that handle massive volumes of data in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free Image Optimization for Everyone!
&lt;/h2&gt;

&lt;p&gt;Here’s some news for all you performance junkies: Cloudflare Images is now available for free! With up to 5,000 transformations per month, you can ensure your images are perfectly optimized for any browser or device without breaking a sweat.&lt;/p&gt;

&lt;p&gt;By transforming images dynamically based on request, you get blazing-fast page load speeds and lower data usage. Whether it’s resizing, format conversion, or cropping, Cloudflare Images ensures that your images are a breeze to work with—no subscription required.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for Builders?
&lt;/h2&gt;

&lt;p&gt;Cloudflare’s commitment to making the web faster and more developer-friendly is clear with these updates. Whether you're working on personal projects or enterprise-grade applications, Cloudflare is making it easier to scale, secure, and optimize your services.&lt;/p&gt;

&lt;p&gt;To top it all off, they’re offering $250,000 in credits for qualified startups building on their platform. This is your chance to build the next big thing without the headache of infrastructure management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to Dive In?
&lt;/h2&gt;

&lt;p&gt;All these updates are live right now! Whether you’re deploying a Next.js app, connecting to a private database, or optimizing your site’s images, Cloudflare’s platform is designed to help you move faster and more efficiently than ever before.&lt;/p&gt;

&lt;p&gt;For a deeper dive, watch the Builder Day 2024 stream, or check out their developer documentation to start building!&lt;/p&gt;

&lt;p&gt;And that’s a wrap on Cloudflare’s latest and greatest. What will you build next?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Getting Started with pyenv: A Must-Have Tool for Python Development</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Sat, 24 Aug 2024 20:36:15 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/getting-started-with-pyenv-a-must-have-tool-for-python-development-1d3j</link>
      <guid>https://forem.com/shanu-kumawat/getting-started-with-pyenv-a-must-have-tool-for-python-development-1d3j</guid>
      <description>&lt;h2&gt;
  
  
  What is pyenv, and Why Do You Need It?
&lt;/h2&gt;

&lt;p&gt;pyenv is a simple yet powerful tool that allows you to manage multiple Python versions on your system. As a Python developer, you often need to work on different projects that require different Python versions. Manually managing these versions can be cumbersome and prone to errors. This is where pyenv comes in, making it easy to switch between Python versions, ensuring that your projects are always running on the correct version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use pyenv?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Version Management: Install and switch between different Python versions effortlessly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Project Isolation: Ensure that each project uses the correct Python version, avoiding compatibility issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flexibility: Easily test your code on multiple Python versions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've ever faced issues with version conflicts or had to work with both Python 2.x and 3.x on the same machine, you'll appreciate how pyenv simplifies your development workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating pyenv with Poetry
&lt;/h2&gt;

&lt;p&gt;pyenv works exceptionally well with Poetry, a tool that manages dependencies and Python environments. If you're already familiar with Poetry (and if you aren't, check out my article on &lt;a href="https://dev.to/shanu-kumawat/poetry-simplifying-python-dependency-management-on-linux-3pfb"&gt;getting started with Poetry&lt;/a&gt;), you'll find that combining it with pyenv gives you even more control over your projects.&lt;/p&gt;

&lt;p&gt;When you create a new project with Poetry, it automatically uses the Python version that pyenv has set for the directory. This ensures that your project dependencies are managed in an environment that matches your project's requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing pyenv
&lt;/h2&gt;

&lt;p&gt;Let's start by installing pyenv. The installation process varies depending on your operating system.&lt;/p&gt;

&lt;h3&gt;
  
  
  On macOS
&lt;/h3&gt;

&lt;p&gt;Using Homebrew:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;To avoid them accidentally linking against a Pyenv-provided Python, add the following line into your interactive shell's configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bash/Zsh:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;brew&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'env PATH="${PATH//$(pyenv root)\/shims:/}" brew'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Fish:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;brew&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"env PATH=(string replace (pyenv root)/shims '' &lt;/span&gt;&lt;span class="se"&gt;\"\$&lt;/span&gt;&lt;span class="s2"&gt;PATH&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;) brew"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  On Linux
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Using curl:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://pyenv.run | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, add the following to your shell configuration file (e.g., .bashrc, .zshrc):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.pyenv/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pyenv init -&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pyenv virtualenv-init -&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Using Package Manager
On Arch Linux it can be installed with the help of pacman
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; pyenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;add the commands to ~/.bashrc by running the following in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PYENV_ROOT="$HOME/.pyenv"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'command -v pyenv &amp;gt;/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'eval "$(pyenv init -)"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Zsh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PYENV_ROOT="$HOME/.pyenv"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'[[ -d $PYENV_ROOT/bin ]] &amp;amp;&amp;amp; export PATH="$PYENV_ROOT/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'eval "$(pyenv init -)"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Fish:&lt;br&gt;
If you have Fish 3.2.0 or newer, execute this interactively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-Ux&lt;/span&gt; PYENV_ROOT &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.pyenv
fish_add_path &lt;span class="nv"&gt;$PYENV_ROOT&lt;/span&gt;/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, execute the snippet below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-Ux&lt;/span&gt; PYENV_ROOT &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.pyenv
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; fish_user_paths &lt;span class="nv"&gt;$PYENV_ROOT&lt;/span&gt;/bin &lt;span class="nv"&gt;$fish_user_paths&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, add this to &lt;code&gt;~/.config/fish/config.fish&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pyenv init - | &lt;span class="nb"&gt;source&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more detail, check out their &lt;a href="https://github.com/pyenv/pyenv?tab=readme-ov-file#installation" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Pyenv
&lt;/h2&gt;

&lt;p&gt;1) Checking the Python Version&lt;/p&gt;

&lt;p&gt;To check the Python version currently in use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ pyenv versions
* system (set by /home/shanu/.pyenv/version)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Installing Python Versions&lt;/p&gt;

&lt;p&gt;With pyenv, you can install any version of Python easily:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;After installing a python version, it can be set globally or locally for a project&lt;/p&gt;

&lt;p&gt;3) Setting the Global Python Version &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Not Recommended, may cause problems with your system&lt;/code&gt;&lt;br&gt;
You can set a global Python version that will be used by default across your system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pyenv global 3.10.6 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) Setting the Local Python Version&lt;/p&gt;

&lt;p&gt;You can also set a local Python version for a specific project directory. This version will override the global version when you are in that directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ pyenv &lt;span class="nb"&gt;local &lt;/span&gt;3.8.10

❯ pyenv versions
  system
&lt;span class="k"&gt;*&lt;/span&gt; 3.11.9 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set &lt;/span&gt;by /home/shanu/test_folder/.python-version&lt;span class="o"&gt;)&lt;/span&gt;

❯ python &lt;span class="nt"&gt;-V&lt;/span&gt;
Python 3.11.9 &lt;span class="o"&gt;(&lt;/span&gt;my global version is 3.12.5&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To unset it, just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ pyenv local --unset

❯ pyenv versions
* system (set by /home/shanu/.pyenv/version)
  3.11.9

❯ python -V
Python 3.12.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5) Uninstalling Python Versions&lt;/p&gt;

&lt;p&gt;To uninstall a Python version that is no longer needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pyenv uninstall 3.11.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Pyenv is an invaluable tool for Python developers, especially when used in conjunction with Poetry. By managing Python versions effortlessly, it allows you to focus on writing code rather than worrying about version conflicts. Give it a try in your next Python project!&lt;/p&gt;

</description>
      <category>python</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>linux</category>
    </item>
    <item>
      <title>Poetry Beginner's Guide: Simplifying Python Dependency Management on Linux 🐍📜</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Thu, 01 Aug 2024 16:58:54 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/poetry-simplifying-python-dependency-management-on-linux-3pfb</link>
      <guid>https://forem.com/shanu-kumawat/poetry-simplifying-python-dependency-management-on-linux-3pfb</guid>
      <description>&lt;h2&gt;
  
  
  The Need for Virtual Environments and Reproducibility
&lt;/h2&gt;

&lt;p&gt;Python projects often rely on numerous external libraries and packages. As projects grow and evolve, managing these dependencies can become complex. Two critical aspects of Python development are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Virtual Environments: Isolated spaces that keep project dependencies separate from system-wide Python installations, allowing you to create a virtual environment for your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reproducibility: Ensuring that a project can be easily set up and run consistently across different machines or environments is crucial for successful development and deployment of Python packages.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Traditional tools like &lt;code&gt;venv&lt;/code&gt; and &lt;code&gt;pip&lt;/code&gt; have long been used for these purposes, but they often require multiple steps and manual intervention. This is where Poetry comes in, offering a more streamlined and robust solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Choose Poetry?
&lt;/h2&gt;

&lt;p&gt;Poetry offers several advantages over traditional tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Simplified Workflow: Combines dependency management, packaging, and publishing in one tool, making it easier to install dependencies for your poetry project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependency Resolution: Automatically resolves dependencies and potential conflicts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reproducible Builds: Ensures consistent environments across different machines by using the same Python version and dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lock File: Generates a lock file for exact version control of all dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Project Isolation: Creates and manages virtual environments automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Intuitive Commands: Offers a user-friendly CLI for common tasks.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Installing and Setting Up Poetry
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sSL https://install.python-poetry.org | python3 -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After installation, add Poetry to your PATH by adding the following line to your shell configuration file (e.g., &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt;):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export PATH="$HOME/.local/bin:$PATH"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Restart your terminal or run &lt;code&gt;source ~/.bashrc&lt;/code&gt;  You can use the appropriate file to apply the changes to your project setup.&lt;/p&gt;

&lt;p&gt;Verify the installation by running:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Enable tab completion for Bash, Fish, or Zsh
&lt;/h3&gt;

&lt;p&gt;poetry supports generating completion scripts for Bash, Fish, and Zsh, making it easier to use poetry commands in different environments.&lt;/p&gt;
&lt;h4&gt;
  
  
  Bash
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry completions bash &amp;gt;&amp;gt; ~/.bash_completion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Fish
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry completions fish &amp;gt; ~/.config/fish/completions/poetry.fish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Zsh
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry completions zsh &amp;gt; ~/.zfunc/_poetry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Using Poetry
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Creating a New Project
&lt;/h3&gt;

&lt;p&gt;To create a new Python project with Poetry:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry new my-project
cd my-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This creates a new directory with a basic project structure, including a &lt;code&gt;pyproject.toml&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Dependencies
&lt;/h3&gt;

&lt;p&gt;To add a new dependency, use the command &lt;code&gt;poetry add \&lt;/code&gt; to install the package directly.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry add requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This adds the package to your &lt;code&gt;pyproject.toml&lt;/code&gt; file and installs it in the virtual environment managed by poetry for your current project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing Dependencies
&lt;/h3&gt;

&lt;p&gt;View installed packages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Update all packages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Remove a package:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry remove requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Running Scripts
&lt;/h3&gt;

&lt;p&gt;Execute Python scripts within the project's virtual environment:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry run python your_script.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Managing the Virtual Environment
&lt;/h3&gt;

&lt;p&gt;Activate the virtual environment:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Deactivate it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Building and Publishing
&lt;/h3&gt;

&lt;p&gt;Build your project using poetry to ensure compatibility with different Python versions.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Publish to PyPI:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Exporting Requirements
&lt;/h3&gt;

&lt;p&gt;Generate a &lt;code&gt;requirements.txt&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    poetry export -f requirements.txt --output requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Poetry simplifies Python project management by providing a unified tool for dependency management, virtual environments, and packaging. Its intuitive interface and powerful features make it an excellent choice for Python developers looking to streamline their workflow and ensure project reproducibility.&lt;/p&gt;

&lt;p&gt;We're a place where coders share, stay up-to-date and grow their careers.&lt;/p&gt;

</description>
      <category>python</category>
      <category>productivity</category>
      <category>linux</category>
      <category>management</category>
    </item>
    <item>
      <title>Boost Your Linux Productivity: Remapping Useless Keys with Kanata ⚡</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Sun, 28 Jul 2024 05:07:01 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/boost-your-linux-productivity-remapping-useless-keys-with-kanata-3ih5</link>
      <guid>https://forem.com/shanu-kumawat/boost-your-linux-productivity-remapping-useless-keys-with-kanata-3ih5</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: The Useless Caps Lock Key
&lt;/h2&gt;

&lt;p&gt;We've all been there - accidentally hitting the Caps Lock key and suddenly shouting at our screens in ALL CAPS. This relic from the typewriter era takes up prime keyboard real estate but offers little value in return. What if we could transform this useless key into a productivity powerhouse?&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Kanata: Your Key Remapping Solution
&lt;/h2&gt;

&lt;p&gt;Kanata is a powerful, cross-platform key remapper written in Rust. It allows you to redefine your keyboard layout at a low level, opening up a world of possibilities for customization and efficiency. With Kanata, we can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remap the Caps Lock key to serve dual purposes:

&lt;ul&gt;
&lt;li&gt;Tap for Escape (perfect for Neovim users)&lt;/li&gt;
&lt;li&gt;Hold for Control (easier access to common shortcuts)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Transform the Tab key into a symbol layer accessor:

&lt;ul&gt;
&lt;li&gt;Tap for normal Tab functionality&lt;/li&gt;
&lt;li&gt;Hold to access a custom layer of symbols and navigation keys&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's dive into how we can achieve this setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install Kanata
&lt;/h3&gt;

&lt;p&gt;First, you'll need to install Kanata. The installation process varies depending on your Linux distribution. Check the &lt;a href="https://github.com/jtroo/kanata" rel="noopener noreferrer"&gt;official Kanata repository&lt;/a&gt; for detailed installation instructions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Create Your Kanata Configuration File
&lt;/h3&gt;

&lt;p&gt;Create a new file named &lt;code&gt;kanata.kbd&lt;/code&gt; in your home directory. This is where we'll define our custom keyboard layout.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Define Your Source Layer
&lt;/h3&gt;

&lt;p&gt;Start by defining your source layer. This represents your physical keyboard layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(defsrc
esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12
grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
tab  q    w    e    r    t    y    u    i    o    p    [    ]    
caps a    s    d    f    g    h    j    k    l    ;    '    ret
lsft z    x    c    v    b    n    m    ,    .    /    rsft
lctl lmet lalt           spc            ralt rmet rctl
)

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

&lt;/div&gt;



&lt;p&gt;This layout represents a standard QWERTY keyboard. Adjust it if your physical layout differs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Create Custom Aliases
&lt;/h3&gt;

&lt;p&gt;Next, we'll define aliases for our custom key behaviors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(defalias
cec (tap-hold 200 200 esc lctl)
sym (tap-hold 200 200 tab (layer-toggle symbols))
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what these aliases do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cec&lt;/code&gt;: Caps as Escape (tap) and Control (hold)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sym&lt;/code&gt;: Tab as normal Tab (tap) and Symbol layer toggle (hold)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The numbers (200 200) represent the tap and hold timeouts in milliseconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Define Your Default Layer
&lt;/h3&gt;

&lt;p&gt;Now, let's create our default layer, incorporating our new aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(deflayer default
esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12
grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
@sym q    w    e    r    t    y    u    i    o    p    [    ]    
@cec a    s    d    f    g    h    j    k    l    ;    '    ret
lsft z    x    c    v    b    n    m    ,    .    /    rsft
lctl lmet lalt           spc            ralt rmet rctl
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how we've replaced &lt;code&gt;tab&lt;/code&gt; with &lt;code&gt;@sym&lt;/code&gt; and &lt;code&gt;caps&lt;/code&gt; with &lt;code&gt;@cec&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Create Your Symbol Layer
&lt;/h3&gt;

&lt;p&gt;Finally, let's define our symbol layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(deflayer symbols
  _    _    _    _    _    _    _    _    _    _    _    _    _
  _    S-1  S-2  S-3  S-4  S-5  S-6  S-7  S-8  S-9  S-0  _    _    _
  _    S-5  S-6  S-7  S-8  _    _    _    _    S-9  S-0  _    _    _
  _    _    _    del  _    _    left down up   rght _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

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

&lt;/div&gt;



&lt;p&gt;In this layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;S-&lt;/code&gt; represents Shift, so &lt;code&gt;S-1&lt;/code&gt; outputs &lt;code&gt;!&lt;/code&gt;, &lt;code&gt;S-2&lt;/code&gt; outputs &lt;code&gt;@&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;We've added arrow key functionality to &lt;code&gt;h&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt; for vim-style navigation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;del&lt;/code&gt; is now easily accessible on the home row&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So at the end you config should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(defsrc
  esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

(defalias
  cec (tap-hold 200 200 esc lctl)
  sym (tap-hold 200 200 tab (layer-toggle symbols))
)

(deflayer default
  esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  @sym q    w    e    r    t    y    u    i    o    p    [    ]    \
  @cec a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

(deflayer symbols
  _    _    _    _    _    _    _    _    _    _    _    _    _
  _    S-1  S-2  S-3  S-4  S-5  S-6  S-7  S-8  S-9  S-0  _    _    _
  _    S-5  S-6  S-7  S-8  _    _    _    _    S-9  S-0  _    _    _
  _    _    _    del  _    _    left down up   rght _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _              _              _    _    _
)

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Run Kanata
&lt;/h3&gt;

&lt;p&gt;Save your &lt;code&gt;kanata.kbd&lt;/code&gt; file and run Kanata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kanata &lt;span class="nt"&gt;-c&lt;/span&gt; /path/to/your/kanata.kbd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Instructions
&lt;/h2&gt;

&lt;p&gt;In Linux, kanata needs to be able to access the input and uinput subsystem to inject events. To do this, your user needs to have permissions. Follow the steps in this page to obtain user permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. If the uinput group does not exist, create a new group
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;groupadd uinput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Add your user to the input and the uinput group
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; input &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; uinput &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure that it's effective by running &lt;code&gt;groups&lt;/code&gt;. You might have to logout and login.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Make sure the uinput device file has the right permissions.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Create a new file:
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;/etc/udev/rules.d/99-input.rules&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Insert the following in the code
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KERNEL&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s2"&gt;"uinput"&lt;/span&gt;, &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0660"&lt;/span&gt;, &lt;span class="nv"&gt;GROUP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"uinput"&lt;/span&gt;, OPTIONS+&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"static_node=uinput"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Machine reboot or run this to reload
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;udevadm control &lt;span class="nt"&gt;--reload-rules&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;udevadm trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Verify settings by following command:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /dev/uinput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Output:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crw-rw---- 1 root &lt;span class="nb"&gt;date &lt;/span&gt;uinput /dev/uinput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Make sure the uinput drivers are loaded
&lt;/h3&gt;

&lt;p&gt;You may need to run this command whenever you start kanata for the first time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo modprobe uinput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5a. To create and enable a systemd daemon service
&lt;/h3&gt;

&lt;p&gt;Run this command first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.config/systemd/user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add this to: &lt;code&gt;~/.config/systemd/user/kanata.service&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;Unit]
&lt;span class="nv"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Kanata keyboard remapper
&lt;span class="nv"&gt;Documentation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://github.com/jtroo/kanata

&lt;span class="o"&gt;[&lt;/span&gt;Service]
&lt;span class="nv"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin:/usr/local/sbin:/usr/bin:/bin
&lt;span class="nv"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DISPLAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;:0
&lt;span class="nv"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;simple
&lt;span class="nv"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin/sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'exec $$(which kanata) --cfg $${HOME}/.config/kanata/config.kbd'&lt;/span&gt;
&lt;span class="nv"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;no

&lt;span class="o"&gt;[&lt;/span&gt;Install]
&lt;span class="nv"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;default.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to update the executable location for sh in the snippet above.&lt;br&gt;
This would be the line starting with &lt;code&gt;ExecStart=/usr/bin/sh -c&lt;/code&gt;.&lt;br&gt;
You can check the executable path with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;which sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; daemon-reload
systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nb"&gt;enable &lt;/span&gt;kanata.service
systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; start kanata.service
systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; status kanata.service   &lt;span class="c"&gt;# check whether the service is running&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;With this setup, you've transformed your Caps Lock and Tab keys into productivity powerhouses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tap Caps Lock for Escape, hold for Control&lt;/li&gt;
&lt;li&gt;Tap Tab for normal Tab, hold to access your symbol layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This configuration is especially powerful for Neovim users, providing quick access to Escape, and for developers who frequently use symbols and navigation keys.&lt;/p&gt;

&lt;p&gt;Remember, this is just the beginning. Kanata offers a wealth of customization options. Experiment, refine, and create a keyboard layout that perfectly suits your workflow.&lt;/p&gt;

&lt;p&gt;Happy typing!&lt;/p&gt;

&lt;h3&gt;
  
  
  About the Author
&lt;/h3&gt;

&lt;p&gt;Hi, I'm Shanu Kumawat, a Flutter developer passionate about crafting seamless and beautiful mobile applications. Currently, I'm diving deeper into expanding my tech stack by learning Elixir and Phoenix, embracing the world of functional programming and scalable web development.  &lt;/p&gt;

&lt;p&gt;When I'm not coding, I enjoy exploring innovative technologies and sharing knowledge with the community. Connect with me on &lt;a href="https://github.com/Shanu-Kumawat" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://twitter.com/Shanu_Kumawat01" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://linkedin.com/in/shanu-kumawat01" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to collaborate and grow together!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>keyboard</category>
    </item>
    <item>
      <title>Getting Started with llama.cpp on Linux! (Updated+) 🦙💻</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Tue, 19 Mar 2024 17:58:06 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/getting-started-with-lammacpp-on-arch-linux-58nc</link>
      <guid>https://forem.com/shanu-kumawat/getting-started-with-lammacpp-on-arch-linux-58nc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;llama.cpp is a wonderful project for running llms locally on your system. It is lightweight and provide state-of-the-art performance. It comes with GPU offloading support, allowing you to use your GPU capabilities to run llms. &lt;/p&gt;

&lt;p&gt;I am personally using it for running llms on my arch system and I found it better than ollama in terms of performance, while trying to set this it up, I found their documentation confusing and there were no guides specifically for arch linux, that's why I decided to write an article after figuring things out.&lt;br&gt;
So, lets gets started with it.&lt;/p&gt;

&lt;p&gt;So, there are 4 ways to use it :-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method 1: Clone this repository and build locally, see how to Build&lt;/li&gt;
&lt;li&gt;Method 2: If you are using macOS or Linux, you can install llama.cpp via brew, flox or nix&lt;/li&gt;
&lt;li&gt;Method 3: Use a Docker image, see documentation for Docker&lt;/li&gt;
&lt;li&gt;Method 4: Download pre-built binary from &lt;a href="https://github.com/ggerganov/llama.cpp/releases" rel="noopener noreferrer"&gt;releases&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Guide
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Method 1
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;let's start by cloning the repo and cd into that
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;After that we need to build this, it can be done by using &lt;code&gt;make&lt;/code&gt;, but like me if you have Nvidia GPU then for using it to for offloading you will need to build it with cuBLAS and for that we need cuda toolkit, You can download it from your Linux distro's package manager. 
(e.g. &lt;code&gt;apt install nvidia-cuda-toolkit&lt;/code&gt;)
here I am using AUR helper, you can also install it manually.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;paru -S cuda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now to build project with cuda run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make GGML_CUDA=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;CMake&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake -B build -DGGML_CUDA=ON
cmake --build build --config Release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might take a while, after build is finished we can now finally run llms.&lt;/p&gt;

&lt;p&gt;The environment variable &lt;code&gt;GGML_CUDA_ENABLE_UNIFIED_MEMORY=1&lt;/code&gt; can be used to enable unified memory on Linux. This allows swapping to system RAM instead of crashing when the GPU VRAM is exhausted&lt;/p&gt;




&lt;h3&gt;
  
  
  Method 2
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Homebrew
&lt;/h4&gt;

&lt;p&gt;On Mac and Linux, the homebrew package manager can be used via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;llama.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The formula is automatically updated with new &lt;code&gt;llama.cpp&lt;/code&gt; releases. More info: &lt;a href="https://github.com/ggerganov/llama.cpp/discussions/7668" rel="noopener noreferrer"&gt;https://github.com/ggerganov/llama.cpp/discussions/7668&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Nix
&lt;/h4&gt;

&lt;p&gt;On Mac and Linux, the Nix package manager can be used via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nix profile &lt;span class="nb"&gt;install &lt;/span&gt;nixpkgs#llama-cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For flake enabled installations.&lt;/p&gt;

&lt;p&gt;Or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nix-env &lt;span class="nt"&gt;--file&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;nixpkgs&amp;gt;'&lt;/span&gt; &lt;span class="nt"&gt;--install&lt;/span&gt; &lt;span class="nt"&gt;--attr&lt;/span&gt; llama-cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For non-flake enabled installations.&lt;/p&gt;

&lt;p&gt;This expression is automatically updated within the &lt;a href="https://github.com/NixOS/nixpkgs/blob/nixos-24.05/pkgs/by-name/ll/llama-cpp/package.nix#L164" rel="noopener noreferrer"&gt;nixpkgs repo&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Flox
&lt;/h4&gt;

&lt;p&gt;On Mac and Linux, Flox can be used to install llama.cpp within a Flox environment via&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Flox follows the nixpkgs build of llama.cpp.&lt;/p&gt;




&lt;h3&gt;
  
  
  Method 3
&lt;/h3&gt;

&lt;p&gt;Follow the documentation &lt;a href="https://github.com/ggerganov/llama.cpp/blob/master/docs/docker.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;
It's well documented, you will not have problem following it.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

&lt;p&gt;In llama.cpp folder you will find a executable named &lt;code&gt;llama-server&lt;/code&gt; and &lt;code&gt;llama-cli&lt;/code&gt;&lt;br&gt;
which can be used to run the model&lt;br&gt;
for cli mode just run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./llama-cli -m path-to-model -n no-of-tokens -ngl no-of-layers-to-offload-to-gpu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for server run this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./llama-server -m path-to-model -n no-of-tokens -ngl no-of-layers-to-offload-to-gpu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now open your browser and in the URL section type &lt;a href="http://localhost:8080/" rel="noopener noreferrer"&gt;http://localhost:8080/&lt;/a&gt; and a web UI will appear.&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%2Fihjjr8tmfkgk69jmdlj2.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%2Fihjjr8tmfkgk69jmdlj2.png" alt="lamma web ui" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can have fun with your local llm.&lt;br&gt;
Hope you will find this article helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  About the Author
&lt;/h3&gt;

&lt;p&gt;Hi, I'm Shanu Kumawat, a Flutter developer passionate about crafting seamless and beautiful mobile applications. Currently, I'm diving deeper into expanding my tech stack by learning Elixir and Phoenix, embracing the world of functional programming and scalable web development.  &lt;/p&gt;

&lt;p&gt;When I'm not coding, I enjoy exploring innovative technologies and sharing knowledge with the community. Connect with me on &lt;a href="https://github.com/Shanu-Kumawat" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://twitter.com/Shanu_Kumawat01" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://linkedin.com/in/shanu-kumawat01" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to collaborate and grow together!&lt;/p&gt;

</description>
      <category>llm</category>
      <category>llama</category>
      <category>arch</category>
      <category>guide</category>
    </item>
    <item>
      <title>Ten Must Repos For A Dev !! 🔑📂</title>
      <dc:creator>Shanu Kumawat</dc:creator>
      <pubDate>Wed, 07 Feb 2024 15:45:38 +0000</pubDate>
      <link>https://forem.com/shanu-kumawat/top-10-github-repositories-every-developer-should-bookmark-in-2024-l6a</link>
      <guid>https://forem.com/shanu-kumawat/top-10-github-repositories-every-developer-should-bookmark-in-2024-l6a</guid>
      <description>&lt;p&gt;In the vast ocean of code that is GitHub, finding the right repositories to propel your development journey can feel like searching for treasure on a deserted island. Worry not, fellow coders, for I have unearthed 10 hidden gems that will equip you with knowledge, challenge your skills, and spark your creativity.&lt;br&gt;
1) The Algorithms: Hone your problem-solving prowess with this comprehensive collection of algorithms and data structures implemented in various programming languages. From classic sorting algorithms to graph theory marvels, this repository is your one-stop shop for algorithmic enlightenment. (&lt;a href="https://github.com/TheAlgorithms" rel="noopener noreferrer"&gt;https://github.com/TheAlgorithms&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0z2ru1tddo5ru90jdo0.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%2Ff0z2ru1tddo5ru90jdo0.png" alt=" " width="280" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) 100 Days of ML Code: Embark on a 100-day journey into the fascinating world of machine learning with this structured curriculum. Packed with bite-sized coding challenges and real-world projects, this repository will transform you from a coding novice to a confident ML enthusiast. (&lt;a href="https://github.com/Avik-Jain/100-Days-Of-ML-Code" rel="noopener noreferrer"&gt;https://github.com/Avik-Jain/100-Days-Of-ML-Code&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx31v73ukolh5cpwnz05h.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%2Fx31v73ukolh5cpwnz05h.png" alt=" " width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) Project-Based Learning: Break free from the shackles of theoretical frameworks and dive headfirst into practical projects. This repository curates a diverse range of project ideas, from building basic web applications to creating intricate 3D games, all designed to solidify your understanding through hands-on experience. (&lt;a href="https://github.com/practical-tutorials/project-based-learning" rel="noopener noreferrer"&gt;https://github.com/practical-tutorials/project-based-learning&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5anjpa3lezhuhr7vqe1.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%2Fu5anjpa3lezhuhr7vqe1.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) Coding Interview University: Conquer the dreaded coding interview with this battle-tested arsenal of algorithms, data structures, and interview prep strategies. Sharpen your problem-solving skills, optimize your coding efficiency, and ace those technical assessments with this invaluable resource. (&lt;a href="https://github.com/jwasham/coding-interview-university" rel="noopener noreferrer"&gt;https://github.com/jwasham/coding-interview-university&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqczfmtuej2joa0tt1bi.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%2Fcqczfmtuej2joa0tt1bi.png" alt=" " width="640" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) Open Source University (OSSU): Dive deep into the world of open-source software with curated roadmaps for mastering in-demand programming languages, frameworks, and tools. This repository provides a structured learning path for contributing to open-source projects and becoming a valuable member of the developer community. (&lt;a href="https://github.com/ossu" rel="noopener noreferrer"&gt;https://github.com/ossu&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshn0t236ifmbip4ixa5p.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%2Fshn0t236ifmbip4ixa5p.png" alt=" " width="280" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6) Awesome Python: Embrace the power of Python with this extensive collection of awesome libraries, frameworks, resources, and software. Whether you're a seasoned Pythonista or just starting your journey, this repository is your ultimate guide to maximizing the potential of this versatile language. (&lt;a href="https://github.com/vinta/awesome-python" rel="noopener noreferrer"&gt;https://github.com/vinta/awesome-python&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1gz7p3mfwptcud29sh9.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%2Ff1gz7p3mfwptcud29sh9.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7) Sindresorhus's Awesome List: Get lost in a rabbit hole of curated awesomeness with this treasure trove of awesome lists for everything tech-related. From libraries and frameworks to blogs and podcasts, this repository is a gateway to discovering hidden gems and expanding your technological horizons. (&lt;a href="https://github.com/topics/awesome" rel="noopener noreferrer"&gt;https://github.com/topics/awesome&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjbsyri7k7xs21qhjdcv.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%2Fkjbsyri7k7xs21qhjdcv.png" alt=" " width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8) Build Your Own X: Unleash your inner inventor and embark on a journey of self-creation with this collection of project ideas for building your own software, tools, and even operating systems. Fuel your entrepreneurial spirit and learn valuable engineering principles by bringing your innovative ideas to life. (&lt;a href="https://github.com/codecrafters-io/build-your-own-x" rel="noopener noreferrer"&gt;https://github.com/codecrafters-io/build-your-own-x&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczbf8mi3ahv800pspo52.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%2Fczbf8mi3ahv800pspo52.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;9) 100 Days, 100 Projects: Challenge yourself to a marathon of creativity with this ambitious collection of 100 project ideas to be completed in 100 days. From web development to mobile apps, data visualization to game development, this repository will push your boundaries and keep you coding through the night. (&lt;a href="https://github.com/topics/100-days-of-code" rel="noopener noreferrer"&gt;https://github.com/topics/100-days-of-code&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3beeggupso5qxgnmc8w.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%2Fx3beeggupso5qxgnmc8w.png" alt=" " width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;10) You Don't Need: Break free from the shackles of third-party dependencies and rediscover the joy of building things from scratch. This repository is a collection of resources and tutorials on how to build your own essential tools and libraries, fostering self-reliance and a deeper understanding of how things work. (&lt;a href="https://github.com/you-dont-need" rel="noopener noreferrer"&gt;https://github.com/you-dont-need&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqhewzgme6dgm2wvtq4o.jpg" 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%2Fqqhewzgme6dgm2wvtq4o.jpg" alt=" " width="280" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember, these repositories are just the tip of the iceberg. Dive deep, explore, experiment, and most importantly, have fun! The GitHub universe is waiting to be conquered, and these gems are your map to coding treasure. So, what are you waiting for? Start exploring and unleash your inner coding superhero!&lt;/p&gt;

</description>
      <category>github</category>
      <category>resources</category>
      <category>useful</category>
      <category>career</category>
    </item>
  </channel>
</rss>
