<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: BarbWire</title>
    <description>The latest articles on Forem by BarbWire (@barbwire1).</description>
    <link>https://forem.com/barbwire1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1003474%2F406e9147-1bef-4653-880e-163cd4b80333.png</url>
      <title>Forem: BarbWire</title>
      <link>https://forem.com/barbwire1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/barbwire1"/>
    <language>en</language>
    <item>
      <title>Tired of setting up environment for Lib creation?</title>
      <dc:creator>BarbWire</dc:creator>
      <pubDate>Tue, 19 May 2026 11:35:21 +0000</pubDate>
      <link>https://forem.com/barbwire1/tired-of-setting-up-environment-for-lib-creation-3ilm</link>
      <guid>https://forem.com/barbwire1/tired-of-setting-up-environment-for-lib-creation-3ilm</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/barbwire1/built-a-tiny-cli-to-scaffold-vite-npm-libraries-live-consumer-apps-5016" class="crayons-story__hidden-navigation-link"&gt;From Frustration to Automation&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/barbwire1" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F1003474%2F406e9147-1bef-4653-880e-163cd4b80333.png" alt="barbwire1 profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/barbwire1" class="crayons-story__secondary fw-medium m:hidden"&gt;
              BarbWire
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                BarbWire
                
              
              &lt;div id="story-author-preview-content-3694381" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/barbwire1" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F1003474%2F406e9147-1bef-4653-880e-163cd4b80333.png" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;BarbWire&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/barbwire1/built-a-tiny-cli-to-scaffold-vite-npm-libraries-live-consumer-apps-5016" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/barbwire1/built-a-tiny-cli-to-scaffold-vite-npm-libraries-live-consumer-apps-5016" id="article-link-3694381"&gt;
          From Frustration to Automation
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/npm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;npm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cli"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cli&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/vite"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vite&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/barbwire1/built-a-tiny-cli-to-scaffold-vite-npm-libraries-live-consumer-apps-5016#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>cli</category>
      <category>npm</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>From Frustration to Automation</title>
      <dc:creator>BarbWire</dc:creator>
      <pubDate>Mon, 18 May 2026 14:55:43 +0000</pubDate>
      <link>https://forem.com/barbwire1/built-a-tiny-cli-to-scaffold-vite-npm-libraries-live-consumer-apps-5016</link>
      <guid>https://forem.com/barbwire1/built-a-tiny-cli-to-scaffold-vite-npm-libraries-live-consumer-apps-5016</guid>
      <description>&lt;h2&gt;
  
  
  Overcoming Boilerplate Fatigue in JavaScript Libraries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The architectural journey behind building a lightweight workspace wizard for wiring and testing JS libraries
&lt;/h3&gt;

&lt;p&gt;Every single time I wanted to build a small utility or a custom JavaScript library, the exact same headache occurred. I would spend the first hours tweaking configuration files and handling local package symlinks instead of writing actual code — or even worse, I would start to code my library and come to the point to test it, only to have my creative process completely interrupted by setup chores.&lt;/p&gt;

&lt;p&gt;After doing this for the fifth time, I had enough. I just wanted to build features without losing my momentum. Here is the story of my journey automating this pain away, the technical hurdles of writing a zero-dependency CLI wrapper, and how I plan to transform the setup into an extensible, plugin-based architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Frustration of Manual Setup
&lt;/h3&gt;

&lt;p&gt;Setting up a modern JavaScript library with a reliable local testing loop is far from trivial these days. To get a clean development environment, I found myself manually repeating these exact steps every single time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Configuring Vite Multi-Entry Mode&lt;/strong&gt;: Wrestling with Rollup options to ensure both ESM and CJS bundles build correctly with proper subpath exports (e.g., &lt;code&gt;my-lib/modifiers&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Symlink Nightmare&lt;/strong&gt;: Setting up a local, lightweight test app in the same folder and forcing it to consume the local library package. Doing this dependency-free without &lt;code&gt;npm link&lt;/code&gt; breaking down constantly is a massive chore.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Watch Mode Battle&lt;/strong&gt;: Making sure that changes in the library instantly trigger updates in the test app via a seamless file watcher.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Testing Setup&lt;/strong&gt;: Configuring a quick test runner (&lt;code&gt;index.test.js&lt;/code&gt; using Vitest) inside the library structure right away so testing isn't an afterthought.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This repetitive setup felt like factory assembly work. It completely drained my creative energy before the actual project even started.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Process: Building a Zero-Dependency Wrapper in Pure Node.js
&lt;/h3&gt;

&lt;p&gt;When I decided to write a CLI tool to automate this, I made a strict rule for myself: &lt;strong&gt;zero third-party dependencies&lt;/strong&gt;. I didn’t want my tool to pull down hundreds of megabytes of external packages just to scaffold a project. &lt;/p&gt;

&lt;p&gt;This meant skipping trendy CLI frameworks like Clack or Inquirer. Instead, I built the interactive wizard using pure, native Node.js modules like &lt;code&gt;readline&lt;/code&gt;, &lt;code&gt;fs&lt;/code&gt;, and &lt;code&gt;child_process&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Wrestling with native Node APIs brought some unique engineering challenges:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Intercepting Vite's Internal Automation
&lt;/h4&gt;

&lt;p&gt;Instead of reinventing the wheel, I wanted to delegate the foundation of the project scaffolding to Vite's official creator tool via &lt;code&gt;child_process&lt;/code&gt;. However, automation workflows hate interactive prompts. &lt;/p&gt;

&lt;p&gt;During execution, Vite's initializer tries to take over the terminal control loop and eagerly asks the user if they want to run or install immediately. If a user says "yes", it interrupts my wrapper script, stopping it from performing vital post-scaffolding tasks. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; I had to structure the tool's documentation and internal flow to explicitly instruct users to answer &lt;strong&gt;NO&lt;/strong&gt; to Vite's immediate run prompt. By preventing Vite from running its install step prematurely, my script safely regains control to execute the clean-up, structure generation, folder renaming, and global symlinking using native &lt;code&gt;fs&lt;/code&gt; commands.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. The Package Manager Dilemma (npm vs. pnpm vs. yarn)
&lt;/h4&gt;

&lt;p&gt;I didn't want to force developers into a single ecosystem. Handling dependencies across &lt;code&gt;npm&lt;/code&gt;, &lt;code&gt;pnpm&lt;/code&gt;, and &lt;code&gt;yarn&lt;/code&gt; meant translating execution commands dynamically under the hood. Managing global symlinks programmatically across three different CLI APIs using raw Node subprocesses required a lot of trial, error, and meticulous string parsing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Result: A Lightweight Monorepo Workspace
&lt;/h3&gt;

&lt;p&gt;The final product of this engineering journey is &lt;strong&gt;create-lib-workspace&lt;/strong&gt;. It automatically scaffolds a perfectly wired development monorepo workspace with zero overhead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;my-project/
├── app/                  &lt;span class="c"&gt;# Pure static consumer app to see your lib in action&lt;/span&gt;
│   ├── index.html        
│   └── main.js           &lt;span class="c"&gt;# Directly imports and tests your library locally&lt;/span&gt;
└── core-lib/             &lt;span class="c"&gt;# Your actual Library (Vite-powered)&lt;/span&gt;
    ├── src/
    │   ├── index.js      &lt;span class="c"&gt;# Main entry point&lt;/span&gt;
    │   ├── index.test.js &lt;span class="c"&gt;# Vitest-ready testing structure&lt;/span&gt;
    │   └── modifiers/    &lt;span class="c"&gt;# Pre-configured secondary entry point sub-module&lt;/span&gt;
    ├── package.json      &lt;span class="c"&gt;# Hardcoded with proper ESM/CJS exports&lt;/span&gt;
    └── vite.config.js    &lt;span class="c"&gt;# Pre-configured multi-entry build setup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Features of the Architecture:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Interactive Wizard&lt;/strong&gt;: Built entirely on native Node.js APIs to guide you through naming and setup.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Multi-Package Manager Support&lt;/strong&gt;: Seamless compatibility with &lt;strong&gt;pnpm&lt;/strong&gt;, &lt;strong&gt;npm&lt;/strong&gt;, or &lt;strong&gt;yarn&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Automated Symlinking&lt;/strong&gt;: Connects the test app to the library completely dependency-free, creating an instant local testing loop.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Multi-Entry &amp;amp; Subpaths&lt;/strong&gt;: The generated boilerplate comes with a &lt;code&gt;modifiers/&lt;/code&gt; subpath pre-configured so you can see exactly how to export separate modules from day one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  See it in Action
&lt;/h3&gt;

&lt;p&gt;You can run it directly right now using executors without a global install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Using pnpm&lt;/span&gt;
pnpm dlx create-lib-workspace

&lt;span class="c"&gt;# Using npm&lt;/span&gt;
npx create-lib-workspace

&lt;span class="c"&gt;# Using yarn&lt;/span&gt;
yarn dlx create-lib-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Remember: When Vite asks if you want to run or install immediately, hit **NO&lt;/em&gt;* so the native script can finish wiring the workspace components together!)*&lt;/p&gt;

&lt;p&gt;Once it completes, you simply spin up the library watcher in one terminal window (&lt;code&gt;npm run watch&lt;/code&gt;) and the test app server in another (&lt;code&gt;npx vite --open&lt;/code&gt;), giving you a real-time, hot-reloading library development environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next Steps: Moving to a True Plugin Architecture
&lt;/h3&gt;

&lt;p&gt;While the current tool solves the immediate boilerplate fatigue using hardcoded internal structures, the next major evolutionary step for this package is &lt;strong&gt;extensibility&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Instead of keeping everything bundled inside a single, rigid core configuration, I want to redesign the package to support an isolated &lt;strong&gt;plugin ecosystem&lt;/strong&gt;. The core library package will handle the baseline monorepo lifecycle, while specialized features will be separated into their own dedicated dependencies. &lt;/p&gt;

&lt;p&gt;Under this new architecture, if a user wants to build a specialized workspace, they will be able to pull in independent ecosystem plugins. This will allow the community to write and hook their own plugins directly into the core execution engine, transforming it from a static template generator into a modular library workbench.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lessons Learned &amp;amp; Open Source
&lt;/h3&gt;

&lt;p&gt;Building this taught me a lot about the friction points in modern JavaScript tooling, and reminded me how powerful native Node.js can be without a heavy &lt;code&gt;node_modules&lt;/code&gt; folder backing it up. &lt;/p&gt;

&lt;p&gt;You can check out the full source code and documentation on GitHub:&lt;br&gt;
&lt;a href="https://github.com" rel="noopener noreferrer"&gt;🔗 GitHub Repository: create-lib-workspace&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am really curious to hear from other developers: &lt;strong&gt;How do you approach designing plugin systems for CLI utilities?&lt;/strong&gt; What kind of independent plugins would you want to see built for a core workspace setup like this? Let's discuss below!&lt;/p&gt;

</description>
      <category>npm</category>
      <category>cli</category>
      <category>vite</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
