<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sanjay Kumar Sah</title>
    <description>The latest articles on DEV Community by Sanjay Kumar Sah (@sanjaysah).</description>
    <link>https://dev.to/sanjaysah</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1656931%2F92645e0c-3291-4e97-aa16-b1904ecae286.jpg</url>
      <title>DEV Community: Sanjay Kumar Sah</title>
      <link>https://dev.to/sanjaysah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanjaysah"/>
    <language>en</language>
    <item>
      <title>You Should Own Your UI Components, Not Just Install Them</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Wed, 29 Jul 2026 05:00:03 +0000</pubDate>
      <link>https://dev.to/sanjaysah/you-should-own-your-ui-components-not-just-install-them-bce</link>
      <guid>https://dev.to/sanjaysah/you-should-own-your-ui-components-not-just-install-them-bce</guid>
      <description>&lt;p&gt;One of my favorite ideas behind &lt;code&gt;shadcn/ui&lt;/code&gt; has nothing to do with components. It's about ownership. Unlike most UI libraries, &lt;code&gt;shadcn/ui&lt;/code&gt; doesn't ask you to install a package and hope the maintainers keep it stable forever. Instead, it generates the source code directly into your project.&lt;/p&gt;

&lt;p&gt;Those components become yours. You can edit them. Refactor them. Delete them. There is no vendor lock-in. &lt;/p&gt;

&lt;p&gt;When I started building &lt;strong&gt;&lt;a href="https://github.com/notils/create-notils" rel="noopener noreferrer"&gt;create-notils&lt;/a&gt;&lt;/strong&gt;, I realized this philosophy shouldn't stop at components. It should extend to the entire project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Dependencies vs. Owning Your Code
&lt;/h2&gt;

&lt;p&gt;Most starter kits work like this:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Your application now depends on another package. Every update means waiting for a new release, and every customization risks diverging from upstream. Sometimes you end up wrapping library components just to make them fit your project. Slowly, your application becomes a thin layer around someone else's code.&lt;/p&gt;

&lt;p&gt;There's nothing inherently wrong with this approach, but I wanted something different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Code Is the API
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;create-notils&lt;/code&gt;, the generated project belongs to you. The UI components are copied into your repository. The configuration files are yours. The project structure is yours. Nothing is hidden behind an SDK.&lt;/p&gt;

&lt;p&gt;That means changing a button isn't a breaking change—it's just another Git commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Design System, Multiple Applications
&lt;/h2&gt;

&lt;p&gt;One challenge with monorepos is avoiding duplicated UI code. Instead of installing &lt;code&gt;shadcn/ui&lt;/code&gt; inside every individual application, &lt;code&gt;create-notils&lt;/code&gt; keeps a single, shared design system at the workspace root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/
└── ui/
    ├── components/
    ├── lib/
    └── styles/

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

&lt;/div&gt;



&lt;p&gt;Every application imports components from the exact same package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@notils/ui/components/ui/button&lt;/span&gt;&lt;span class="dl"&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 a new component is added, every application immediately has access to it. There is one source of truth, not three slightly different copies floating around your workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating Isn't a Package Upgrade
&lt;/h2&gt;

&lt;p&gt;One thing I always found awkward about UI libraries is updating them. Usually, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm update some-library

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

&lt;/div&gt;



&lt;p&gt;Then you read the changelog, hope nothing broke, and fix any breaking changes.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;shadcn/ui&lt;/code&gt;, updating is different because you're updating raw source files. In &lt;code&gt;create-notils&lt;/code&gt;, the workflow is intentionally simple. Want to add a component?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun ui:add dialog

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

&lt;/div&gt;



&lt;p&gt;Need to see what changed upstream before you pull it in?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun ui:diff button

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

&lt;/div&gt;



&lt;p&gt;Ready to update?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun ui:update button

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

&lt;/div&gt;



&lt;p&gt;Every change is visible as a normal Git diff. No hidden abstractions. No magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Philosophy Beyond Components
&lt;/h2&gt;

&lt;p&gt;This release made me realize something: the idea of ownership applies to much more than just UI.&lt;/p&gt;

&lt;p&gt;Authentication should live in your repository. Configuration should live in your repository. Database schemas should live in your repository. Generated code should be fully understandable without having to read a framework's internal source code.&lt;/p&gt;

&lt;p&gt;That's the direction I want &lt;code&gt;create-notils&lt;/code&gt; to move toward. I don't want to build a platform that owns your application. I want to build a platform that helps &lt;em&gt;you&lt;/em&gt; own it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 0.2.0 is Live
&lt;/h2&gt;

&lt;p&gt;This release introduces the foundation for that philosophy. Highlights include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interactive project creation:&lt;/strong&gt; Scaffold exactly what you need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monorepo and standalone generation:&lt;/strong&gt; Two outputs from one canonical source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared &lt;code&gt;@notils/ui&lt;/code&gt; package:&lt;/strong&gt; A unified design system for your workspace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in UI commands:&lt;/strong&gt; Add, preview, and update &lt;code&gt;shadcn/ui&lt;/code&gt; components effortlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dedicated developer guide:&lt;/strong&gt; Generated specifically for your new project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better documentation &amp;amp; testing:&lt;/strong&gt; For all generated applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is still early. Authentication, database integration, and additional capabilities are coming in future releases. But the core philosophy is already taking shape: Own your code. Reduce repetitive setup. Spend your time building products instead of rebuilding infrastructure.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>shadcnui</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Opinionated by Design: Why I Chose Sensible Defaults Over Endless Configuration</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Wed, 22 Jul 2026 06:33:14 +0000</pubDate>
      <link>https://dev.to/sanjaysah/opinionated-by-design-why-i-chose-sensible-defaults-over-endless-configuration-4lnm</link>
      <guid>https://dev.to/sanjaysah/opinionated-by-design-why-i-chose-sensible-defaults-over-endless-configuration-4lnm</guid>
      <description>&lt;p&gt;When people hear about a new project scaffolding tool, one of the first questions they ask is:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Can I choose React Query or TanStack Query?"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"What about pnpm instead of Bun?"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"Can I use ESLint instead of Biome?"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"Can I choose Radix instead of Base UI?"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"Can I skip Tailwind?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These are reasonable questions. In fact, I asked myself the same ones while building &lt;strong&gt;&lt;a href="https://github.com/notils/create-notils" rel="noopener noreferrer"&gt;create-notils&lt;/a&gt;&lt;/strong&gt;. My first instinct was to make everything configurable.&lt;/p&gt;

&lt;p&gt;The more I thought about it, the more I realized I was about to build something I didn't actually want to use.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Configuration Trap
&lt;/h2&gt;

&lt;p&gt;Most project generators start simple. Then someone requests another option. Another package manager. Another ORM. Another authentication provider. Another CSS framework. Another UI library.&lt;/p&gt;

&lt;p&gt;Eventually the CLI starts looking 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;? Which package manager?
❯ npm
  pnpm
  yarn
  bun

? Which CSS framework?
? Which ORM?
? Which auth library?
? Which formatter?
? Which icon library?
? Which deployment target?

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

&lt;/div&gt;



&lt;p&gt;It feels flexible. But every new option creates more combinations to support. Five choices in one prompt don't create five possible projects. They multiply with every other prompt. The complexity grows much faster than the number of features.&lt;/p&gt;




&lt;h2&gt;
  
  
  I Built the Tool I Wanted to Use
&lt;/h2&gt;

&lt;p&gt;One thing I've learned from building side projects is this: &lt;strong&gt;the first user should always be yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every project I start today uses almost exactly the same stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js 16&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React 19&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bun&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tailwind CSS v4&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;shadcn/ui&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Base UI&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Biome&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turborepo&lt;/strong&gt; (when needed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wasn't switching between ten different combinations every week. I was rebuilding the same foundation over and over. So instead of asking twenty questions during scaffolding, I decided to optimize for the workflow I actually have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-notils my-app

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

&lt;/div&gt;



&lt;p&gt;A few seconds later, I'm writing features instead of answering prompts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Opinionated Doesn't Mean Closed
&lt;/h2&gt;

&lt;p&gt;There's an important distinction between &lt;strong&gt;opinionated&lt;/strong&gt; and &lt;strong&gt;restrictive&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Some tools hide their implementation behind abstractions. Others generate code you aren't expected to touch. That isn't the direction I wanted.&lt;/p&gt;

&lt;p&gt;Everything &lt;code&gt;create-notils&lt;/code&gt; generates belongs to you. The UI components are source files. The configuration files are yours. The project structure is yours. If you don't like one of my decisions, you can change it immediately.&lt;/p&gt;

&lt;p&gt;There is no vendor lock-in. The CLI gives you a starting point, not a framework you have to live inside forever.&lt;/p&gt;




&lt;h2&gt;
  
  
  Defaults Should Be Battle-Tested
&lt;/h2&gt;

&lt;p&gt;Every opinion in &lt;code&gt;create-notils&lt;/code&gt; comes from building real projects.&lt;/p&gt;

&lt;p&gt;I didn't choose Bun because it was trendy; I chose it because it's the package manager and runtime I use every day. I didn't choose Biome because it's newer than ESLint; I chose it because having one fast tool for linting and formatting simplified my workflow.&lt;/p&gt;

&lt;p&gt;The same applies to Tailwind CSS v4, shadcn/ui, Base UI, and the rest of the stack. The goal isn't to pick the newest tools. The goal is to reduce decisions that I already know the answer to.&lt;/p&gt;




&lt;h2&gt;
  
  
  Configuration Can Come Later
&lt;/h2&gt;

&lt;p&gt;One question I get is: &lt;em&gt;"What if someone doesn't want your stack?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's a fair point. The answer is: &lt;strong&gt;not every problem needs to be solved in version 0.1.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As &lt;code&gt;create-notils&lt;/code&gt; evolves, it will become more modular. Instead of exposing every decision through dozens of prompts, I'm exploring a different direction: generate a solid foundation first, then let developers add capabilities as they need them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Database&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Payments&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those additions can evolve independently without turning the initial project creation into an interrogation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Optimizing for Momentum
&lt;/h2&gt;

&lt;p&gt;One of the biggest costs of starting a new project isn't writing code. It's context switching.&lt;/p&gt;

&lt;p&gt;Every prompt interrupts momentum. Every configuration choice forces another decision before you've even written your first component. I'd rather spend those first ten minutes building a homepage than deciding which formatter to use.&lt;/p&gt;

&lt;p&gt;That's why &lt;code&gt;create-notils&lt;/code&gt; intentionally has very few questions. It assumes a sensible set of defaults and gets out of the way.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Road Ahead
&lt;/h2&gt;

&lt;p&gt;Being opinionated today doesn't prevent flexibility tomorrow. In fact, I think it makes future flexibility easier.&lt;/p&gt;

&lt;p&gt;By first defining a production-ready baseline, I can later introduce optional capabilities without compromising the core experience. The foundation stays consistent. The project grows through composition instead of endless configuration.&lt;/p&gt;

&lt;p&gt;That's the direction I want to explore next. In the next article, I'll take a closer look at how &lt;code&gt;create-notils&lt;/code&gt; is organized internally, why the UI lives in its own package, and how that decision helps keep multiple applications consistent without duplicating components.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Try out the compiler architecture yourself by running &lt;code&gt;npx create-notils my-app&lt;/code&gt;, or check out the source code on &lt;a href="https://github.com/notils/create-notils" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>nextjs</category>
      <category>opensource</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>One Monorepo, Two Outputs: How I Eliminated Duplicate Starter Templates</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Mon, 20 Jul 2026 09:53:00 +0000</pubDate>
      <link>https://dev.to/sanjaysah/one-monorepo-two-outputs-how-i-eliminated-duplicate-starter-templates-33ke</link>
      <guid>https://dev.to/sanjaysah/one-monorepo-two-outputs-how-i-eliminated-duplicate-starter-templates-33ke</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Part 2 of the &lt;strong&gt;Building create-notils&lt;/strong&gt; series.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/sanjaysah/why-i-stopped-copy-pasting-repositories-and-started-building-my-own-starter-cli-246j"&gt;previous article&lt;/a&gt;, I explained why I stopped copy-pasting repositories and started building my own project scaffolding tool. However, one major architectural problem remained: I wanted &lt;code&gt;create-notils&lt;/code&gt; to support &lt;strong&gt;both&lt;/strong&gt; of these primary project structures.&lt;/p&gt;

&lt;p&gt;A standalone Next.js application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-app/
├── src/
├── public/
├── package.json
└── components.json

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

&lt;/div&gt;



&lt;p&gt;And a Turborepo monorepo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-app/
├── apps/
│   └── app/
├── packages/
│   ├── ui/
│   └── config/
├── turbo.json
└── package.json

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

&lt;/div&gt;



&lt;p&gt;At first glance, the obvious solution is to maintain two separate templates—one for standalone and one for monorepo. Problem solved, right?&lt;/p&gt;

&lt;p&gt;Except... it isn't.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hidden Cost of Multiple Templates
&lt;/h2&gt;

&lt;p&gt;Every starter template starts out identical. Then one day, you fix a subtle bug in one template and forget to update the other. A week later, you upgrade Next.js in one repository before getting around to the second. A month later, you improve your UI package and find yourself manually copying files back and forth between folders.&lt;/p&gt;

&lt;p&gt;Eventually, the templates slowly drift apart. &lt;strong&gt;The true cost isn't creating templates; the cost is maintaining them forever.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Changes?
&lt;/h2&gt;

&lt;p&gt;When I sat down and compared the two project layouts side by side, surprisingly little was different. The actual application code, UI components, theming, and utility functions were 100% identical.&lt;/p&gt;

&lt;p&gt;The only real differences were the structural project boundaries:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;Monorepo&lt;/th&gt;
&lt;th&gt;Standalone&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UI Package&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;packages/ui&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;src/components/ui&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Utilities&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@notils/ui/lib/utils&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@/lib/utils&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shared workspace package&lt;/td&gt;
&lt;td&gt;Local configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Package Manifests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multiple (&lt;code&gt;package.json&lt;/code&gt; files)&lt;/td&gt;
&lt;td&gt;Single root manifest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Workspace Tooling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Present (&lt;code&gt;turbo.json&lt;/code&gt;, workspaces)&lt;/td&gt;
&lt;td&gt;Removed entirely&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything else was effectively the exact same code. That single observation changed the entire architecture of &lt;code&gt;create-notils&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Different Approach: The Canonical Source of Truth
&lt;/h2&gt;

&lt;p&gt;Instead of maintaining two templates, I decided to maintain only one. The monorepo became the &lt;strong&gt;canonical source of truth&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Whenever a developer chooses the monorepo option, the CLI simply clones and scaffolds it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Canonical Monorepo
│
▼
Generated Monorepo

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

&lt;/div&gt;



&lt;p&gt;When someone chooses a standalone project, something much more interesting happens. The CLI dynamically transforms the canonical monorepo into a flattened standalone application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Canonical Monorepo
│
▼
Flatten Transform
│
▼
Generated Standalone

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

&lt;/div&gt;



&lt;p&gt;Instead of storing two separate templates, I generate one directly from the other.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thinking Like a Compiler
&lt;/h2&gt;

&lt;p&gt;This shift changed how I thought about the CLI. It isn't just copying static files anymore; &lt;strong&gt;it is compiling a project&lt;/strong&gt;. The monorepo acts as the source code, and the generated starter is the compiled output.&lt;/p&gt;

&lt;p&gt;Because of this, the transformation can be cleanly broken down into deterministic, sequential steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Canonical Project
│
▼
1. Resolve Workspace Packages
│
▼
2. Rewrite Import Paths
│
▼
3. Move &amp;amp; Flatten Files
│
▼
4. Merge package.json Manifests
│
▼
5. Inline Shared Configurations
│
▼
6. Output Standalone Project

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

&lt;/div&gt;



&lt;p&gt;Each step in this pipeline has a single, isolated responsibility. That makes the entire process predictable, highly testable, and easy to evolve over time.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Monorepo Flattening Works
&lt;/h2&gt;

&lt;p&gt;The transformation itself is surprisingly straightforward under the hood. Workspace packages simply become internal directories inside the application structure. For example, UI components are shifted directly into the source tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/ui/src/components/ui  ──►  src/components/ui

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

&lt;/div&gt;



&lt;p&gt;Shared utility functions are moved alongside them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/ui/src/lib/utils.ts  ──►  src/lib/utils.ts

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

&lt;/div&gt;



&lt;p&gt;Next, the Abstract Syntax Tree (AST) or file contents are processed to rewrite import paths. A workspace import like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Monorepo Workspace Import&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@notils/ui/components/ui/button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Is automatically rewritten to a standard Next.js path alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Standalone Local Import&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/ui/button&lt;/span&gt;&lt;span class="dl"&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 exact same transformation happens for every shared workspace reference across the codebase. Zero component logic changes—only the artificial project boundaries disappear.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architectural Benefits
&lt;/h2&gt;

&lt;p&gt;Treating the monorepo as a canonical compilation source provides several massive advantages for long-term maintenance:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. One Source of Truth
&lt;/h3&gt;

&lt;p&gt;Every bug fix, UI tweak, and architectural improvement is made exactly once. I never have to second-guess whether both project styles are synchronized.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Effortless Upgrades
&lt;/h3&gt;

&lt;p&gt;When breaking changes drop for Next.js, Tailwind CSS, or React, I only update the canonical monorepo. Every generated project shape automatically inherits the upgraded foundation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Automated CI Testing
&lt;/h3&gt;

&lt;p&gt;Because generation is 100% deterministic, I can rigorously verify both outputs in a automated Continuous Integration (CI) pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generate Monorepo ──► Build &amp;amp; Typecheck
       │
       ▼
Generate Standalone ──► Build &amp;amp; Typecheck ──► Verify Zero "@notils/*" Imports Remain

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

&lt;/div&gt;



&lt;p&gt;If the standalone transformation accidentally leaves behind even a single &lt;code&gt;@notils/*&lt;/code&gt; workspace import, the CI pipeline fails immediately. Subtle scaffolding bugs become instant, actionable build failures.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Not Keep a "Shared Core" Submodule?
&lt;/h2&gt;

&lt;p&gt;One common alternative I explored was keeping shared files in a common repository or submodule and wrapping two thin project templates around them. While this sounds clean in theory, it doesn't actually eliminate maintenance duplication.&lt;/p&gt;

&lt;p&gt;You still end up manually managing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two separate &lt;code&gt;package.json&lt;/code&gt; manifests&lt;/li&gt;
&lt;li&gt;Two TypeScript (&lt;code&gt;tsconfig.json&lt;/code&gt;) configurations&lt;/li&gt;
&lt;li&gt;Two distinct linting and formatting setups&lt;/li&gt;
&lt;li&gt;Two &lt;code&gt;shadcn/ui&lt;/code&gt; configuration files&lt;/li&gt;
&lt;li&gt;Two separate build and deployment pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The duplication doesn't disappear; it just gets pushed to a different layer of the codebase. By treating the monorepo as the canonical compiler source, the standalone application becomes a zero-maintenance generated artifact.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking Ahead: From Templates to Targets
&lt;/h2&gt;

&lt;p&gt;Right now, &lt;code&gt;create-notils&lt;/code&gt; focuses exclusively on modern Next.js environments. But this compiler-style architecture opens up an exciting possibility: &lt;strong&gt;instead of thinking in terms of static templates, I'm starting to think in terms of compilation targets.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A single canonical project can eventually compile into completely different project shapes depending on the exact requirements of the developer. Today's supported targets are simply &lt;code&gt;monorepo&lt;/code&gt; and &lt;code&gt;standalone&lt;/code&gt;. Tomorrow, they could expand to include mobile-first layouts, desktop wrappers, or alternate frameworks that share a unified design system and backend layer.&lt;/p&gt;




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

&lt;p&gt;The most valuable lesson I learned while building &lt;code&gt;create-notils&lt;/code&gt; wasn't about Next.js app routers or Turborepo caching—it was about aggressively reducing maintenance overhead.&lt;/p&gt;

&lt;p&gt;Every duplicated template is future technical debt. Every generated template is automation working in your favor.&lt;/p&gt;

&lt;p&gt;When building developer tooling, the fundamental question stopped being:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"How many templates should I maintain?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"How many project shapes can I generate from a single source of truth?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That mindset shift fundamentally transformed how I build and maintain open-source software.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What do you think of generating standalone projects from a monorepo source of truth? Have you tackled template drift in your own tooling before? Let's discuss in the comments!&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Try out the compiler architecture yourself by running &lt;code&gt;npx create-notils my-app&lt;/code&gt;, or check out the source code on &lt;a href="https://github.com/notils/create-notils" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>nextjs</category>
      <category>monorepo</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why I Stopped Copy-Pasting Repositories and Started Building My Own Starter CLI</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Sat, 18 Jul 2026 18:51:36 +0000</pubDate>
      <link>https://dev.to/sanjaysah/why-i-stopped-copy-pasting-repositories-and-started-building-my-own-starter-cli-246j</link>
      <guid>https://dev.to/sanjaysah/why-i-stopped-copy-pasting-repositories-and-started-building-my-own-starter-cli-246j</guid>
      <description>&lt;p&gt;Every developer has a "starter project." Some keep a GitHub template. Some duplicate their previous SaaS project. Some run &lt;code&gt;create-next-app&lt;/code&gt; and spend the next two hours installing the same dependencies, configuring the same tools, and recreating the same folder structure.&lt;/p&gt;

&lt;p&gt;I was in the second group. Every new project started the same way.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then came the checklist.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Tailwind CSS.&lt;/li&gt;
&lt;li&gt;Configure Biome.&lt;/li&gt;
&lt;li&gt;Add shadcn/ui.&lt;/li&gt;
&lt;li&gt;Organize folders.&lt;/li&gt;
&lt;li&gt;Set up a UI library.&lt;/li&gt;
&lt;li&gt;Configure TypeScript.&lt;/li&gt;
&lt;li&gt;Add environment files.&lt;/li&gt;
&lt;li&gt;Set up a monorepo.&lt;/li&gt;
&lt;li&gt;Copy utility functions.&lt;/li&gt;
&lt;li&gt;Configure path aliases.&lt;/li&gt;
&lt;li&gt;Install development tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these tasks were difficult. They were just repetitive. After starting enough projects, I realized something:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I wasn't building products. I was rebuilding the same foundation over and over again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Starter Kit Trap
&lt;/h2&gt;

&lt;p&gt;Like many developers, I created a "starter repository." Whenever I wanted to build something new, I'd clone it. It worked... until it didn't.&lt;/p&gt;

&lt;p&gt;Eventually I had multiple starter repositories.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One for a monorepo.&lt;/li&gt;
&lt;li&gt;One for a standalone project.&lt;/li&gt;
&lt;li&gt;One with authentication.&lt;/li&gt;
&lt;li&gt;One without authentication.&lt;/li&gt;
&lt;li&gt;One for experiments.&lt;/li&gt;
&lt;li&gt;One that was already outdated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping them synchronized became its own maintenance project. Fix a bug in one. Forget to fix it in another. Upgrade Next.js in one repository. Forget the rest.&lt;/p&gt;

&lt;p&gt;The more starters I created, the less useful they became.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Existing Starters Didn't Quite Fit
&lt;/h2&gt;

&lt;p&gt;There are already fantastic starter kits in the ecosystem. Some focus on minimalism. Others include every feature imaginable. The problem wasn't that they were bad. The problem was that they optimized for someone else's workflow.&lt;/p&gt;

&lt;p&gt;Every project I build starts with almost the same stack.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Bun/pnpm&lt;/li&gt;
&lt;li&gt;Tailwind CSS v4&lt;/li&gt;
&lt;li&gt;shadcn/ui&lt;/li&gt;
&lt;li&gt;Biome&lt;/li&gt;
&lt;li&gt;Production-ready project structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I didn't want to answer twenty configuration questions every time I scaffolded a project.&lt;/p&gt;

&lt;p&gt;I wanted one command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-notils my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and be ready to start building.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opinionated Doesn't Mean Inflexible
&lt;/h2&gt;

&lt;p&gt;One thing I've learned is that &lt;strong&gt;being opinionated is often a strength&lt;/strong&gt;. Frameworks like Laravel, Rails, and even Next.js provide sensible defaults. You can always change them later. The important thing is that you're productive on day one.&lt;/p&gt;

&lt;p&gt;That's the philosophy I'm following. Instead of trying to support every possible technology combination, I picked a stack that I genuinely enjoy using every day.&lt;/p&gt;

&lt;p&gt;Everything generated by the CLI lives inside your repository.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nothing is hidden.&lt;/li&gt;
&lt;li&gt;Nothing is hosted.&lt;/li&gt;
&lt;li&gt;Nothing prevents you from changing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The starter gives you a foundation—not a cage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building for Myself First
&lt;/h2&gt;

&lt;p&gt;A question I've been asked is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why not make everything configurable from the beginning?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because I'm the first user. The goal wasn't to build the most flexible scaffolding tool. The goal was to eliminate repetitive work from my own workflow. Once something proves useful in real projects, it can become configurable.&lt;/p&gt;

&lt;p&gt;Until then, I'd rather spend my time building products than building configuration screens.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Beginning of &lt;code&gt;create-notils&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;That idea eventually became &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/create-notils" rel="noopener noreferrer"&gt;create-notils&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Right now, it focuses on doing one thing well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scaffold a modern Next.js project.&lt;/li&gt;
&lt;li&gt;Support both standalone and monorepo layouts.&lt;/li&gt;
&lt;li&gt;Configure a shared shadcn/ui setup.&lt;/li&gt;
&lt;li&gt;Use Bun, Biome, Tailwind CSS v4, and TypeScript out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's intentionally small.&lt;/p&gt;

&lt;p&gt;Future releases will add authentication, database integration, API clients, Docker support, and more—but only after those features have been battle-tested in my own projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;One design decision turned out to be far more interesting than I expected. I wanted to support both standalone projects and monorepos. Most tools solve this by maintaining two different templates.&lt;/p&gt;

&lt;p&gt;I chose a different approach: The monorepo is the single source of truth, and the standalone project is generated from it through a deterministic transform.&lt;/p&gt;

&lt;p&gt;That means I only maintain one project while generating two different project shapes.&lt;/p&gt;

&lt;p&gt;In the next article, I'll dive into how that architecture works, why I chose it, and how it avoids template duplication.&lt;/p&gt;




&lt;p&gt;I'd love to hear how you start new projects.&lt;/p&gt;

&lt;p&gt;Do you use GitHub templates, starter repositories, scaffolding tools, or something completely different?&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building React Native Shouldn't Feel Like Assembling IKEA Furniture: A Modern Monorepo Starter Kit</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:54:50 +0000</pubDate>
      <link>https://dev.to/sanjaysah/building-react-native-shouldnt-feel-like-assembling-ikea-furniture-a-modern-monorepo-starter-kit-pef</link>
      <guid>https://dev.to/sanjaysah/building-react-native-shouldnt-feel-like-assembling-ikea-furniture-a-modern-monorepo-starter-kit-pef</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I just want to build my app."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence sounds simple. But if you've ever started a new React Native project, you know that is rarely what actually happens.&lt;/p&gt;




&lt;p&gt;You open your terminal with excitement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-expo-app my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five minutes later, you're already searching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"How to set up Tailwind CSS in React Native?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Should I use NativeWind?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"How do I share components between mobile and web apps?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Expo Router or React Navigation?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"How do people organize React Native monorepos?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Should I use Turborepo?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"How do I keep multiple apps sharing the same UI?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before you have written your first screen... you have already spent hours making architectural decisions. Not product decisions. Not business decisions. &lt;strong&gt;Just project setup.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Invisible Tax Every React Native Developer Pays
&lt;/h2&gt;

&lt;p&gt;Imagine you are opening a restaurant. You have recipes. You have chefs. You know exactly what food you want to serve. But before opening the doors, someone tells you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"First, build the kitchen."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So you start researching: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which stove?&lt;/li&gt;
&lt;li&gt;Which oven?&lt;/li&gt;
&lt;li&gt;Which refrigerator?&lt;/li&gt;
&lt;li&gt;How should the plumbing work?&lt;/li&gt;
&lt;li&gt;How do multiple restaurants share ingredients?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Months later... you still haven't served a single customer.&lt;/p&gt;

&lt;p&gt;Software development often feels exactly like that. We don't struggle because building apps is hard. &lt;strong&gt;We struggle because building the environment to build apps is hard.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Every New Project Starts With The Same Questions
&lt;/h2&gt;

&lt;p&gt;Every engineering team eventually reaches the same crossroads:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"How should we organize this codebase?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Should every app have its own repository?&lt;/li&gt;
&lt;li&gt;Or should they share everything?&lt;/li&gt;
&lt;li&gt;Should design components live inside the mobile app folder, or inside separate workspace packages?&lt;/li&gt;
&lt;li&gt;What about authentication, API clients, themes, icons, and utilities?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every answer seems correct... until six months later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then The Real Problems Begin
&lt;/h2&gt;

&lt;p&gt;Imagine your company builds two applications: a &lt;strong&gt;Customer App&lt;/strong&gt; and a &lt;strong&gt;POS App&lt;/strong&gt;. Both need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buttons &amp;amp; Forms&lt;/li&gt;
&lt;li&gt;A consistent design theme&lt;/li&gt;
&lt;li&gt;Icons &amp;amp; Typography&lt;/li&gt;
&lt;li&gt;Authentication plumbing&lt;/li&gt;
&lt;li&gt;A typed API client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, copy-pasting feels faster. Until the designer changes one button style. Now your codebase looks 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;Customer App  👉  Updated ✅
POS App       👉  Outdated ❌

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

&lt;/div&gt;



&lt;p&gt;Next week, the typography changes. Then the color palette. Then spacing. Suddenly, you are spending your weekends maintaining two separate design systems that were supposed to be one.&lt;/p&gt;




&lt;h2&gt;
  
  
  "Let's Make a Shared UI Package"
&lt;/h2&gt;

&lt;p&gt;Sounds easy. Until you actually try to set it up in a mobile environment. Now you are diving deep into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;npm / pnpm&lt;/strong&gt; workspaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turborepo&lt;/strong&gt; pipeline caching&lt;/li&gt;
&lt;li&gt;Package export maps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metro bundler&lt;/strong&gt; configuration&lt;/li&gt;
&lt;li&gt;TypeScript path aliases &amp;amp; references&lt;/li&gt;
&lt;li&gt;Babel plugins &amp;amp; module resolution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You started because you wanted one shared button. Now you are spending your evening debugging &lt;strong&gt;why Metro cannot resolve an SVG icon&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Styling Was Supposed To Be Easy, Too
&lt;/h2&gt;

&lt;p&gt;Most web developers already know and love &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;. So naturally, they ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Can I just use Tailwind in React Native?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer is yes. Then comes another rabbit hole: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Babel plugins&lt;/li&gt;
&lt;li&gt;Metro config adjustments&lt;/li&gt;
&lt;li&gt;Dark mode persistence&lt;/li&gt;
&lt;li&gt;Theme CSS variables&lt;/li&gt;
&lt;li&gt;Hot reload bugs&lt;/li&gt;
&lt;li&gt;And version compatibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;a href="https://www.nativewind.dev/v5" rel="noopener noreferrer"&gt;NativeWind v5&lt;/a&gt; arrived, it solved many long-standing pain points and made styling feel much closer to the web Tailwind experience developers love. But getting everything configured correctly - and keeping it working smoothly across SDK upgrades - still takes considerable time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The styling itself isn't the hard part. The boilerplate setup is.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Building Components Is Harder Than It Looks
&lt;/h2&gt;

&lt;p&gt;Most production apps don't need fancy, animated components. They need &lt;strong&gt;consistent, accessible components&lt;/strong&gt;. A button should always look and feel like a button. An input should always handle keyboard focus correctly. A modal dialog should behave predictably across iOS and Android.&lt;/p&gt;

&lt;p&gt;Projects like &lt;a href="https://reactnativereusables.com/" rel="noopener noreferrer"&gt;React Native Reusables&lt;/a&gt; made this dramatically easier by bringing modern, accessible UI primitives into the React Native ecosystem. Instead of reinventing custom components for every project, you start with well-designed building blocks.&lt;/p&gt;

&lt;p&gt;But even then... someone still has to integrate, theme, and wire everything together across version upgrades.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚡ The NativeWind v5 Migration Gap (And How RNStack Solves It)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Right now, React Native Reusables officially targets &lt;strong&gt;NativeWind v4&lt;/strong&gt;. If you try using it with &lt;strong&gt;NativeWind v5&lt;/strong&gt;, you will immediately hit styling bugs and breaking changes.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;RNStack&lt;/strong&gt;, I have already &lt;strong&gt;fully migrated all included components to NativeWind v5&lt;/strong&gt; (Tailwind v4) and pre-fixed common problem areas—especially complex components like &lt;code&gt;Icon&lt;/code&gt;, &lt;code&gt;Button&lt;/code&gt;, and &lt;code&gt;Select&lt;/code&gt;—so they render seamlessly across iOS, Android, and web out of the box.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  And Then Comes Scale
&lt;/h2&gt;

&lt;p&gt;Your first app becomes successful. Now the business asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Can we build another app for our internal team?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Great! Except now your architectural requirements have multiplied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📱 Customer App   |   🛠️ Admin App   |   🏪 POS App   |   🚚 Driver App

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

&lt;/div&gt;



&lt;p&gt;Four applications. One engineering team. One design language. One backend API. One authentication system.&lt;/p&gt;

&lt;p&gt;Should you create four separate repositories? Or one? This is where &lt;strong&gt;monorepos&lt;/strong&gt; stop being a buzzword and start becoming a practical survival tool.&lt;/p&gt;

&lt;p&gt;A monorepo isn't just about putting everything into one giant folder. It is about giving every project access to the exact same foundation: &lt;strong&gt;One shared UI. One shared API layer. One shared configuration. One source of truth.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  But Monorepos Bring Their Own Challenges
&lt;/h2&gt;

&lt;p&gt;Large repositories can easily become painfully slow. Without proper tooling, every build starts rebuilding everything from scratch, and every dependency install feels heavier.&lt;/p&gt;

&lt;p&gt;That is where &lt;a href="https://turborepo.dev/docs" rel="noopener noreferrer"&gt;Turborepo&lt;/a&gt; changes the story. Instead of rebuilding the entire house every time you make a change, &lt;strong&gt;it only rebuilds the rooms you have actually touched&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The result is a development workflow that stays lightning-fast even as your codebase grows. Not because your apps became smaller—but because your tooling became smarter.&lt;/p&gt;




&lt;h2&gt;
  
  
  After Solving The Same Problems Again And Again...
&lt;/h2&gt;

&lt;p&gt;I noticed a pattern. Every project I worked on looked different on the surface... but the foundational setup looked almost identical.&lt;/p&gt;

&lt;p&gt;Every time I started a new React Native project, I found myself &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;copying the same workspace files&lt;/li&gt;
&lt;li&gt;installing the exact same dependencies&lt;/li&gt;
&lt;li&gt;configuring the same Metro resolver fixes&lt;/li&gt;
&lt;li&gt;setting up the same TypeScript aliases&lt;/li&gt;
&lt;li&gt;building the same shared UI package&lt;/li&gt;
&lt;li&gt;and configuring &lt;a href="https://docs.expo.dev/router/introduction/" rel="noopener noreferrer"&gt;Expo Router&lt;/a&gt; and NativeWind. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over and over again.&lt;/p&gt;

&lt;p&gt;Eventually, I stopped asking: &lt;em&gt;"How do I start another project?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead, I asked: &lt;strong&gt;"Why am I solving this plumbing problem every single time?"&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  That's Why I Built RNStack
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/sanjaysah101/rnstack" rel="noopener noreferrer"&gt;RNStack&lt;/a&gt; isn't trying to replace Expo. It isn't another heavy UI library. It isn't a random collection of disconnected snippets.&lt;/p&gt;

&lt;p&gt;It is simply the &lt;strong&gt;mobile-first, production-ready monorepo foundation&lt;/strong&gt; I wished every new React Native project started with. A clean architecture where the difficult, time-consuming setup decisions have already been made for you. So you can focus on building your actual product instead of wrestling with build tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Command To Start
&lt;/h2&gt;

&lt;p&gt;You can scaffold a clean, production-ready project instantly using the &lt;a href="https://www.npmjs.com/package/create-rnstack" rel="noopener noreferrer"&gt;create-rnstack npm package&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm create rnstack my-app

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

&lt;/div&gt;



&lt;p&gt;A few moments later, you have a fully wired workspace that already includes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Pre-Configured Tooling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Core Framework&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://expo.dev/" rel="noopener noreferrer"&gt;Expo&lt;/a&gt; (SDK 56) + &lt;a href="https://docs.expo.dev/router/introduction/" rel="noopener noreferrer"&gt;Expo Router&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Styling &amp;amp; UI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://www.nativewind.dev/v5" rel="noopener noreferrer"&gt;NativeWind v5&lt;/a&gt; + &lt;a href="https://reactnativereusables.com/" rel="noopener noreferrer"&gt;React Native Reusables&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Architecture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://turborepo.dev/docs" rel="noopener noreferrer"&gt;Turborepo&lt;/a&gt; + pnpm Workspaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shared Packages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pre-linked &lt;code&gt;@repo/ui&lt;/code&gt;, &lt;code&gt;@repo/api-client&lt;/code&gt;, and &lt;code&gt;@repo/config&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code Quality&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Strict TypeScript, Biome, Husky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatic Expo dependency validation &amp;amp; native bundle ID management&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No hunting through outdated Medium tutorials. No copy-pasting broken configurations. No wondering whether you forgot a crucial setup step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Small Details Matter
&lt;/h2&gt;

&lt;p&gt;The biggest improvements in developer experience are often the ones you never notice because everything just works. RNStack automatically handles the subtle details that are easy to forget but painful to fix later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Unique Native Bundle IDs:&lt;/strong&gt; Every generated app automatically gets a clean, unique bundle identifier.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Aligned SDK Versions:&lt;/strong&gt; Expo dependency versions stay strictly aligned with your installed SDK.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Immediate Git Hooks:&lt;/strong&gt; Pre-commit formatting and linting work right out of the box.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Zero Bloat:&lt;/strong&gt; Projects start clean without shipping dozens of unnecessary boilerplate demo screens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't flashy marketing features. They are the quiet, architectural details that save dozens of hours over the lifetime of a production codebase.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Goal Was Never To Build Just Another Boilerplate
&lt;/h2&gt;

&lt;p&gt;There are already plenty of starters out there. But most of them stop right after generating a few static files.&lt;/p&gt;

&lt;p&gt;RNStack tries to go one step further: it gives you an evolving foundation meant to survive far beyond your first commit. Something robust enough to build your next weekend side project on, scale into a startup MVP, or ship to thousands of production users.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It Out &amp;amp; Join The Journey
&lt;/h2&gt;

&lt;p&gt;If you are starting a new React Native project this week, give RNStack a spin. I would genuinely love to hear your feedback—what feels intuitive, what feels awkward, and what could be improved!&lt;/p&gt;

&lt;p&gt;Every issue opened, suggestion made, and pull request submitted helps make the mobile development experience better for the next engineer.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔗 Get Started in Seconds
&lt;/h3&gt;

&lt;p&gt;Scaffold your new project right now from 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;pnpm create rnstack my-app

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;📦 NPM Package:&lt;/strong&gt; Check out the CLI documentation on the &lt;a href="https://www.npmjs.com/package/create-rnstack" rel="noopener noreferrer"&gt;create-rnstack npm page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;⭐ GitHub Repository:&lt;/strong&gt; Explore the monorepo architecture, star the repo, or contribute on &lt;a href="https://github.com/sanjaysah101/rnstack" rel="noopener noreferrer"&gt;sanjaysah101/rnstack&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If RNStack saves you a few hours—or helps you skip a frustrating evening of configuration—that is exactly why I built it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy building! 🚀&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>expo</category>
      <category>react</category>
      <category>opensource</category>
    </item>
    <item>
      <title>BrewOps: A Production-Grade HTCPCP Dashboard</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Thu, 02 Apr 2026 11:40:36 +0000</pubDate>
      <link>https://dev.to/sanjaysah/brewops-a-production-grade-htcpcp-dashboard-l35</link>
      <guid>https://dev.to/sanjaysah/brewops-a-production-grade-htcpcp-dashboard-l35</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;BrewOps&lt;/strong&gt;, a highly serious, production-grade DevOps dashboard for a delightfully useless protocol: the Hyper Text Coffee Pot Control Protocol (HTCPCP, RFC 2324). &lt;/p&gt;

&lt;p&gt;Tired of walking to the breakroom only to find the coffee pot empty? BrewOps brings 1998's best internet joke into the modern era. It's a sleek control center that lets you monitor your network of coffee pots and teapots. You can issue &lt;code&gt;BREW&lt;/code&gt; and &lt;code&gt;PROPFIND&lt;/code&gt; requests, select your &lt;code&gt;Accept-Additions&lt;/code&gt; (like Milk, Syrup, or Alcohol), and watch the live terminal logs. &lt;/p&gt;

&lt;p&gt;And yes, if you try to brew coffee using the "Earl Grey Teapot" appliance, the server will correctly reject your request with a &lt;code&gt;418 I'm a teapot&lt;/code&gt; status code, complete with a panic animation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live App:&lt;/strong&gt; &lt;a href="https://brewops-htcpcp-dashboard-775853986076.us-west1.run.app" rel="noopener noreferrer"&gt;BrewOps HTCPCP Dashboard&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://brewops-htcpcp-dashboard-775853986076.us-west1.run.app"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Source Code:&lt;/strong&gt; &lt;a href="https://ai.studio/apps/1e2bc60e-2228-47dc-9b84-4da88097bbf4" rel="noopener noreferrer"&gt;Google AI Studio Project&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;I built this using &lt;strong&gt;Next.js&lt;/strong&gt; and &lt;strong&gt;Tailwind CSS&lt;/strong&gt; to give it that authentic, dark-mode "serious developer tool" aesthetic. The icons are from &lt;code&gt;lucide-react&lt;/code&gt;, and I used &lt;code&gt;motion/react&lt;/code&gt; (Framer Motion) to create the smooth terminal log entries and the bouncing teapot animation when a 418 error is triggered. &lt;/p&gt;

&lt;p&gt;The entire project was generated, iterated on, and deployed using &lt;strong&gt;Google AI Studio&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Category
&lt;/h2&gt;

&lt;p&gt;I am submitting this for two categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Best Ode to Larry Masinter:&lt;/strong&gt; &lt;br&gt;
This project is a literal, playable implementation of Larry Masinter's legendary RFC 2324. It faithfully recreates the HTCPCP headers (&lt;code&gt;Accept-Additions&lt;/code&gt;, &lt;code&gt;message/coffeepot&lt;/code&gt; content types) and intentionally triggers the famous &lt;code&gt;418 I'm a teapot&lt;/code&gt; error when you target the wrong appliance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Best Google AI Usage:&lt;/strong&gt; &lt;br&gt;
I built this entire application from scratch using &lt;strong&gt;Google AI Studio&lt;/strong&gt; (powered by Gemini 3.1 Pro). The AI agent helped me scaffold the Next.js app, design the Tailwind UI, write the simulated terminal logic, and instantly deploy the final build to &lt;strong&gt;Google Cloud Run&lt;/strong&gt; (which is where it is currently hosted!).&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Serenity: A Personal AI Wellbeing Companion Built with Google Gemini</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Tue, 03 Mar 2026 11:51:28 +0000</pubDate>
      <link>https://dev.to/sanjaysah/serenity-a-personal-ai-wellbeing-companion-built-with-google-gemini-2epk</link>
      <guid>https://dev.to/sanjaysah/serenity-a-personal-ai-wellbeing-companion-built-with-google-gemini-2epk</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mlh-built-with-google-gemini-02-25-26"&gt;Built with Google Gemini: Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built with Google Gemini
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;Serenity&lt;/strong&gt;, a comprehensive, privacy-first mental health and wellbeing application designed to act as your personal caretaker, health coach, and daily companion. &lt;/p&gt;

&lt;p&gt;Mental health tools are often fragmented—you use one app for habit tracking, another for journaling, and yet another for meditation. Serenity solves this by combining all these tools into one cohesive, beautifully designed platform. It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mood Check-ins &amp;amp; Insights:&lt;/strong&gt; Track daily emotional trends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Journal:&lt;/strong&gt; A safe space for reflection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Habit &amp;amp; Goal Tracker:&lt;/strong&gt; Build positive routines and set long-term targets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wellness Hub:&lt;/strong&gt; Interactive exercises including Box Breathing, 5-4-3-2-1 Grounding, Body Scan meditations, and Eye Strain Relief.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Role of Google Gemini:&lt;/strong&gt;&lt;br&gt;
Google Gemini (&lt;code&gt;gemini-3-flash-preview&lt;/code&gt;) acts as the core "brain" and empathetic heart of the app. Instead of just a generic chatbot, Serenity uses the &lt;code&gt;@google/genai&lt;/code&gt; SDK to read your recent moods, incomplete habits, journal entries, and long-term goals as context. &lt;/p&gt;

&lt;p&gt;Gemini provides highly tailored advice, health tips, and emotional support. For example, if you set a goal to "Run a 5K", you can click "Ask Serenity for a Plan", and Gemini will instantly generate a personalized diet, exercise, and lifestyle plan based on your current habits and mood history. It also proactively generates warm, encouraging reminders if you forget to complete your daily habits!&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

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

&lt;p&gt;You can try out the live version of Serenity here:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://serenity-xi-eight.vercel.app/" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://github.com/sanjaysah101/serenity" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: The app is designed with a "Warm Organic" aesthetic using Tailwind CSS and Framer Motion to create a calming user experience.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Building Serenity was an incredible learning experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contextual AI Engineering:&lt;/strong&gt; I learned how to effectively pass structured JSON data (user moods, habits, journals) into Gemini's system prompt to create an AI that truly "remembers" and understands the user's current state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI/UX for Mental Health:&lt;/strong&gt; I learned the importance of color psychology and micro-interactions. Using glassmorphism, soft sage/earth tones, and smooth Framer Motion animations helped create a UI that actually lowers stress rather than adding to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Component Design:&lt;/strong&gt; Building the Wellness Hub taught me how to manage complex state and timers in React, especially for the Body Scan and Eye Strain Relief exercises.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Google Gemini Feedback
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What worked well:&lt;/strong&gt;&lt;br&gt;
The new &lt;code&gt;@google/genai&lt;/code&gt; SDK is incredibly intuitive. The speed of the &lt;code&gt;gemini-3-flash-preview&lt;/code&gt; model is phenomenal—it makes the conversational assistant feel truly real-time. I was also deeply impressed by how well Gemini understood the structured context I passed to it. It seamlessly connected the dots between a user feeling "anxious" in their mood log and suggesting the built-in grounding exercises.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where I ran into friction:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The main challenge was prompt engineering to get the &lt;em&gt;tone&lt;/em&gt; exactly right. Initially, the AI sounded a bit too clinical or robotic. I had to refine the system instructions heavily to ensure it consistently spoke with the warmth, empathy, and brevity of a "personal caretaker." Additionally, handling the multimodal inputs (allowing users to upload images to the chat) required some careful base64 encoding logic to pass to the API correctly, but once set up, it worked flawlessly.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with ❤️ for the Hack for &lt;a href="https://hackformental.com/2026" rel="noopener noreferrer"&gt;Mental Health 2026&lt;/a&gt; &amp;amp; DEV Challenge.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>gemini</category>
    </item>
    <item>
      <title>From Zero Rust to DevOps: Building a System Monitor with GitHub Copilot CLI</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Sun, 15 Feb 2026 06:34:12 +0000</pubDate>
      <link>https://dev.to/sanjaysah/from-zero-rust-to-devops-building-a-system-monitor-with-github-copilot-cli-3mf5</link>
      <guid>https://dev.to/sanjaysah/from-zero-rust-to-devops-building-a-system-monitor-with-github-copilot-cli-3mf5</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;&lt;code&gt;rust-tui-dashboard&lt;/code&gt;&lt;/strong&gt;, a terminal-based system monitor (similar to &lt;code&gt;htop&lt;/code&gt; or &lt;code&gt;btop&lt;/code&gt;) written entirely in &lt;strong&gt;Rust&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As a Full-Stack developer primarily experienced with JavaScript and the MERN stack, I have always wanted to learn Rust. However, the steep learning curve—specifically the borrow checker and strict type system—was intimidating. For this challenge, I decided to use the &lt;strong&gt;GitHub Copilot CLI&lt;/strong&gt; as my "Senior Rust Engineer" to guide me through building a production-ready application from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visual Gauges:&lt;/strong&gt; Real-time CPU &amp;amp; Memory usage visualized with colorful progress bars (Cyan &amp;amp; Yellow).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disk Alerts:&lt;/strong&gt; Tracks partition usage (which hilariously warned me that my own drive is &lt;strong&gt;97.5% full&lt;/strong&gt;!).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Stats:&lt;/strong&gt; Live upload/download speed tracking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Platform:&lt;/strong&gt; Runs on Linux, macOS, and Windows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Builds:&lt;/strong&gt; A CI/CD pipeline set up via GitHub Actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Here is the final result running in my terminal:&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%2Frl1yqezg62q7mn0uq98b.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%2Frl1yqezg62q7mn0uq98b.png" alt="Rust TUI Dashboard" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/sanjaysah101/rust-tui-dashboard" rel="noopener noreferrer"&gt;rust-tui-dashboard&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;Building this project was a journey of &lt;strong&gt;"Prompt -&amp;gt; Error -&amp;gt; Explanation -&amp;gt; Fix."&lt;/strong&gt; The Copilot CLI didn't just write code for me; it taught me &lt;em&gt;why&lt;/em&gt; the code worked (or didn't).&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The "Hello World" Moment
&lt;/h3&gt;

&lt;p&gt;I started with an empty folder and didn't even know the command to initialize a Rust project.&lt;br&gt;
&lt;strong&gt;Prompt:&lt;/strong&gt; &lt;code&gt;how to initialize a new rust project named dev-dashboard&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Result:&lt;/strong&gt; It gave me &lt;code&gt;cargo new dev-dashboard&lt;/code&gt; immediately. I was up and running in seconds.&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%2Fad8rzy8dan56jixx6eci.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%2Fad8rzy8dan56jixx6eci.png" alt="how to initialize a new rust project named dev-dashboard" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Overcoming the "Generic" Hallucination
&lt;/h3&gt;

&lt;p&gt;This was the most valuable interaction. I used the &lt;code&gt;ratatui&lt;/code&gt; library for the UI, but the code Copilot initially suggested threw a complex compilation error:&lt;br&gt;
&lt;code&gt;error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsre88tljcnnr8153k0f4.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%2Fsre88tljcnnr8153k0f4.png" alt="struct takes 0 generic arguments but 1 generic argument was supplied" width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of pasting this into Google, I asked the CLI:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; &lt;code&gt;struct takes 0 generic arguments but 1 generic argument was supplied&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Copilot correctly identified that the library version I installed had a breaking API change (&lt;code&gt;Frame&amp;lt;B&amp;gt;&lt;/code&gt; became just &lt;code&gt;Frame&lt;/code&gt;). It explained the difference, and while its initial code fix was slightly aggressive (it removed generics from &lt;em&gt;everything&lt;/em&gt;), the explanation gave me enough context to manually fix the &lt;code&gt;Terminal&lt;/code&gt; struct generics while simplifying the &lt;code&gt;Frame&lt;/code&gt; struct. It turned a potential 2-hour debugging session into a 5-minute fix.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. From Text to "Eye Candy"
&lt;/h3&gt;

&lt;p&gt;Initially, my dashboard was just text blocks. I wanted it to look professional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; &lt;code&gt;"Update the ui function. Instead of displaying CPU Usage as simple text, use the ratatui::widgets::Gauge widget. Set the percent to app.cpu_usage and color it Cyan."&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It instantly scaffolded the &lt;code&gt;Gauge&lt;/code&gt; widget code, giving me professional-looking progress bars without me needing to read the entire documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The DevOps Bonus
&lt;/h3&gt;

&lt;p&gt;I didn't want users to have to compile the code themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; &lt;code&gt;"Create a GitHub Actions workflow file named .github/workflows/release.yml to build the project on push."&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Copilot generated a perfect YAML file. Now, every time I push code, GitHub Actions automatically compiles my Rust binary and uploads it as an artifact.&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%2Fycw42nmaptpprfp4vp5z.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%2Fycw42nmaptpprfp4vp5z.png" alt="Copilot generated a perfect Github Action workflow" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;GitHub Copilot CLI&lt;/strong&gt; bridged the gap between my JavaScript knowledge and Rust's strict environment. It allowed me to build a tool that I actually use now—if only to remind me to clean up my hard drive (seriously, only 7GB left!).&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>How I Improved Email Rendering Performance 15x Using Rust + WebAssembly (Next.js 16 Devlog)</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Fri, 13 Feb 2026 10:41:57 +0000</pubDate>
      <link>https://dev.to/sanjaysah/how-i-improved-email-rendering-performance-15x-using-rust-webassembly-nextjs-16-devlog-2hml</link>
      <guid>https://dev.to/sanjaysah/how-i-improved-email-rendering-performance-15x-using-rust-webassembly-nextjs-16-devlog-2hml</guid>
      <description>&lt;p&gt;I decided to do something scary: Build a SaaS product in public, from scratch, sharing every win and every embarrassing error log along the way.&lt;/p&gt;

&lt;p&gt;The product is &lt;strong&gt;Ansomail&lt;/strong&gt;—an AI-powered drag-and-drop email editor.&lt;br&gt;
The goal? To build a tool where Developers set the rules (Design System) and Marketers just drag-and-drop blocks, without ever breaking the layout.&lt;/p&gt;

&lt;p&gt;Here is the unvarnished truth of my first week: battling the "bleeding edge" tax of Next.js 16, crashing my database, and eventually rewriting my engine in Rust for a 15x speed boost.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;The Stack: Betting on Speed&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I didn't want a legacy stack. I wanted speed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runtime:&lt;/strong&gt; Bun (for instant startup)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js 16 (Turbopack)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monorepo:&lt;/strong&gt; Turborepo (preparing for the &lt;code&gt;Ansospace&lt;/code&gt; ecosystem)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; Postgres + Drizzle ORM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linting:&lt;/strong&gt; Biome (Farewell, ESLint)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looked perfect on paper. Then I started coding.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Days 1-2: The Architecture &amp;amp; The "AI Architect"&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The first challenge wasn't code; it was philosophy. How do you stop an AI from generating broken HTML?&lt;/p&gt;

&lt;p&gt;Most AI builders treat LLMs like creative writers. I decided to treat them like &lt;strong&gt;Strict Architects&lt;/strong&gt;. I set up a system where the AI's output is validated against a rigid &lt;strong&gt;JSON Schema&lt;/strong&gt;. If the AI hallucinates a CSS class that doesn't exist in my system, the update is rejected before it ever hits the UI.&lt;/p&gt;

&lt;p&gt;I also set up the "Hello World" of modern SaaS: An empty repo configured with Biome and Bun. It was clean, fast, and satisfying.&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%2Fi0f0cf4mpr9jes3gcjth.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%2Fi0f0cf4mpr9jes3gcjth.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Days 3-4: The "Bleeding Edge" Tax&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Then came the pain.&lt;/p&gt;

&lt;p&gt;I hit what I call the "Bleeding Edge Tax." Next.js 16 and Bun are incredible, but they don't always play nice together. My dev server started crashing on hot reloads.&lt;/p&gt;

&lt;p&gt;And then, I killed my database. 💀&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%2Fm5c00nyvihmxodxf5edd.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%2Fm5c00nyvihmxodxf5edd.png" alt="FATAL: sorry, too many clients already"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started getting the dreaded error:&lt;br&gt;
&lt;code&gt;FATAL: sorry, too many clients already&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Because I'm using a serverless environment, every hot reload was opening a new connection to Postgres without closing the old one. My database choked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; I had to implement strict &lt;strong&gt;Connection Pooling&lt;/strong&gt;. It was a harsh reminder that "Serverless" doesn't mean "Ops-less." Once I capped the active connections, the backend stabilized, and I shipped the "My Templates" dashboard.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Days 5-6: Chasing the "Google Docs" Feel&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With the backend stable, I moved to UX. I wanted a "Rename Template" feature that felt like Google Docs—instant.&lt;/p&gt;

&lt;p&gt;I implemented &lt;strong&gt;Optimistic UI&lt;/strong&gt;. When a user types, the UI updates immediately. The server validates it in the background. If it fails, we revert. If it works, the user never notices the lag.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2021209854837158185-500" src="https://platform.twitter.com/embed/Tweet.html?id=2021209854837158185"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2021209854837158185-500');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2021209854837158185&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;I also built the first version of the &lt;strong&gt;Rendering Engine&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DB stores JSON.&lt;/li&gt;
&lt;li&gt;Parser converts JSON → MJML.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mjml-browser&lt;/code&gt; converts MJML → HTML.&lt;/li&gt;
&lt;li&gt;Result renders in an iframe.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It worked. But it was slow. &lt;strong&gt;~18ms&lt;/strong&gt; per render. For a drag-and-drop tool, that felt sluggish.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Day 7: The Rust Rewrite (15x Speed Boost)&lt;/strong&gt; 🚀
&lt;/h2&gt;

&lt;p&gt;I couldn't settle for 18ms. I knew &lt;code&gt;mjml-browser&lt;/code&gt; (Pure JS) was the bottleneck.&lt;/p&gt;

&lt;p&gt;So, I did something drastic for a one-week-old project: &lt;strong&gt;I swapped the engine to Rust.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ToHtmlResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convertMJMLToHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mjmlString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mjmlString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&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 integrated &lt;strong&gt;MRML&lt;/strong&gt; (a Rust port of MJML) via WebAssembly.&lt;br&gt;
The integration was tricky—Rust is strict. It refused to compile my "sloppy" JSON that JS had been happily ignoring. It forced me to fix my data structure.&lt;/p&gt;

&lt;p&gt;But once it worked? The results were insane.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JS Engine:&lt;/strong&gt; ~18ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust (WASM):&lt;/strong&gt; ~1.1ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That is a 15x speed increase.&lt;/strong&gt; The preview is now effectively real-time, running at 60fps.&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%2Fsd1tfpcpmqtzs44u3tn5.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%2Fsd1tfpcpmqtzs44u3tn5.jpg" alt="That is a 15x speed increase."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What's Next?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Week 1 was about the Foundation. Week 2 is about the &lt;strong&gt;Interaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now that I have a 1ms rendering engine, I'm building the actual Drag-and-Drop layer.&lt;/p&gt;

&lt;p&gt;I'm documenting this entire journey daily on X (Twitter). If you're into Next.js, Rust, or just want to see a developer struggle and succeed in real-time, come say hi!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow the journey:&lt;/strong&gt; &lt;a href="https://x.com/hashtag/ansomail?src=hashtag_click" rel="noopener noreferrer"&gt;#ansomail / @ansomail&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Connect with me:&lt;/strong&gt; &lt;a href="https://x.com/sanjaysah101" rel="noopener noreferrer"&gt;x.com/sanjaysah101&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>rust</category>
      <category>webdev</category>
      <category>saas</category>
    </item>
    <item>
      <title>Ansomail Devlog #1: Replacing JavaScript with Rust for 15x Faster Email Rendering (Next.js + WASM)</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Fri, 13 Feb 2026 05:46:06 +0000</pubDate>
      <link>https://dev.to/sanjaysah/ansomail-devlog-1-replacing-javascript-with-rust-for-15x-faster-email-rendering-nextjs-wasm-3h82</link>
      <guid>https://dev.to/sanjaysah/ansomail-devlog-1-replacing-javascript-with-rust-for-15x-faster-email-rendering-nextjs-wasm-3h82</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Ansomail is an AI-powered drag-and-drop email builder I’m building in public. This week, I replaced its JavaScript rendering engine with Rust — and made it 15x faster.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I decided to do something scary: build a SaaS product in public, from scratch, sharing every win and every embarrassing error log along the way.&lt;/p&gt;

&lt;p&gt;By Day 4, I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crashed my database
&lt;/li&gt;
&lt;li&gt;Broken hot reload
&lt;/li&gt;
&lt;li&gt;Built an engine that felt painfully slow
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By Day 7, I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewritten the rendering engine in Rust
&lt;/li&gt;
&lt;li&gt;Reduced render time from &lt;strong&gt;~18ms → ~1.1ms&lt;/strong&gt; (~15x faster)
&lt;/li&gt;
&lt;li&gt;Learned that “bleeding edge” stacks come with hidden costs
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is my Week 1 retrospective building &lt;strong&gt;Ansomail&lt;/strong&gt;, an AI-powered drag-and-drop email editor.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Goal: Building a High-Performance AI Email Builder
&lt;/h2&gt;

&lt;p&gt;I’m building an email editor where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers define the &lt;strong&gt;design system&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Marketers drag-and-drop blocks&lt;/li&gt;
&lt;li&gt;AI generates content — but never breaks layout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The constraint: The preview must feel like &lt;strong&gt;Google Docs&lt;/strong&gt;. Instant.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack: Next.js 16, Bun, Postgres &amp;amp; MJML
&lt;/h2&gt;

&lt;p&gt;I deliberately chose a modern stack optimized for speed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runtime:&lt;/strong&gt; Bun
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js 16 (Turbopack)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monorepo:&lt;/strong&gt; Turborepo
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; Postgres + Drizzle ORM
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linting/Formatting:&lt;/strong&gt; Biome
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initial Rendering Engine:&lt;/strong&gt; &lt;code&gt;mjml-browser&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looked perfect on paper.&lt;/p&gt;

&lt;p&gt;Then reality happened.&lt;/p&gt;




&lt;h2&gt;
  
  
  Days 1–2: Enforcing AI Output with JSON Schema Validation
&lt;/h2&gt;

&lt;p&gt;The first architectural decision wasn’t about performance.&lt;/p&gt;

&lt;p&gt;It was about control.&lt;/p&gt;

&lt;p&gt;Instead of letting the LLM freely generate HTML, I:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forced output into a strict &lt;strong&gt;JSON Schema&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Validated structure before rendering&lt;/li&gt;
&lt;li&gt;Rejected hallucinated classes or invalid styles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the AI generates something outside the system, the update is rejected before it ever touches the UI.&lt;/p&gt;

&lt;p&gt;That constraint will save me months later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Days 3–4: The “Bleeding Edge” Tax (Next.js + Bun Issues)
&lt;/h2&gt;

&lt;p&gt;Using Bun with Next.js 16 is fast — but not always stable.&lt;/p&gt;

&lt;p&gt;Hot reload started &lt;a href="https://github.com/oven-sh/bun/issues/25639" rel="noopener noreferrer"&gt;crashing with cache component errors&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Next.js cannot guarantee that Cache Components will run as expected due to the current runtime&lt;span class="s1"&gt;'s implementation of setTimeout().
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I hit this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;FATAL: sorry, too many clients already
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a serverless dev environment, every hot reload opened a new Postgres connection.&lt;/p&gt;

&lt;p&gt;They weren’t being closed. My database choked.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fixing “Too Many Clients Already” with Proper Connection Pooling
&lt;/h2&gt;

&lt;p&gt;“Serverless” does NOT mean “Ops-less.”&lt;/p&gt;

&lt;p&gt;I implemented strict pooling and ensured a singleton pattern during development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drizzle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drizzle-orm/node-postgres&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./schema&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connectionString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DATABASE_URL is missing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;globalForDb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;globalThis&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;globalForDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_MAX_CONNECTIONS&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_MAX_CONNECTIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;idleTimeoutMillis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;connectionTimeoutMillis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;globalForDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🔌 Database: New client connected to the pool; client: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`❌ Database: Unexpected error on idle client; client: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🗑️ Database: Client removed from pool; client: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once I capped connections, everything stabilized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Dev hot reload + serverless Postgres can quietly DOS your own app.&lt;/p&gt;




&lt;h2&gt;
  
  
  Days 5–6: Implementing Optimistic UI for Instant Feedback
&lt;/h2&gt;

&lt;p&gt;I implemented &lt;strong&gt;Optimistic UI&lt;/strong&gt; for renaming templates.&lt;br&gt;


&lt;iframe class="tweet-embed" id="tweet-2021209854837158185-995" src="https://platform.twitter.com/embed/Tweet.html?id=2021209854837158185"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2021209854837158185-995');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2021209854837158185&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;User types → UI updates immediately.&lt;br&gt;
Server validates in the background.&lt;br&gt;
Failure → rollback.&lt;br&gt;
Success → seamless.&lt;/p&gt;

&lt;p&gt;That part worked beautifully.&lt;/p&gt;

&lt;p&gt;But the real bottleneck was rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial Rendering Pipeline (JavaScript + MJML)
&lt;/h2&gt;

&lt;p&gt;The original rendering pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JSON stored in DB&lt;/li&gt;
&lt;li&gt;JSON → MJML&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mjml-browser&lt;/code&gt; converts MJML → HTML&lt;/li&gt;
&lt;li&gt;HTML rendered inside an iframe&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It worked.&lt;/p&gt;

&lt;p&gt;But it averaged &lt;strong&gt;~18ms per render&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a drag-and-drop email builder, that felt sluggish.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 7: Replacing JavaScript with Rust + WebAssembly
&lt;/h2&gt;

&lt;p&gt;The bottleneck was &lt;code&gt;mjml-browser&lt;/code&gt; (pure JavaScript).&lt;/p&gt;

&lt;p&gt;So I replaced it.&lt;/p&gt;

&lt;p&gt;I integrated &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/mrml" rel="noopener noreferrer"&gt;MRML&lt;/a&gt;&lt;/strong&gt; (a Rust port of MJML) compiled to &lt;strong&gt;WebAssembly (WASM)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rust → predictable performance&lt;/li&gt;
&lt;li&gt;MRML → faster MJML parsing&lt;/li&gt;
&lt;li&gt;WASM → near-native speed in the browser&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Rust Integration Challenges
&lt;/h2&gt;

&lt;p&gt;Rust does not tolerate “almost correct.”&lt;/p&gt;

&lt;p&gt;It refused to compile my “sloppy” JSON that JavaScript had been happily ignoring.&lt;/p&gt;

&lt;p&gt;It forced me to fix my data structures.&lt;/p&gt;

&lt;p&gt;That strictness improved my architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  Performance Results: 15x Faster Email Rendering
&lt;/h2&gt;

&lt;p&gt;After integrating MRML via WASM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript Engine:&lt;/strong&gt; ~18ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust (WASM) Engine:&lt;/strong&gt; ~1.1ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s roughly a &lt;strong&gt;15x performance improvement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The preview now runs comfortably within a 16ms frame budget — effectively real-time at 60fps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unexpected Benefits of Moving to Rust
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Cleaner schema enforcement&lt;/li&gt;
&lt;li&gt;Deterministic parsing&lt;/li&gt;
&lt;li&gt;Smaller rendering bottleneck surface&lt;/li&gt;
&lt;li&gt;Future-proof performance foundation&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Lessons Learned Building a SaaS in Public (Week 1)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Bleeding-edge stacks save time — until they don’t.&lt;/li&gt;
&lt;li&gt;Serverless still requires backend discipline.&lt;/li&gt;
&lt;li&gt;Rust’s strictness is a feature, not friction.&lt;/li&gt;
&lt;li&gt;Early performance decisions compound.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Week 1 was about the foundation.&lt;/p&gt;

&lt;p&gt;Week 2 is about interaction.&lt;/p&gt;

&lt;p&gt;Now that I have a ~1ms rendering engine, I’m building the actual drag-and-drop layer on top of it.&lt;/p&gt;

&lt;p&gt;I’m documenting this entire journey publicly.&lt;/p&gt;

&lt;p&gt;If you're building with Next.js, Rust, WebAssembly, or experimenting with high-performance SaaS architecture — I’d love to connect.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ansomail is currently in development. If you're a developer or marketer who struggles with email design systems, I’d love to talk.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>nextjs</category>
      <category>rust</category>
      <category>webdev</category>
      <category>saas</category>
    </item>
    <item>
      <title>SanjayOS: I Built an AI-Powered Operating System for My Portfolio 🚀</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Thu, 29 Jan 2026 10:08:32 +0000</pubDate>
      <link>https://dev.to/sanjaysah/sanjayos-i-built-an-ai-powered-operating-system-for-my-portfolio-3bih</link>
      <guid>https://dev.to/sanjaysah/sanjayos-i-built-an-ai-powered-operating-system-for-my-portfolio-3bih</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;Hi there! 👋 I'm Sanjay Sah, a Software Engineer based in India (originally from Nepal) with over two years of experience building high-performance web applications. I currently work at Zuru Tech, where I focus on the MERN stack, Next.js, and crafting smooth user experiences.&lt;/p&gt;

&lt;p&gt;I've always felt that standard portfolio websites are... well, a bit static. They tell you about a developer, but they don't show you how they think.&lt;/p&gt;

&lt;p&gt;For this challenge, I wanted to break that mold. I wanted to express my love for complex systems, retro aesthetics, and cutting-edge AI. My goal was to build a portfolio that isn't just a document you read, but a system you explore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Portfolio
&lt;/h2&gt;

&lt;p&gt;Welcome to SanjayOS v1.0 — an AI-native Developer Operating System.&lt;/p&gt;

&lt;p&gt;Instead of navigating a menu, you boot into a desktop environment. You can drag windows, run terminal commands, and interact with an intelligent system core.&lt;/p&gt;

&lt;p&gt;Go ahead, give it a spin! The entire OS is running serverless on Google Cloud Run.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://sanjay-os-46103652818.us-central1.run.app/"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;




&lt;p&gt;&lt;em&gt;(If the interactive embed above doesn't load fully, you can &lt;a href="https://sanjay-os-46103652818.us-central1.run.app/" rel="noopener noreferrer"&gt;launch SanjayOS in a new tab here&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Building an "Operating System" in the browser is no small feat. Here is the architecture that powers SanjayOS:&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ The Tech Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js 16&lt;/a&gt; (App Router) for the core structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime:&lt;/strong&gt; &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; for ultra-fast builds and package management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; &lt;strong&gt;Tailwind CSS&lt;/strong&gt; + &lt;strong&gt;Shadcn/ui&lt;/strong&gt; (heavily customized for that "Glassmorphism" OS look).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management:&lt;/strong&gt; &lt;strong&gt;Zustand&lt;/strong&gt; to handle the complex window manager logic (z-indexing, minimizing, focusing apps).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Dockerized and hosted on &lt;strong&gt;Google Cloud Run&lt;/strong&gt; to handle Server-Side Rendering (SSR) while scaling to zero when idle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧠 The Google AI &amp;amp; Antigravity Workflow
&lt;/h3&gt;

&lt;p&gt;The heart of SanjayOS is &lt;strong&gt;Google Gemini 2.5 Flash&lt;/strong&gt;, integrated via the &lt;strong&gt;Vercel AI SDK&lt;/strong&gt;. But the &lt;em&gt;construction&lt;/em&gt; of this complex system was accelerated by &lt;strong&gt;Google Antigravity&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Built with Antigravity:&lt;/strong&gt; I used Google's &lt;strong&gt;Antigravity&lt;/strong&gt; (AI-first IDE) to scaffold the complex window management logic and rapidly prototype the Generative UI components. It acted as my "pair programmer," helping me integrate the Gemini API correctly and ensuring my prompt engineering was optimized for tool calling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System Instructions:&lt;/strong&gt; I fed the AI a structured JSON context of my entire career (resume, projects, skills). This means no RAG vector database was needed—Gemini's massive context window handles it all in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Calling:&lt;/strong&gt; The AI has permission to "control" the OS. If you ask, &lt;em&gt;"Show me Sanjay's projects,"&lt;/em&gt; Gemini doesn't just write a list; it executes a function to &lt;strong&gt;launch the Project Viewer app&lt;/strong&gt; automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'm Most Proud Of
&lt;/h2&gt;

&lt;p&gt;There are three specific achievements I'm thrilled with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The "Alive" Feeling:&lt;/strong&gt; The moment you realize the AI isn't just a text box—it's the &lt;strong&gt;OS Kernel&lt;/strong&gt;. Seeing the AI open windows and highlight UI elements based on a conversation feels like the future of web interfaces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Window Manager:&lt;/strong&gt; Building a performant, draggable, resizable window system in React was a complex challenge. Solving the "z-index stacking" (ensuring the clicked window always comes to the front) without causing re-renders was a great engineering puzzle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Cloud Run Deployment:&lt;/strong&gt; Getting a Next.js Docker container to run smoothly on Cloud Run with the correct &lt;code&gt;standalone&lt;/code&gt; output and environment variables was a huge win. It proves that personal portfolios can be both high-tech and cost-effective.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope you enjoy exploring &lt;strong&gt;SanjayOS&lt;/strong&gt; as much as I enjoyed building it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Hacking!&lt;/strong&gt; 💻✨&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>🎉 From Hackathon Idea to Super Contributor — My Hacktoberfest 2025 Journey</title>
      <dc:creator>Sanjay Kumar Sah</dc:creator>
      <pubDate>Tue, 14 Oct 2025 06:55:31 +0000</pubDate>
      <link>https://dev.to/sanjaysah/from-hackathon-idea-to-super-contributor-my-hacktoberfest-2025-journey-1g9m</link>
      <guid>https://dev.to/sanjaysah/from-hackathon-idea-to-super-contributor-my-hacktoberfest-2025-journey-1g9m</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest"&gt;2025 Hacktoberfest Writing Challenge&lt;/a&gt;: Open Source Reflections&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hackathons build projects. Open source builds people.” 💡&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hey everyone 👋 I’m &lt;strong&gt;Sanjay Kumar Sah&lt;/strong&gt;, and this Hacktoberfest was more than just a coding challenge — it was a &lt;em&gt;journey of growth, collaboration, and community.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I started with a small idea from a hackathon project, and ended up becoming a &lt;strong&gt;Super Contributor&lt;/strong&gt; with &lt;strong&gt;6 merged PRs&lt;/strong&gt;, &lt;strong&gt;open-source growth&lt;/strong&gt;, and even the official &lt;strong&gt;Hacktoberfest T-shirt! 🎽&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s the story 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🌱 The Beginning: Humanizing AI Text
&lt;/h2&gt;

&lt;p&gt;It all began with the &lt;a href="https://aihumanizehack.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Humanizing AI Text Hackathon&lt;/strong&gt;&lt;/a&gt;, organized by &lt;a href="https://raptors.dev" rel="noopener noreferrer"&gt;Hackathon Raptors&lt;/a&gt;.&lt;br&gt;
My goal was simple but exciting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make AI-generated text feel more human — natural, emotional, and contextual.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The result?&lt;br&gt;
My project &lt;strong&gt;&lt;a href="https://github.com/sanjaysah101/humanize-ai" rel="noopener noreferrer"&gt;Humanize-AI&lt;/a&gt;&lt;/strong&gt; was born.&lt;/p&gt;

&lt;p&gt;And guess what — it &lt;strong&gt;ranked 3rd place! 🥉&lt;/strong&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%2F5xlqsjzrbguek4ke6ada.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%2F5xlqsjzrbguek4ke6ada.png" alt="Certificate of Appreciation" width="634" height="890"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That recognition gave me the push to take it further — beyond the hackathon and into the &lt;strong&gt;open-source world&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Turning a Hackathon Project into an Open-Source Repo
&lt;/h2&gt;

&lt;p&gt;After the hackathon, I decided to open-source &lt;strong&gt;Humanize-AI&lt;/strong&gt; so others could contribute, improve, and learn from it.&lt;/p&gt;

&lt;p&gt;The response was incredible:&lt;br&gt;
⭐ &lt;strong&gt;26 stars&lt;/strong&gt;&lt;br&gt;
🍴 &lt;strong&gt;19 forks&lt;/strong&gt;&lt;br&gt;
💬 and real collaboration from developers around the world.&lt;/p&gt;

&lt;p&gt;It was the first time I saw how powerful open source can be — how a small idea can grow when shared publicly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Open source isn’t just about publishing your code — it’s about building a community around your ideas.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🤝 From Contributor → Collaborator
&lt;/h2&gt;

&lt;p&gt;This year, I also became an official &lt;strong&gt;contributor at &lt;a href="https://github.com/NexGenStudioDev" rel="noopener noreferrer"&gt;NexGenStudioDev&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But instead of just submitting PRs, I started doing &lt;strong&gt;code reviews&lt;/strong&gt; — and that changed everything.&lt;/p&gt;

&lt;p&gt;Reviewing others’ code helped me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand new perspectives 👀&lt;/li&gt;
&lt;li&gt;Learn clean coding practices 💡&lt;/li&gt;
&lt;li&gt;Communicate better as a developer 🧠&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Writing code makes you a contributor.&lt;br&gt;
Reviewing code makes you a collaborator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you’ve never reviewed a PR before, I highly recommend it.&lt;br&gt;
It’s the fastest way to level up your technical and communication skills.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 The Finish Line: Super Contributor Badge
&lt;/h2&gt;

&lt;p&gt;Completing &lt;strong&gt;6 pull requests&lt;/strong&gt; this Hacktoberfest earned me the &lt;strong&gt;Super Contributor Badge 🏅&lt;/strong&gt; — and the classic &lt;strong&gt;Hacktoberfest T-shirt 🎽&lt;/strong&gt; (the best kind of swag 😄).&lt;/p&gt;

&lt;p&gt;But beyond the badge and T-shirt, what I really earned was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confidence to contribute anywhere 💪&lt;/li&gt;
&lt;li&gt;Deeper respect for maintainers 🛠️&lt;/li&gt;
&lt;li&gt;And lifelong connections in the developer community 🌐&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📚 What I Learned Along the Way
&lt;/h2&gt;

&lt;p&gt;Here are my top takeaways from this journey:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start small.&lt;/strong&gt;&lt;br&gt;
You don’t need a huge project — even a simple idea can inspire others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open-source early.&lt;/strong&gt;&lt;br&gt;
Don’t wait for perfection. Share your work and invite collaboration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Review more.&lt;/strong&gt;&lt;br&gt;
Reviewing others’ code teaches you more than writing your own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Engage with the community.&lt;/strong&gt;&lt;br&gt;
Hacktoberfest is about people, not just pull requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Celebrate progress.&lt;/strong&gt;&lt;br&gt;
Every PR, every merge, every star — it all counts. 🎉&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  💬 What’s Next?
&lt;/h2&gt;

&lt;p&gt;I plan to keep improving &lt;strong&gt;Humanize-AI&lt;/strong&gt; with new features and better humanization techniques for AI-generated text.&lt;br&gt;
If you’re interested in NLP, prompt engineering, or AI communication — I’d love to collaborate!&lt;/p&gt;

&lt;p&gt;👉 Check it out here: &lt;a href="https://github.com/sanjaysah101/humanize-ai" rel="noopener noreferrer"&gt;github.com/sanjaysah101/humanize-ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you’re preparing for &lt;strong&gt;Hacktoberfest 2026&lt;/strong&gt;, here’s my advice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don’t just aim to complete PRs — aim to connect, learn, and give back.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🫶 Thanks to the Community
&lt;/h2&gt;

&lt;p&gt;A huge shoutout to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/NexGenStudioDev" rel="noopener noreferrer"&gt;@NexGenStudioDev&lt;/a&gt; team&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/company/hackathon-raptors/" rel="noopener noreferrer"&gt;Hackathon Raptors&lt;/a&gt; organizers for Humanizing AI Text&lt;/li&gt;
&lt;li&gt;Every contributor who starred, forked, or opened an issue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You all made this journey memorable.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏆 TL;DR – My Hacktoberfest 2025 in Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Highlights&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hackathon&lt;/td&gt;
&lt;td&gt;Humanizing AI Text (Ranked 3rd 🥉)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repo&lt;/td&gt;
&lt;td&gt;26+⭐ + 19+🍴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contributions&lt;/td&gt;
&lt;td&gt;6+ PRs merged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Roles&lt;/td&gt;
&lt;td&gt;Contributor + Reviewer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rewards&lt;/td&gt;
&lt;td&gt;Super Contributor Badge 🏅 + Official T-shirt 🎽&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  💌 Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Hacktoberfest isn’t just a celebration of code — it’s a celebration of collaboration.&lt;br&gt;
If you’ve ever hesitated to start, remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The best time to contribute to open source was yesterday. The next best time is today.”&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>devchallenge</category>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
