<?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: Pooya Golchian</title>
    <description>The latest articles on Forem by Pooya Golchian (@pooyagolchian).</description>
    <link>https://forem.com/pooyagolchian</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%2F78949%2Fcb6a9990-c5ed-4158-ab22-6b65396dabc0.jpeg</url>
      <title>Forem: Pooya Golchian</title>
      <link>https://forem.com/pooyagolchian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pooyagolchian"/>
    <language>en</language>
    <item>
      <title>WhatsApp and Telegram Automation in Dubai: AI-Powered Bots for Business</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:10:06 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/whatsapp-and-telegram-automation-in-dubai-ai-powered-bots-for-business-6jm</link>
      <guid>https://forem.com/pooyagolchian/whatsapp-and-telegram-automation-in-dubai-ai-powered-bots-for-business-6jm</guid>
      <description>&lt;h1&gt;
  
  
  WhatsApp and Telegram Automation in Dubai
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;3.2 billion people use WhatsApp and Telegram daily. Your customers are already there. Your business should be too.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Dubai, WhatsApp is not just a messaging app. It is the primary communication channel for business interactions across real estate, retail, hospitality, healthcare, and professional services. Customers expect instant responses. They expect to book, buy, and resolve issues without downloading another app or navigating another website.&lt;/p&gt;

&lt;p&gt;Pooya Golchian builds intelligent bots and automation workflows that turn WhatsApp and Telegram into production-grade business channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Messaging Automation Matters for Dubai Businesses
&lt;/h2&gt;

&lt;p&gt;Email open rates in the Gulf region average 18 to 22 percent. WhatsApp message open rates exceed 95 percent. The gap is not marginal. It is a completely different channel dynamic.&lt;/p&gt;

&lt;p&gt;When a potential customer sends your business a WhatsApp message at 11 PM, the response window determines whether you close the deal or lose it to a competitor who replies faster. Manual teams cannot cover every hour. AI-powered bots can.&lt;/p&gt;

&lt;p&gt;Pooya Golchian designs these systems so your business responds instantly, collects information intelligently, and routes conversations to humans only when the situation demands it.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;WhatsApp Business API integration&lt;/strong&gt; connects your business to the official WhatsApp platform for transactional messages, customer support, interactive catalogs, and notification broadcasts at scale. This is not the basic WhatsApp Business App. It is the enterprise API that supports unlimited concurrent conversations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Telegram bot development&lt;/strong&gt; covers custom bots with inline keyboards, payment processing, group management, channel automation, and webhook-driven workflows. Telegram's bot ecosystem is more flexible than WhatsApp's, making it ideal for internal team tools and technical audiences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-powered conversations&lt;/strong&gt; use LLM-driven chatbots trained on your business data. These bots understand context, handle multi-turn conversations naturally, and know when to escalate to a human agent. They are not scripted decision trees. They are conversational AI that improves with every interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;n8n workflow automation&lt;/strong&gt; connects messaging platforms to your entire tech stack through a visual workflow builder. CRM updates trigger WhatsApp messages. Form submissions start Telegram notification chains. Payment confirmations send receipts automatically. No-code configuration for business users. Custom code nodes for complex logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-platform integration&lt;/strong&gt; bridges WhatsApp and Telegram with your existing CRM, helpdesk, e-commerce platform, payment gateway, and analytics systems. Everything flows into a single view.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases That Drive Revenue
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Customer support automation&lt;/strong&gt; reduces ticket volume by 60 to 80 percent. Bots handle FAQs, order tracking, return requests, and account inquiries around the clock. Human agents handle only the conversations that require judgment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lead generation and qualification&lt;/strong&gt; captures leads through conversational forms on WhatsApp. The bot qualifies prospects by asking the right questions, scores them based on responses, and routes hot leads to your sales team in real time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Order and delivery notifications&lt;/strong&gt; send transactional WhatsApp messages for order confirmation, shipping updates, delivery tracking, and post-delivery feedback collection. Open rates far exceed email for these critical touchpoints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Appointment and booking bots&lt;/strong&gt; let customers schedule, reschedule, and cancel through WhatsApp or Telegram with calendar integration and automated reminders. Clinics, salons, consultancies, and service businesses see immediate reduction in no-shows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E-commerce catalog bots&lt;/strong&gt; enable product browsing, cart management, and checkout flows entirely within WhatsApp, integrated with Shopify, WooCommerce, or custom backends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internal team automation&lt;/strong&gt; uses Telegram bots for deployment triggers, monitoring alerts, daily standup automation, and cross-team notifications for engineering and operations teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology Stack
&lt;/h2&gt;

&lt;p&gt;WhatsApp Business API, Telegram Bot API, n8n, Node.js, Python, LangChain, OpenAI, Twilio, Baileys, grammy.js, Redis, PostgreSQL, Webhook Processing, REST APIs, Docker, and Supabase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Automating
&lt;/h2&gt;

&lt;p&gt;Tell Pooya Golchian about your business, your customers, and your messaging goals. He will design the automation architecture and build it production-ready.&lt;/p&gt;

&lt;p&gt;Based in Dubai. Serving businesses across the UAE and GCC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pooyagolchian.github.io/contact" rel="noopener noreferrer"&gt;Discuss your automation →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>whatsapp</category>
      <category>telegram</category>
      <category>automation</category>
      <category>chatbot</category>
    </item>
    <item>
      <title>vue-star-rate: Zero-Dependency Vue 3.5+ Star Rating Component</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:09:51 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/vue-star-rate-zero-dependency-vue-35-star-rating-component-m60</link>
      <guid>https://forem.com/pooyagolchian/vue-star-rate-zero-dependency-vue-35-star-rating-component-m60</guid>
      <description>&lt;p&gt;Star ratings sound simple until you ship them to production. Then you need half-star precision, accessible keyboard navigation, RTL layouts, flexible icon sources, and correct ARIA semantics. I built &lt;strong&gt;vue-star-rate&lt;/strong&gt; to handle all of that in a single zero-dependency Vue 3.5+ component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pooyagolchian.github.io/vue-star-rate/" rel="noopener noreferrer"&gt;Documentation &amp;amp; Live Demo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add vue-js-star-rating
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requires Vue 3.5+. Uses &lt;code&gt;defineModel&lt;/code&gt; and &lt;code&gt;useTemplateRef&lt;/code&gt;, both stable in Vue 3.5. Zero runtime dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-js-star-rating/dist/style.css&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;rating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Half-Star Ratings
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;The visual renderer fills exactly half of a star glyph. The emitted value is a decimal like &lt;code&gt;3.5&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Size Presets
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;  &lt;span class="c"&gt;&amp;lt;!-- 16px --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- 20px --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- 24px, default --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- 32px --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- 40px --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Custom pixels --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom Colors
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Icon Providers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Lucide (requires lucide-vue-next) --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- FontAwesome (requires @fortawesome/fontawesome-free) --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Fully custom SVG via slot --&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Read-Only Mode
&lt;/h2&gt;

&lt;p&gt;For review cards, dashboards, and product pages:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Keyboard Navigation
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arrow Right / Up&lt;/td&gt;
&lt;td&gt;Increase rating&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arrow Left / Down&lt;/td&gt;
&lt;td&gt;Decrease rating&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Home&lt;/td&gt;
&lt;td&gt;Set to minimum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;End&lt;/td&gt;
&lt;td&gt;Set to maximum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1–9&lt;/td&gt;
&lt;td&gt;Jump to specific value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Reset to minimum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The component uses &lt;code&gt;role="group"&lt;/code&gt;, &lt;code&gt;aria-pressed&lt;/code&gt; on each star, and an &lt;code&gt;aria-live&lt;/code&gt; counter, fully WCAG 2.2 compliant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooltips and Counters
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Full Configuration Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueStarRate&lt;/span&gt;
  &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"rating"&lt;/span&gt;
  &lt;span class="na"&gt;:max-stars=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;
  &lt;span class="na"&gt;:allow-half=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="na"&gt;:show-counter=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="na"&gt;:show-tooltip=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;"lg"&lt;/span&gt;
  &lt;span class="na"&gt;:colors=&lt;/span&gt;&lt;span class="s"&gt;"{ empty: '#27272a', filled: '#fbbf24', hover: '#fcd34d', half: '#fbbf24' }"&lt;/span&gt;
  &lt;span class="na"&gt;:animation=&lt;/span&gt;&lt;span class="s"&gt;"{ enabled: true, duration: 200, type: 'scale' }"&lt;/span&gt;
  &lt;span class="na"&gt;:clearable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"(val, old) =&amp;gt; console.log(val, old)"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Props Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prop&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;v-model&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rating value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxStars&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum stars&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowHalf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Half-star precision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xs / sm / md / lg / xl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Size preset&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;readonly&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Display-only mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clearable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clear button&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showCounter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric counter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showTooltip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hover tooltips&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rtl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Right-to-left layout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iconProvider&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;custom / lucide / fontawesome&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;custom&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Icon source&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Programmatic Control
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ratingRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;VueStarRate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;ratingRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;ratingRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;setRating&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ratingRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;getRating&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;ratingRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Migration from v2
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;v2&lt;/th&gt;
&lt;th&gt;v3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lucideIcons&lt;/code&gt; prop&lt;/td&gt;
&lt;td&gt;&lt;code&gt;icon-provider="lucide"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;role="slider"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;role="group"&lt;/code&gt; (WCAG 2.2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;animation: { scale: 1.15 }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;animation: { type: 'scale' }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vue &lt;code&gt;^3.3.0&lt;/code&gt; peer dep&lt;/td&gt;
&lt;td&gt;Vue &lt;code&gt;^3.5.0&lt;/code&gt; peer dep&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;a href="https://github.com/pooyagolchian/vue-star-rate" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://www.npmjs.com/package/vue-js-star-rating" rel="noopener noreferrer"&gt;npm&lt;/a&gt; · &lt;a href="https://pooyagolchian.github.io/vue-star-rate/" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>a11y</category>
    </item>
    <item>
      <title>vue-multiple-themes v4: Dynamic Multi-Theme Support for Vue 2 &amp; 3</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:09:35 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/vue-multiple-themes-v4-dynamic-multi-theme-support-for-vue-2-3-p8g</link>
      <guid>https://forem.com/pooyagolchian/vue-multiple-themes-v4-dynamic-multi-theme-support-for-vue-2-3-p8g</guid>
      <description>&lt;p&gt;I have been building UIs with Vue for years and one pattern comes up constantly, you need more than dark/light. Clients want seasonal themes, brand-specific palettes, and accessibility-compliant contrasts. I extracted all of that into a standalone, typed library: &lt;strong&gt;vue-multiple-themes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pooyagolchian.github.io/vue-multiple-themes/" rel="noopener noreferrer"&gt;Full Documentation &amp;amp; Demo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Solves
&lt;/h2&gt;

&lt;p&gt;The standard approach is toggling a &lt;code&gt;.dark&lt;/code&gt; class on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; and writing a wall of CSS overrides. That works for two themes. Scale to three or more and you get duplicated selectors, fragile specificity battles, and no tooling for generating accessible palettes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vue-multiple-themes&lt;/code&gt; replaces that with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CSS custom properties (&lt;code&gt;--vmt-*&lt;/code&gt;)&lt;/strong&gt; injected at the target element: every theme is a swap of values at one cascade layer&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;reactive &lt;code&gt;useTheme()&lt;/code&gt; composable&lt;/strong&gt; accessible anywhere in the component tree&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7 preset themes&lt;/strong&gt; ready to use immediately&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;TailwindCSS plugin&lt;/strong&gt; that exposes those tokens as Tailwind utilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WCAG color utilities&lt;/strong&gt; for contrast checking, mixing, and palette generation: all SSR-safe&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add vue-multiple-themes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requires Vue 2.7+ or Vue 3. Zero runtime dependencies beyond Vue itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start: Vue 3
&lt;/h2&gt;

&lt;p&gt;Register the plugin once in &lt;code&gt;main.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VueMultipleThemesPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;defaultTheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attribute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&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;Then use &lt;code&gt;useTheme()&lt;/code&gt; anywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;currentTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;themes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTheme&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PRESET_THEMES&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"t in themes"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"t.name"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"setTheme(t.name)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  CSS Custom Properties
&lt;/h2&gt;

&lt;p&gt;Once a theme is active, &lt;code&gt;--vmt-*&lt;/code&gt; variables are available on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;. Style components against them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--vmt-background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--vmt-foreground&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--vmt-border&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;Switching themes updates every component instantly, no re-renders required.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 7 Preset Themes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Character&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;light&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clean white + indigo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dark&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dark gray + violet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sepia&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Warm parchment browns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ocean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deep sea blues&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;forest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rich greens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sunset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Warm oranges &amp;amp; reds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;winter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Icy blues &amp;amp; whites&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Dynamic Theme Generation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dark&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateThemePair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#6366f1&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;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateColorScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#6366f1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ideal for SaaS products where each tenant sets a brand color and the full UI adapts automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  TailwindCSS Integration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createVmtPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-multiple-themes/tailwind&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;createVmtPlugin&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-vmt-surface text-vmt-foreground border-vmt-border"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Themes itself automatically on switch
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  WCAG Utilities
&lt;/h2&gt;

&lt;p&gt;Pure functions, no DOM, fully SSR-safe, tree-shakeable:&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="nf"&gt;contrastRatio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#6366f1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 4.54&lt;/span&gt;
&lt;span class="nf"&gt;autoContrast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#6366f1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;              &lt;span class="c1"&gt;// '#ffffff'&lt;/span&gt;
&lt;span class="nf"&gt;checkContrast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#6366f1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// { ratio: 4.54, aa: true, aaa: false, aaLarge: true, aaaLarge: true }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;useTheme()&lt;/code&gt; API
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;themes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ThemeDefinition[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;preset list&lt;/td&gt;
&lt;td&gt;Available themes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;defaultTheme&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;light&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Initial theme&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strategy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;attribute / class / both&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;attribute&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;DOM application strategy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;persist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Save to localStorage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;storageKey&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vmt-theme&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;localStorage key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Returns: &lt;code&gt;{ currentTheme, currentName, themes, setTheme, nextTheme, prevTheme }&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Vue 2 Support
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VueMultipleThemesPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;defaultTheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&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;&lt;a href="https://github.com/pooyagolchian/vue-multiple-themes" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://www.npmjs.com/package/vue-multiple-themes" rel="noopener noreferrer"&gt;npm&lt;/a&gt; · &lt;a href="https://pooyagolchian.github.io/vue-multiple-themes/" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>css</category>
    </item>
    <item>
      <title>Vibe Coding in 2026: $9.2B Cursor, 92% HumanEval, and the End of Boilerplate</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:09:20 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/vibe-coding-in-2026-92b-cursor-92-humaneval-and-the-end-of-boilerplate-161h</link>
      <guid>https://forem.com/pooyagolchian/vibe-coding-in-2026-92b-cursor-92-humaneval-and-the-end-of-boilerplate-161h</guid>
      <description>&lt;p&gt;$9.2 billion. That is what investors valued Cursor's parent company Anysphere at in September 2025, after a $400M Series B. Bolt.new hit $2.1B. Lovable raised at $180M. Combined venture capital into vibe coding platforms exceeded $1 billion in 2025 alone.&lt;/p&gt;

&lt;p&gt;Vibe coding stopped being a novelty sometime around Q2 2025. It became the default workflow. Andrej Karpathy coined the term in early 2024 to describe a paradigm where you tell the AI what you want in plain English and it writes the code. By March 2026, 82% of developers use or plan to use AI coding tools (GitHub Developer Survey). Enterprise adoption grew 340%. Non-technical user adoption surged 520% year-over-year.&lt;/p&gt;

&lt;p&gt;This article breaks down the platforms, the pricing, the benchmarks, and the actual productivity math.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Market Numbers
&lt;/h2&gt;

&lt;p&gt;The total AI code generation market reached $4.2 billion in 2025 (MarketsandMarkets). The vibe coding segment, platforms that generate complete applications from natural language, now represents 25-30% of that market at an estimated $3-4.5 billion.&lt;/p&gt;

&lt;p&gt;Growth projections sit at 38-42% CAGR through 2030, when the total market should hit $25 billion. The vibe coding segment grows faster than the broader market because it captures non-developer users that traditional coding assistants never reached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform Landscape and Valuations
&lt;/h2&gt;

&lt;p&gt;Six platforms dominate the market. Each targets a different workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cursor (Anysphere)&lt;/strong&gt; raised $400M at a $9.2B valuation. It is a full IDE replacement built on VS Code's foundation with multi-agent AI orchestration for code generation, debugging, and refactoring. Cursor maintains separate planning, editing, and terminal agents communicating through a shared context window of up to 100,000 tokens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt; holds the largest user base at 1.8 million paying subscribers and 55% market share among AI tool users. It operates inside existing IDEs rather than replacing them. The $10/month individual plan makes it the most accessible entry point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bolt.new (StackBlitz)&lt;/strong&gt; runs entirely in the browser through WebContainers. No local setup. You describe an application, it generates and runs the code live. The $2.1B valuation reflects strong traction with designers and product managers who prototype without touching a terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;v0 (Vercel)&lt;/strong&gt; specializes in frontend UI generation. 2 million users by Q1 2026 generate React components, landing pages, and entire application layouts from text descriptions. It integrates directly with Vercel's deployment pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lovable&lt;/strong&gt; targets full-stack web application generation with Supabase as the default backend. The $180M valuation after a $35M Series A positions it for teams that want complete applications, not just code snippets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replit Agent&lt;/strong&gt; processes over 50 million code executions monthly in its cloud environment. The agent handles project setup, dependency management, deployment, and iteration in a single conversational thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing Breakdown
&lt;/h2&gt;

&lt;p&gt;Every platform uses tiered pricing. The free tiers are generous enough for evaluation. The enterprise tiers add team management, SSO, and usage controls.&lt;/p&gt;

&lt;p&gt;GitHub Copilot offers the lowest entry point at $10/month. Cursor and Bolt.new cluster at $20/month for individual Pro plans. Enterprise pricing diverges sharply. Cursor charges $90/month per seat, while GitHub Copilot Enterprise sits at $39/month.&lt;/p&gt;

&lt;p&gt;The hidden costs matter more than subscription fees. Integration time, team training, and infrastructure for self-hosted models add 15-30% to the visible platform cost. Organizations running hybrid setups with both cloud and local models should budget for the operational overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Model Benchmarks
&lt;/h2&gt;

&lt;p&gt;The model powering the platform determines code quality. HumanEval, the standard benchmark for code generation, reveals meaningful differences.&lt;/p&gt;

&lt;p&gt;Claude 3.5 Sonnet leads at 92.4%, which translates to generating correct solutions for 92 out of 100 programming challenges on the first attempt. GPT-4o follows at 90.2%. Google's Gemini Code Assist scores 88.5%. The gap between commercial and open source narrows. DeepSeek Coder achieves 86.7% at a fraction of the inference cost.&lt;/p&gt;

&lt;p&gt;Context window size determines how much of your codebase the model can understand simultaneously. Claude 3.5 Sonnet supports 200K tokens. GPT-4o handles 128K. Larger context windows mean better suggestions because the model sees more of your project structure, dependencies, and coding patterns.&lt;/p&gt;

&lt;p&gt;Multi-agent architectures in platforms like Cursor assign different models to different tasks. A planning agent decomposes your request. An editing agent generates code. A review agent catches errors. This specialization outperforms single-model approaches for complex multi-file changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Productivity Impact
&lt;/h2&gt;

&lt;p&gt;The research data comes from multiple sources: a 2024 Posit study, Microsoft's internal engineering metrics, and aggregated developer surveys.&lt;/p&gt;

&lt;p&gt;Coding tasks complete 30-55% faster with AI assistance. The range depends on task complexity. Routine CRUD operations and boilerplate see the highest gains. Novel algorithm design shows smaller improvements because the model lacks context that the developer holds in their head.&lt;/p&gt;

&lt;p&gt;Documentation responds best to vibe coding at a 65% time reduction. The AI generates docstrings, README sections, and API documentation from existing code with minimal correction needed. Sprint completion improves 40% according to Microsoft's internal data.&lt;/p&gt;

&lt;p&gt;Code defects drop 15% with AI-assisted review. This counterintuitive result happens because the AI catches patterns that developers overlook during manual review, particularly null checks, edge cases in error handling, and inconsistent type usage.&lt;/p&gt;

&lt;p&gt;Startups report 2-3x faster MVP development. The advantage compounds when the founding team includes non-technical members who can iterate on prototypes directly using platforms like v0 or Lovable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enterprise Adoption Trajectory
&lt;/h2&gt;

&lt;p&gt;Enterprise adoption grew 340% from 2024 to early 2026. The S-curve is now hitting the steep middle section.&lt;/p&gt;

&lt;p&gt;82% of developers use or plan to use AI coding tools. That figure from the GitHub Developer Survey represents saturation at the individual level. The enterprise transition lags because it requires security review, compliance approval, and integration with existing CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;Non-technical user adoption grew 520% year-over-year. Platforms like v0 and Lovable absorb users who previously depended on no-code tools like Webflow or Bubble. The output quality from vibe coding surpasses no-code platforms because it generates actual production-ready code rather than proprietary markup.&lt;/p&gt;

&lt;p&gt;Financial services and healthcare move slowest due to data governance requirements. Technology and media companies adopted fastest. The gap narrows as platforms add SOC 2 compliance, on-premises deployment options, and audit logging.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Changes Next
&lt;/h2&gt;

&lt;p&gt;Three trends will reshape vibe coding through 2027.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model commoditization.&lt;/strong&gt; Open source models close the quality gap with commercial offerings. DeepSeek Coder already scores within 6 points of Claude 3.5 Sonnet on HumanEval. When model quality becomes a non-factor, platform differentiation shifts entirely to developer experience, integrations, and ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent autonomy.&lt;/strong&gt; Current platforms still require human guidance for complex tasks. The next generation will handle multi-step workflows autonomously: read the bug report, identify the root cause, write the fix, run the tests, open the pull request. Early versions of this workflow exist in Cursor and Replit Agent today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regulatory pressure.&lt;/strong&gt; Generated code inherits copyright and licensing questions that remain unresolved. The EU AI Act includes provisions for AI-generated content transparency. Companies using vibe coding at scale will need audit trails showing which code was human-written versus AI-generated.&lt;/p&gt;

&lt;p&gt;The $25 billion projected market by 2030 assumes these trends accelerate. Every developer becomes more productive. Every non-developer gains the ability to build functional software. The economic value creation from that shift dwarfs the platform revenue numbers.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Vibe coding data sourced from MarketsandMarkets AI Code Generation Report 2025, Gartner AI Developer Tools Forecast Q4 2025, GitHub Developer Survey 2026, Posit Developer Productivity Study 2024, and Redmonk Developer Survey 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://pooyagolchian.github.io/subscribe" rel="noopener noreferrer"&gt;Subscribe to get new research articles with data visualizations&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>aicodegeneration</category>
      <category>cursorai</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>use-local-llm: React Hooks for AI That Actually Work Locally</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:09:05 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/use-local-llm-react-hooks-for-ai-that-actually-work-locally-28mi</link>
      <guid>https://forem.com/pooyagolchian/use-local-llm-react-hooks-for-ai-that-actually-work-locally-28mi</guid>
      <description>&lt;p&gt;You've finally got your local LLM running. You pull a model, test it with curl, and it works beautifully. But the moment you try to integrate it into your React app, you hit a wall.&lt;/p&gt;

&lt;p&gt;The tools everyone uses assume you're calling OpenAI or Anthropic from a server. They don't expect you to talk to &lt;code&gt;localhost:11434&lt;/code&gt; directly from the browser. And if they do, they force you to build API routes, add a backend, and complicate your prototype.&lt;/p&gt;

&lt;p&gt;I kept running into this frustration, so I built &lt;strong&gt;use-local-llm&lt;/strong&gt;, a library with a single purpose. It streams AI responses from local models directly in the browser with no backend, in 2.8 KB of code and zero dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Existing Tools Don't Fit
&lt;/h2&gt;

&lt;p&gt;You'd think you could just use &lt;a href="https://sdk.vercel.ai" rel="noopener noreferrer"&gt;Vercel AI SDK&lt;/a&gt;. It's the standard for React + AI. It ships adapters for multiple frameworks, maintains thorough API references, and handles production traffic at scale.&lt;/p&gt;

&lt;p&gt;But Vercel did not build it for direct browser-to-localhost communication.&lt;/p&gt;

&lt;p&gt;Vercel AI SDK requires an API layer. Your React app POSTs to your Next.js server, which then calls the LLM and streams back. This makes sense for production apps using OpenAI or Anthropic, because you need the backend for authentication, cost tracking, and security.&lt;/p&gt;

&lt;p&gt;But when the LLM is already running locally on &lt;code&gt;localhost:11434&lt;/code&gt;, that server adds nothing but friction. More code to write. More latency. More complexity for something that should be a quick prototype.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I wanted one thing.&lt;/strong&gt; A single React hook that talks directly to my local model. No middleman. No API routes. Just React and a running LLM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser → fetch() → localhost:11434 → streaming tokens back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the entire architecture. No intermediary.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;use-local-llm gives you React hooks that stream responses from local LLMs directly in the browser.&lt;/strong&gt; No API routes. No backend. Just one hook and your running model.&lt;/p&gt;

&lt;p&gt;Here's what a complete, production-ready chat interface looks like in practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  One Hook. That's It.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Chat&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isStreaming&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useOllama&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemma3:1b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isStreaming&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isStreaming&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Generating...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Send&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. That's a complete, streaming chat interface. Message history? Handled. Streaming state? Handled. Stopping mid-generation? Handled. All the complexity is wrapped inside the hook.&lt;/p&gt;

&lt;p&gt;No &lt;code&gt;/api/chat&lt;/code&gt; route. No &lt;code&gt;Next.js&lt;/code&gt;. No backend configuration. Just React doing what it does best.&lt;/p&gt;

&lt;h3&gt;
  
  
  Works With Any Local LLM
&lt;/h3&gt;

&lt;p&gt;Whether you're using Ollama, LM Studio, llama.cpp, or any OpenAI-compatible server, the same API applies.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ollama&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLocalLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:11434&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemma3:1b&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;lmStudio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLocalLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:1234&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;local-model&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;llamaCpp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLocalLLM&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:8080&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&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 library detects the backend from the port. Each uses its native streaming protocol, so you get optimal performance regardless of which tool you chose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced: Token-by-Token Control
&lt;/h3&gt;

&lt;p&gt;Need fine-grained control? You can hook into every token as it arrives.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Writer&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isStreaming&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStreamCompletion&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:11434&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemma3:1b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Token:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Write a haiku about React&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Generate
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Discover Available Models
&lt;/h3&gt;

&lt;p&gt;Let your users pick from available models without manual configuration:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ModelPicker&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useModelList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Compares
&lt;/h2&gt;

&lt;p&gt;Vercel AI SDK is fantastic for production apps using cloud APIs. But for local development, the architectures diverge:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Vercel AI SDK&lt;/th&gt;
&lt;th&gt;use-local-llm&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud LLMs (OpenAI, Anthropic, etc.)&lt;/td&gt;
&lt;td&gt;Local LLMs (Ollama, LM Studio, llama.cpp)&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;Client → Server → Cloud API&lt;/td&gt;
&lt;td&gt;Client → Local LLM directly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backend needed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (required)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10+ minutes&lt;/td&gt;
&lt;td&gt;2 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bundle size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~50 KB+&lt;/td&gt;
&lt;td&gt;2.8 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dependencies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multiple&lt;/td&gt;
&lt;td&gt;Zero (React only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data leaves your machine&lt;/td&gt;
&lt;td&gt;Never leaves your machine&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Pick the tool for your use case. If you're calling OpenAI in production, use Vercel AI SDK. If you're prototyping locally or prioritizing privacy, use &lt;strong&gt;use-local-llm&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It's Built This Way
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Zero Dependencies (2.8 KB Total)
&lt;/h3&gt;

&lt;p&gt;The entire package is 2.8 KB gzipped. No runtime dependencies. Only React as a peer.&lt;/p&gt;

&lt;p&gt;Why does this matter? Your prototype should install instantly and never conflict with anything else in your project. No dependency conflicts. No version mismatches. No bloat.&lt;/p&gt;

&lt;h3&gt;
  
  
  Works Outside React Too
&lt;/h3&gt;

&lt;p&gt;The core streaming functions (&lt;code&gt;streamChat()&lt;/code&gt; and &lt;code&gt;streamGenerate()&lt;/code&gt;) are async generators that run in any JavaScript environment, from React and Vue to vanilla JS and Node.js scripts. Use the hooks for React apps or the generators directly for everything else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;streamChat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:11434&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemma3:1b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&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="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &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;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&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;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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;h3&gt;
  
  
  AbortController Integration
&lt;/h3&gt;

&lt;p&gt;Every stream is cancellable immediately. User-initiated aborts do not trigger error states, because aborting a generation is a normal user action, not an error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full TypeScript Support
&lt;/h3&gt;

&lt;p&gt;Everything is strongly typed. IDE autocompletion, type safety, and explicit contracts cover every function.&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// "ollama" | "lmstudio" | "llamacpp" | "openai-compatible"&lt;/span&gt;
  &lt;span class="nx"&gt;ChatMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// { role: "system" | "user" | "assistant", content: string }&lt;/span&gt;
  &lt;span class="nx"&gt;StreamChunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// { content: string, done: boolean, model?: string }&lt;/span&gt;
  &lt;span class="nx"&gt;LocalModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// { name, size?, modifiedAt?, digest? }&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;use-local-llm&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;h2&gt;
  
  
  Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────┐
│  Your React App                                 │
│                                                 │
│  useOllama("gemma3:1b")                         │
│        │                                        │
│        ▼                                        │
│  useLocalLLM({ endpoint, model, ... })          │
│        │                                        │
│        ▼                                        │
│  streamChat() / streamGenerate()                │
│        │          async generators              │
│        ▼                                        │
│  parseStreamChunk()                             │
│        │          NDJSON + SSE parser            │
│        ▼                                        │
│  fetch() + ReadableStream                       │
└─────────┬───────────────────────────────────────┘
          │ HTTP (no server in between)
          ▼
┌─────────────────────┐
│  Ollama    :11434   │
│  LM Studio :1234    │
│  llama.cpp :8080    │
└─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each layer is independently testable. The hooks compose on top of pure functions that can run anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Reach for use-local-llm
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Perfect for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;strong&gt;Rapid prototyping&lt;/strong&gt; that puts AI streaming in your React app in 2 minutes, not 20&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Privacy-first apps&lt;/strong&gt; where data never leaves your machine. No cloud API calls. No tracking&lt;/li&gt;
&lt;li&gt;🏢 &lt;strong&gt;Enterprise/offline&lt;/strong&gt; deployments that run in air-gapped networks and disconnected environments&lt;/li&gt;
&lt;li&gt;🎓 &lt;strong&gt;Learning&lt;/strong&gt; how LLM streaming works without server boilerplate&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Small footprint&lt;/strong&gt; for projects where bundle size and dependency count matter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip this library if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're using OpenAI, Anthropic, or other cloud APIs in production&lt;/li&gt;
&lt;li&gt;You need server-side authentication, logging, or rate limiting&lt;/li&gt;
&lt;li&gt;Your app is already using Vercel AI SDK for other reasons&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Start Building
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Install the library&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;use-local-llm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Start your local LLM&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Stream AI in your React app (see examples above)&lt;/p&gt;

&lt;p&gt;That's it. No API routes. No server configuration. AI streaming in your browser in under 2 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learn more:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pooyagolchian.github.io/use-local-llm/" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt; — API reference, advanced patterns, troubleshooting&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pooyagolchian.github.io/use-local-llm/demo/" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt; — See it working with Ollama&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/pooyagolchian/use-local-llm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; — Source code, issues, contributions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/use-local-llm" rel="noopener noreferrer"&gt;npm Package&lt;/a&gt; — Install it&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>TypeScript 6.0: New Features Every Developer Should Know</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:08:49 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/typescript-60-new-features-every-developer-should-know-54md</link>
      <guid>https://forem.com/pooyagolchian/typescript-60-new-features-every-developer-should-know-54md</guid>
      <description>&lt;p&gt;TypeScript 6.0 has arrived. The latest major release brings substantial performance improvements, refined type inference, and developer experience enhancements that address long-standing community requests.&lt;/p&gt;

&lt;p&gt;Microsoft announced TypeScript 6.0 on March 20, 2026, marking a significant milestone in the language's evolution. With over 50 million weekly npm downloads and adoption by 95% of JavaScript developers in enterprise environments, TypeScript continues to shape how modern web applications are built &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0/" rel="noopener noreferrer"&gt;Microsoft DevBlog, 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Improvements: Faster Compilation
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0 delivers measurable performance gains across the compilation pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incremental Compilation Speedup&lt;/strong&gt;: Projects using incremental compilation see 40-60% faster rebuild times. The compiler now caches type resolution results more aggressively, reducing redundant work during watch mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory Usage Reduction&lt;/strong&gt;: Peak memory consumption during compilation drops by approximately 25% for large codebases. This improvement stems from optimized internal data structures and garbage collection patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Editor Responsiveness&lt;/strong&gt;: Language service operations, including autocomplete and error checking, complete 30% faster on average. Developers experience less lag when working with large monorepos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhanced Type Inference
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0 introduces smarter type inference that reduces the need for explicit type annotations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contextual Typing for Array Methods&lt;/strong&gt;: Array methods like &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, and &lt;code&gt;reduce&lt;/code&gt; now infer more precise return types based on usage context. Previously required explicit generics are now often unnecessary.&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="c1"&gt;// TypeScript 5.x: Required explicit type annotation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// inferred as number[]&lt;/span&gt;

&lt;span class="c1"&gt;// TypeScript 6.0: Smarter literal type inference&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// inferred as literal 'production', not string&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;          &lt;span class="c1"&gt;// inferred as literal 3000, not number&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Improved Generic Inference&lt;/strong&gt;: Generic type parameters are inferred more accurately in complex scenarios involving multiple type parameters and constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Control Flow Analysis&lt;/strong&gt;: Narrowing types through control flow analysis now works across more edge cases, including async/await patterns and generator functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  New Language Features
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0 introduces several language features that enhance expressiveness and type safety.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicit Resource Management&lt;/strong&gt;: The &lt;code&gt;using&lt;/code&gt; declaration provides automatic cleanup for disposable resources, similar to C#'s &lt;code&gt;using&lt;/code&gt; statement or Python's context managers.&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="nx"&gt;using&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;openFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data.txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// file is automatically closed when scope exits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Decorator Metadata&lt;/strong&gt;: Stage 3 decorators now support metadata attachment, enabling frameworks to access type information at runtime. This powers dependency injection, validation, and serialization libraries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Import Attributes&lt;/strong&gt;: Import assertions evolve into import attributes, providing a standard way to specify module import conditions.&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="nx"&gt;data&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&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;h2&gt;
  
  
  Developer Experience Enhancements
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0 focuses heavily on improving the day-to-day developer experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Error Messages&lt;/strong&gt;: Error messages now include suggested fixes for common mistakes. The compiler detects likely typos and suggests corrections based on available identifiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go to Source Definition&lt;/strong&gt;: A new editor command jumps directly to the JavaScript source of a library, not just its type declarations. This aids debugging and understanding third-party code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inlay Hints Improvements&lt;/strong&gt;: Parameter name and type inlay hints are more configurable and performant. Large files no longer cause editor slowdowns when hints are enabled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSDoc Support&lt;/strong&gt;: JavaScript projects using JSDoc for type annotations benefit from improved type inference and error detection, narrowing the gap between JavaScript and TypeScript development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Changes and Deprecations
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0 includes minimal breaking changes, maintaining the team's commitment to backward compatibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stricter Generic Checks&lt;/strong&gt;: Some edge cases involving generic constraints now produce errors where they previously passed. These changes catch potential runtime bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deprecated Features&lt;/strong&gt;: The &lt;code&gt;tsconfig.json&lt;/code&gt; &lt;code&gt;suppressExcessPropertyErrors&lt;/code&gt; option is deprecated in favor of more granular control. The &lt;code&gt;noImplicitUseStrict&lt;/code&gt; option is removed, as modules are strict by default in modern JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lib Updates&lt;/strong&gt;: DOM type definitions are updated to reflect the latest web standards. Some deprecated APIs are removed from the default library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration Guide: Upgrading to TypeScript 6.0
&lt;/h2&gt;

&lt;p&gt;Upgrading existing projects to TypeScript 6.0 is straightforward for most codebases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Update Dependencies&lt;/strong&gt;&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;typescript@^6.0.0 &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add typescript@^6.0.0 &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Review Compiler Options&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check your &lt;code&gt;tsconfig.json&lt;/code&gt; for deprecated options. Update or remove &lt;code&gt;suppressExcessPropertyErrors&lt;/code&gt; and &lt;code&gt;noImplicitUseStrict&lt;/code&gt; if present.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Address New Errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the compiler and fix any new type errors. Most projects require minimal changes. Focus on generic constraint violations first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Enable New Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider enabling new strictness flags incrementally. Start with &lt;code&gt;strictFunctionTypes&lt;/code&gt; and &lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt; for maximum safety.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Update Tooling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensure your IDE, build tools, and linting configurations support TypeScript 6.0. Most popular tools update within days of release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosystem Impact
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0's release triggers updates across the JavaScript ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Framework Updates&lt;/strong&gt;: React, Vue, Angular, and Svelte release patches leveraging new TypeScript features. Framework-specific type definitions become more precise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build Tool Support&lt;/strong&gt;: Vite, Webpack, esbuild, and Rollup update their TypeScript integrations to support new language features and optimize for performance improvements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Library Maintenance&lt;/strong&gt;: Popular libraries like lodash, RxJS, and date-fns update their type definitions. Community-maintained &lt;code&gt;@types&lt;/code&gt; packages follow suit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing Frameworks&lt;/strong&gt;: Jest, Vitest, and Playwright enhance their TypeScript support, improving type inference for test matchers and fixtures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison with Alternative Typed Languages
&lt;/h2&gt;

&lt;p&gt;TypeScript 6.0 strengthens its position against alternatives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deno&lt;/strong&gt;: Deno's native TypeScript support remains compelling for new projects, but TypeScript 6.0 narrows the gap with improved performance and features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSDoc&lt;/strong&gt;: JavaScript with JSDoc annotations becomes more viable for teams avoiding build steps, thanks to TypeScript 6.0's enhanced JavaScript support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flow&lt;/strong&gt;: Flow's niche shrinks further as TypeScript's ecosystem dominance grows. Most Flow projects have migrated or are planning migrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ReScript&lt;/strong&gt;: ReScript maintains its position for performance-critical applications, but TypeScript 6.0's speed improvements reduce the performance gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is TypeScript 6.0 backward compatible?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, TypeScript 6.0 maintains strong backward compatibility. Most projects upgrade without code changes. A small number of edge cases involving generic constraints may require adjustments &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html" rel="noopener noreferrer"&gt;TypeScript Documentation, 2026&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much faster is TypeScript 6.0?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Benchmarks show 40-60% faster incremental compilation, 25% reduced memory usage, and 30% faster editor operations. Actual improvements vary based on project size and complexity. Large monorepos benefit most significantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the &lt;code&gt;using&lt;/code&gt; declaration?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;using&lt;/code&gt; declaration enables automatic resource cleanup. When a variable declared with &lt;code&gt;using&lt;/code&gt; goes out of scope, its &lt;code&gt;[Symbol.dispose]()&lt;/code&gt; method is called. This simplifies resource management for files, network connections, and locks &lt;a href="https://github.com/tc39/proposal-explicit-resource-management" rel="noopener noreferrer"&gt;TC39 Proposal, 2025&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need to update my tsconfig.json?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Review your configuration for deprecated options. Remove &lt;code&gt;suppressExcessPropertyErrors&lt;/code&gt; and &lt;code&gt;noImplicitUseStrict&lt;/code&gt; if present. Consider enabling new strictness flags for improved type safety. Most existing configurations work without changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When will frameworks support TypeScript 6.0?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Major frameworks typically release TypeScript 6.0 support within one week of release. React, Vue, Angular, and Svelte have already published compatible versions. Check your framework's changelog for specific version requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use TypeScript 6.0 with Node.js?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, TypeScript 6.0 supports all maintained Node.js versions (18.x, 20.x, 22.x). The TypeScript compiler targets JavaScript output compatible with your specified Node.js version through the &lt;code&gt;target&lt;/code&gt; compiler option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are decorator metadata?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Decorator metadata allows decorators to access type information at runtime. This enables frameworks to implement dependency injection, validation, and ORM mapping with full type safety. The feature uses the Stage 3 decorators proposal &lt;a href="https://www.typescriptlang.org/docs/handbook/decorators.html" rel="noopener noreferrer"&gt;TypeScript Handbook, 2026&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;TypeScript 6.0 represents a mature evolution of the language. Performance improvements address long-standing pain points for large projects. Enhanced type inference reduces boilerplate while maintaining safety. New language features align TypeScript with modern JavaScript proposals.&lt;/p&gt;

&lt;p&gt;For developers, upgrading is low-risk and high-reward. The migration path is smooth, and the benefits are immediate. Faster compilation, better editor support, and improved type inference enhance daily productivity.&lt;/p&gt;

&lt;p&gt;For organizations, TypeScript 6.0 solidifies the language's position as the standard for enterprise JavaScript development. The ecosystem continues to grow, with tooling and library support expanding.&lt;/p&gt;

&lt;p&gt;The future of web development remains typed. TypeScript 6.0 ensures that future is faster, safer, and more developer-friendly than ever before.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pooya Golchian is an AI Engineer and Full Stack Developer specializing in TypeScript and React applications. Follow him on Twitter &lt;a href="https://twitter.com/pooyagolchian" rel="noopener noreferrer"&gt;@pooyagolchian&lt;/a&gt; for more insights on modern web development.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>programminglanguages</category>
      <category>developertools</category>
    </item>
    <item>
      <title>Supply Chain Attacks on Developers: Lessons from LiteLLM and Trivy</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:08:33 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/supply-chain-attacks-on-developers-lessons-from-litellm-and-trivy-113c</link>
      <guid>https://forem.com/pooyagolchian/supply-chain-attacks-on-developers-lessons-from-litellm-and-trivy-113c</guid>
      <description>&lt;p&gt;Supply chain attacks on developers have escalated dramatically in early 2026. Two major incidents, LiteLLM and Trivy, exposed thousands of projects to credential theft, backdoors, and potential data breaches.&lt;/p&gt;

&lt;p&gt;These attacks represent a fundamental shift in how threat actors target software development. Instead of attacking finished applications, they compromise the tools developers use to build them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The LiteLLM PyPI Compromise
&lt;/h2&gt;

&lt;p&gt;In March 2026, malicious versions of LiteLLM appeared on PyPI, affecting thousands of Python projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Happened:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Versions 1.82.7 and 1.82.8 of LiteLLM contained credential theft mechanisms and persistent backdoors. The attack was sophisticated, using obfuscated code and delayed execution to evade detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attack Mechanism:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The malicious code activated 24 hours after installation, making it harder to correlate with the package update. It exfiltrated environment variables, including API keys and database credentials, to attacker-controlled servers.&lt;/p&gt;

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

&lt;p&gt;Over 15,000 projects downloaded the compromised versions before discovery. Major organizations using LiteLLM for LLM abstraction had to rotate credentials and audit access logs.&lt;/p&gt;

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

&lt;p&gt;Security researchers at FutureSearch.ai identified the compromise through behavioral analysis. The malware attempted network connections to unusual domains, triggering automated alerts &lt;a href="https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack/" rel="noopener noreferrer"&gt;FutureSearch.ai, 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trivy GitHub Actions Compromise
&lt;/h2&gt;

&lt;p&gt;Trivy, a popular container vulnerability scanner, was compromised through its GitHub Actions integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attack Vector:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Threat actors gained access to Trivy's GitHub repository and pushed malicious tags. These tags were picked up by CI/CD pipelines worldwide, executing attacker-controlled code in build environments.&lt;/p&gt;

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

&lt;p&gt;The compromise affected any project using Trivy GitHub Actions with floating version tags. CI/CD secrets, including cloud provider credentials and deployment tokens, were exposed.&lt;/p&gt;

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

&lt;p&gt;The malicious code ran with the permissions of the CI/CD pipeline. In many cases, this included write access to container registries, production deployments, and infrastructure management.&lt;/p&gt;

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

&lt;p&gt;Socket.dev and other security firms coordinated disclosure. GitHub revoked compromised tokens and worked with maintainers to secure the repository &lt;a href="https://socket.dev/blog/trivy-under-attack-again-github-actions-compromise" rel="noopener noreferrer"&gt;Socket.dev, 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Supply Chain Attacks Work
&lt;/h2&gt;

&lt;p&gt;Understanding attack vectors is essential for defense.&lt;/p&gt;

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

&lt;p&gt;Attackers publish packages with names similar to popular libraries. Developers mistype imports and install malware. Examples include &lt;code&gt;reqeusts&lt;/code&gt; instead of &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;djano&lt;/code&gt; instead of &lt;code&gt;django&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Confusion:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Public packages with the same name as internal packages take precedence in some package managers. Attackers upload public versions with higher version numbers, tricking build systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compromised Maintainer Accounts:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Phishing attacks on package maintainers give attackers legitimate publishing credentials. These attacks are hard to detect since the packages come from trusted sources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build System Compromise:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Attackers target the infrastructure that builds packages. This was the vector for the Trivy compromise and the 2024 XZ Utils backdoor attempt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Malicious Updates:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Legitimate packages are compromised and used to distribute malware. The LiteLLM attack followed this pattern, with attackers gaining access to the PyPI publishing pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protecting Your Projects
&lt;/h2&gt;

&lt;p&gt;Defense requires multiple layers of security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pin Dependencies:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use exact version numbers in requirements files. Avoid floating versions like &lt;code&gt;package&amp;gt;=1.0&lt;/code&gt;. Pin to specific hashes where possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# requirements.txt with hashes
&lt;/span&gt;&lt;span class="n"&gt;litellm&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;1.82&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; \
    &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;abc123&lt;/span&gt;&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Private Registries:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mirror public packages to private registries you control. Scan packages before internal distribution. This adds a review layer between public repositories and your builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated Scanning:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Integrate security scanning into CI/CD pipelines. Tools like Snyk, Socket.dev, and GitHub Advanced Security detect known malicious packages and vulnerable dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Least Privilege:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run CI/CD pipelines with minimal permissions. Separate build, test, and deployment credentials. Use short-lived tokens with limited scope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Review:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Audit new dependencies before adding them. Check maintainer reputation, update frequency, and community adoption. Avoid abandoned or single-maintainer projects for critical functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Industry Response and Best Practices
&lt;/h2&gt;

&lt;p&gt;The security community has responded with new tools and standards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Software Bills of Materials (SBOM):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SBOMs inventory all dependencies and their versions. They enable rapid vulnerability assessment when new threats emerge. Executive Order 14028 mandates SBOMs for software sold to the US government.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sigstore and Artifact Signing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sigstore provides free certificate authority and transparency logs for software artifacts. Signed packages can be verified against tampering. Adoption is growing across major package registries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Package Manager Improvements:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PyPI, npm, and other registries have implemented stricter authentication, mandatory 2FA for maintainers, and malware scanning. These measures reduce but do not eliminate risk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Frameworks:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NIST SSDF, OWASP SAMM, and SLSA provide frameworks for secure software development. Following these standards reduces supply chain attack surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Economic Impact
&lt;/h2&gt;

&lt;p&gt;Supply chain attacks have measurable business consequences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remediation Costs:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The average supply chain breach costs $4.5 million to remediate. This includes credential rotation, forensic analysis, legal fees, and reputation damage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development Velocity:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Security reviews slow development. Teams spend 15-20% more time on dependency management and security audits post-incident.&lt;/p&gt;

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

&lt;p&gt;Cyber insurance premiums have increased 50% for software companies. Insurers now require SBOMs, dependency scanning, and incident response plans.&lt;/p&gt;

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

&lt;p&gt;The SEC now requires public companies to disclose material cybersecurity incidents within four days. Supply chain attacks affecting customer data trigger these disclosures.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is a supply chain attack?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A supply chain attack targets the tools, libraries, and services used to build software rather than the final application. By compromising upstream dependencies, attackers gain access to all downstream projects. These attacks are difficult to detect since the malicious code comes from trusted sources &lt;a href="https://www.cisa.gov/supply-chain-attacks" rel="noopener noreferrer"&gt;CISA, 2026&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can I check if my project is affected?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Audit your dependency files (requirements.txt, package.json, Cargo.toml) for compromised versions. Use &lt;code&gt;pip list&lt;/code&gt; or &lt;code&gt;npm list&lt;/code&gt; to see installed packages. Security tools like Snyk and GitHub Dependabot alert on known malicious versions automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What should I do if I used a compromised package?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Immediately rotate all credentials that may have been exposed. Check logs for unauthorized access. Update to clean versions of the package. Audit your codebase for signs of compromise. Notify security teams and affected users if sensitive data was accessed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are private package registries safer?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Private registries add a layer of control but are not inherently safer. They must be maintained, scanned, and updated like public registries. The benefit is the ability to review packages before internal distribution and control update timing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I prevent dependency confusion attacks?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use scoped packages (e.g., &lt;a class="mentioned-user" href="https://dev.to/company"&gt;@company&lt;/a&gt;/package) for internal libraries. Configure package managers to prioritize private registries. Implement namespace reservation on public registries for your organization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the future of supply chain security?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Expect mandatory code signing, SBOM requirements, and automated vulnerability scanning to become standard. Supply chain security will be integrated into DevSecOps pipelines by default. Regulatory requirements will drive adoption of secure development practices.&lt;/p&gt;

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

&lt;p&gt;The LiteLLM and Trivy compromises are warnings, not anomalies. Supply chain attacks are increasing in frequency and sophistication. Development teams must treat dependencies as potential attack vectors.&lt;/p&gt;

&lt;p&gt;The solution is not to avoid third-party code. Modern software development depends on open source. The solution is to manage dependencies with security in mind.&lt;/p&gt;

&lt;p&gt;Pin versions. Scan for vulnerabilities. Use private registries. Implement least privilege. Build SBOMs. Sign artifacts. These practices add friction but prevent catastrophe.&lt;/p&gt;

&lt;p&gt;The attackers are targeting your tools. Secure them before they do.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pooya Golchian is an AI Engineer and Full Stack Developer specializing in secure software development. Follow him on Twitter &lt;a href="https://twitter.com/pooyagolchian" rel="noopener noreferrer"&gt;@pooyagolchian&lt;/a&gt; for more insights on cybersecurity and development.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>supplychain</category>
      <category>malware</category>
      <category>developertools</category>
    </item>
    <item>
      <title>State of the Product Job Market in Early 2026</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:08:18 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/state-of-the-product-job-market-in-early-2026-391c</link>
      <guid>https://forem.com/pooyagolchian/state-of-the-product-job-market-in-early-2026-391c</guid>
      <description>&lt;p&gt;The job market statistics tell one story. Candidates tell another.&lt;/p&gt;

&lt;p&gt;Over 7,300 product management roles are open globally right now — the highest count in three years. Engineering has 67,000 open positions. AI-specific roles grew 340% since 2024. By every headline metric, the tech hiring market is in recovery. Yet talk to anyone who has been searching for six months, and you hear something different: a market that moves fast for the right profile and goes silent for everyone else.&lt;/p&gt;

&lt;p&gt;Both stories are true. This is a selective recovery, not a broad one, and the selection criteria shifted fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The PM Numbers
&lt;/h2&gt;

&lt;p&gt;Lenny Rachitsky's biannual &lt;a href="https://www.lennysnewsletter.com/p/state-of-the-product-job-market-in-ee9" rel="noopener noreferrer"&gt;State of the Product Job Market&lt;/a&gt; report is the most systematic tracking of PM openings available, drawing from data across over 9,000 tech companies worldwide. The early 2026 edition recorded the most optimistic outlook across four consecutive reports. Over 7,300 open PM roles globally represent a 75% increase from the 2023 lows and roughly 20% growth since the start of this year alone. One finding stands out beyond the headline count: Growth PM is now the single fastest-growing PM role category, outpacing even AI-adjacent titles in open requisitions.&lt;/p&gt;

&lt;p&gt;That number has a context problem, though. The absolute count feels strong until you compare it to application volumes. Generalist PM roles at mid-market companies attract hundreds of applicants within days of posting. Senior IC and leadership roles, by contrast, sit open for months because qualified candidates are scarce. The same data set produces two completely different job-search experiences depending on which tier you compete in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering's Comeback
&lt;/h2&gt;

&lt;p&gt;The engineering numbers are even more striking. &lt;a href="https://finance.yahoo.com/news/data-shows-surprising-rebound-tech-141608296.html" rel="noopener noreferrer"&gt;Yahoo Finance's analysis of tech hiring data&lt;/a&gt; puts total open engineering roles above 67,000 globally — 26,000 in the U.S. alone. Software engineering job postings grew 11% year-over-year. Supply simply has not kept pace: three engineering jobs exist for every qualified candidate.&lt;/p&gt;

&lt;p&gt;Lenny Rachitsky's data — drawn from over 9,000 tech companies worldwide — shows the engineering rebound as part of a broader industry expansion. The global software development market hit $640 billion in 2026 and analysts project it reaching $1.11 trillion by 2031 at an 11.74% compound annual growth rate. That trajectory demands engineers, not fewer of them.&lt;/p&gt;

&lt;p&gt;This mismatch is not evenly distributed across engineering disciplines. Generalist web and mobile engineering roles remain competitive. Roles requiring Python, cloud infrastructure (AWS), API design, and CI/CD pipeline expertise see the most intense demand. Companies cannot hire fast enough in those areas, while applications for JavaScript-generalist roles stack up in recruiters' inboxes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Wedge
&lt;/h2&gt;

&lt;p&gt;The most disruptive force in this market is not the hiring recovery. It is the structural bifurcation AI is creating inside every job category.&lt;/p&gt;

&lt;p&gt;AI-related job postings increased 340% since 2024, &lt;a href="https://www.informationweek.com/it-staffing-careers/2026-tech-company-layoffs" rel="noopener noreferrer"&gt;according to InformationWeek's 2026 layoff and hiring tracker&lt;/a&gt;. Traditional software engineering roles declined 15% over the same period. Atlassian made this dynamic explicit when it cut 1,600 generalist positions while simultaneously opening 800 AI-focused roles. The headcount math looks like a modest net reduction. The skill-set math is a complete reset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://insight.ieeeusa.org/articles/2026-tech-hiring-outlook/" rel="noopener noreferrer"&gt;IEEE-USA's 2026 tech hiring outlook&lt;/a&gt; projects the roles with the fastest growth as AI governance officers, AI workflow leads, AI agent orchestrators, and machine learning engineers. None of these categories existed at meaningful scale three years ago. Companies are now realizing that reskilling timelines for their existing workforce run 18 to 24 months, while competitive pressure requires these capabilities now. The result is a surplus of applicants for roles companies are quietly defunding and a severe shortage in the specialized space that is actually growing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Market Pays
&lt;/h2&gt;

&lt;p&gt;Compensation data across multiple sources paints a consistent picture. The median PM salary in the U.S. sits at $149,871 to $159,405 annually, &lt;a href="https://www.joinleland.com/library/a/product-manager-salary" rel="noopener noreferrer"&gt;per Leland's 2026 PM salary benchmarks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By experience level:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Years&lt;/th&gt;
&lt;th&gt;Base Salary Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entry&lt;/td&gt;
&lt;td&gt;0–2 yrs&lt;/td&gt;
&lt;td&gt;$80,000 – $110,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mid&lt;/td&gt;
&lt;td&gt;3–7 yrs&lt;/td&gt;
&lt;td&gt;$120,000 – $160,000+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Senior&lt;/td&gt;
&lt;td&gt;7+ yrs&lt;/td&gt;
&lt;td&gt;$160,000 – $210,000+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI PM&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;td&gt;$130,000 – $200,000 base&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Total compensation at top-tier firms extends further. &lt;a href="https://www.simplilearn.com/ai-product-manager-salary-article" rel="noopener noreferrer"&gt;Simplilearn's AI PM salary data&lt;/a&gt; puts total comp for AI product roles at $180,000 to $260,000 including bonuses and equity. Bay Area senior PMs regularly see $250,000+ total packages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ravio.com/blog/product-manager-salary-trends" rel="noopener noreferrer"&gt;Ravio's compensation trend analysis&lt;/a&gt; adds useful color on the growth trajectory: median PM salary increases reached 5.2% in 2025, the strongest growth across all job functions tracked. Late-stage companies pay 14% more than early-stage for mid-level PMs and 34% more for senior roles — a premium worth factoring into any job search.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the Jobs Actually Are
&lt;/h2&gt;

&lt;p&gt;Geography matters more in 2026 than it did during the remote-work peak of 2021 to 2023. The Bay Area holds 23% of all global PM openings, a figure that has grown 50% since 2022. New York ranks second. One-third of every AI-specific role sits in the Bay Area, according to &lt;a href="https://www.lennysnewsletter.com/p/state-of-the-product-job-market-in-ee9" rel="noopener noreferrer"&gt;Lenny's data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Remote opportunities are declining even as overall job counts grow. Companies that expanded their geographic hiring aperture during the pandemic are contracting it. This creates a specific trap for candidates who structured their life around remote flexibility: more jobs on paper, fewer jobs they can actually take.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design's Divergence
&lt;/h2&gt;

&lt;p&gt;One of the more telling signals in Rachitsky's report is what design is not doing. Open design roles sit around 5,700 globally — essentially flat since early 2023 while PM and engineering counts surged. The PM-to-designer demand ratio shifted from near parity in mid-2023 to 1.27x today.&lt;/p&gt;

&lt;p&gt;AI is absorbing design workflow tasks faster than it is absorbing PM or engineering tasks. Wireframing, asset generation, and iteration cycles that previously required a dedicated designer now move through AI tooling in hours. The demand signal is clear and companies are responding to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Levie's Counterargument
&lt;/h2&gt;

&lt;p&gt;Box CEO Aaron Levie made the case for optimism in a &lt;a href="https://finance.yahoo.com/news/box-ceo-aaron-levie-says-085902692.html" rel="noopener noreferrer"&gt;Yahoo Finance interview&lt;/a&gt;. His argument deserves attention precisely because it runs against the prevailing anxiety. "There are few examples of AI replacing an entire job," Levie said. The more likely outcome, in his framing, is that AI-driven productivity makes companies grow faster, which creates downstream demand for more hires to support that growth.&lt;/p&gt;

&lt;p&gt;The counterweight comes from KPMG chief economist Diane Swonk, who flagged the possibility of a "jobless boom" in 2026 — firms achieving more output with fewer workers, without those productivity gains translating into new headcount. Both positions carry historical precedent. The difference between them will likely come down to whether AI-fueled revenue growth is concentrated in a few sectors or distributed broadly across the economy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Selective Recovery
&lt;/h2&gt;

&lt;p&gt;The 2026 tech job market does not reward the same behaviors that worked in 2019 or 2021. Companies hiring right now do so with precision — every open role ties directly to revenue generation, risk reduction, or AI adoption. Generalist headcount is the first thing frozen when planning tightens.&lt;/p&gt;

&lt;p&gt;Senior PMs with demonstrated AI-adjacent impact, engineers holding Python and AWS depth, and candidates willing to operate in-office in the Bay Area sit in high demand. Junior PMs face the sharpest competition: fewer entry-level openings, more applicants, and a bar that has moved up. Candidates locked to remote-only roles face a structural disadvantage that grew more pronounced through 2025 and continues in 2026.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.optimixed.com/state-of-the-product-job-market-in-early-2026-2/" rel="noopener noreferrer"&gt;optimixed.com analysis of Rachitsky's report&lt;/a&gt; notes a key structural reality: despite record PM openings, tech job postings overall remain 35% below pre-pandemic February 2020 levels. The recovery is real, but it is recovering toward a different baseline — one where every role needs a stronger justification to exist and every hire needs a faster path to measurable output.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tooling Argument
&lt;/h2&gt;

&lt;p&gt;Ben Halpern, co-founder of Forem (the company behind dev.to), published a sharp counter-narrative to the doom loop in a &lt;a href="https://dev.to/ben/the-software-industry-is-ready-to-grow-4ie4"&gt;March 2026 essay&lt;/a&gt;. His argument: the industry is moving through a cost-cutting middle phase driven by AI implementation, and substantial growth will follow once tooling matures. "Tooling is getting there to the point where there will be renewed growth — for developers with a handle on how to leverage their skills and knowledge for AI-driven development," Halpern writes.&lt;/p&gt;

&lt;p&gt;The more interesting question his essay surfaces is not whether growth returns but what kind of growth. Community responses to the piece flagged a real challenge: teams are no longer limited by tool maturity but by knowing what to build differently when AI handles the routine work. That question — what to build, not how fast to build it — is a product management question. It is exactly the gap the current surge in PM demand is trying to fill.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Do With This
&lt;/h2&gt;

&lt;p&gt;Position yourself inside the AI skill gap rather than outside it. Generalist experience is a foundation, not a differentiator. The candidates winning in this market reframe their background in terms of AI-adjacent impact — where they accelerated AI adoption, reduced the cost of AI implementation, or translated AI capabilities into product decisions.&lt;/p&gt;

&lt;p&gt;Target late-stage companies. The 14% to 34% salary premium over early-stage is real, and late-stage companies have clearer revenue models that justify headcount. Bay Area optionality, even partial, opens up one-third of the most active AI hiring market in the world. And treat the AI skill mismatch as an opening, not a threat — because right now, the most acute problem tech companies have is not too many applicants. It is that they cannot find enough people who understand both product and AI systems well enough to move fast.&lt;/p&gt;

&lt;p&gt;That gap will not stay open indefinitely. The question is whether you fill it first.&lt;/p&gt;

</description>
      <category>productmanagement</category>
      <category>jobmarket</category>
      <category>techhiring</category>
      <category>ai</category>
    </item>
    <item>
      <title>SSH SOCKS5 Proxy in 2026: macOS, Linux, Windows &amp; sshuttle: Complete Guide</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:08:02 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/ssh-socks5-proxy-in-2026-macos-linux-windows-sshuttle-complete-guide-1m76</link>
      <guid>https://forem.com/pooyagolchian/ssh-socks5-proxy-in-2026-macos-linux-windows-sshuttle-complete-guide-1m76</guid>
      <description>&lt;p&gt;Two common scenarios require routing traffic through a remote server: accessing private network resources, or browsing from a different geographic IP. An SSH SOCKS5 tunnel solves both in under a minute, no VPN software required.&lt;/p&gt;

&lt;h2&gt;
  
  
  How SSH -D Works
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;-D&lt;/code&gt; flag creates a &lt;strong&gt;dynamic port forward&lt;/strong&gt;: SSH listens on a local port and acts as a SOCKS5 proxy. Traffic exits from the SSH server's network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your app -&amp;gt; localhost:1080 (SOCKS5) -&amp;gt; SSH encrypted -&amp;gt; remote server -&amp;gt; internet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  macOS &amp;amp; Linux: Quick Start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start tunnel in background&lt;/span&gt;
ssh &lt;span class="nt"&gt;-D&lt;/span&gt; 1080 &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt; user@your-server.com

&lt;span class="c"&gt;# Verify it is running&lt;/span&gt;
pgrep &lt;span class="nt"&gt;-a&lt;/span&gt; ssh

&lt;span class="c"&gt;# Confirm traffic routes via the server&lt;/span&gt;
curl &lt;span class="nt"&gt;--socks5&lt;/span&gt; 127.0.0.1:1080 https://ipinfo.io/ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flag meanings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-D 1080&lt;/code&gt;: SOCKS5 proxy on local port 1080&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f&lt;/code&gt;: fork to background after auth&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-C&lt;/code&gt;: gzip compression&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-q&lt;/code&gt;: quiet mode&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-N&lt;/code&gt;: tunnel only, no remote command&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  macOS: Toggle Script
&lt;/h2&gt;

&lt;p&gt;Save as &lt;code&gt;~/bin/tunnel&lt;/code&gt;, &lt;code&gt;chmod +x&lt;/code&gt;, then &lt;code&gt;sudo tunnel&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nv"&gt;NET_SERVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Wi-Fi"&lt;/span&gt;   &lt;span class="c"&gt;# run: networksetup -listallnetworkservices&lt;/span&gt;
&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1080
&lt;span class="nv"&gt;SERVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user@your-server.com"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$EUID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Run as root: sudo &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pgrep &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"ssh -D &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Disconnecting (PID &lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;)..."&lt;/span&gt;
  &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  networksetup &lt;span class="nt"&gt;-setsocksfirewallproxystate&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NET_SERVICE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; off
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Tunnel closed."&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Connecting to &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
  ssh &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  networksetup &lt;span class="nt"&gt;-setsocksfirewallproxy&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NET_SERVICE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 127.0.0.1 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  networksetup &lt;span class="nt"&gt;-setsocksfirewallproxystate&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NET_SERVICE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; on
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Connected. System SOCKS proxy active on :&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;networksetup&lt;/code&gt; sets the macOS system-wide SOCKS proxy, all apps that respect it route through the tunnel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux: Route CLI Tools with Proxychains4
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;proxychains4         &lt;span class="c"&gt;# Debian/Ubuntu&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;proxychains-ng       &lt;span class="c"&gt;# Fedora&lt;/span&gt;

&lt;span class="c"&gt;# Edit /etc/proxychains4.conf:&lt;/span&gt;
&lt;span class="c"&gt;#   comment out: socks4 127.0.0.1 9050&lt;/span&gt;
&lt;span class="c"&gt;#   add:         socks5 127.0.0.1 1080&lt;/span&gt;

&lt;span class="c"&gt;# Start the SSH tunnel&lt;/span&gt;
ssh &lt;span class="nt"&gt;-D&lt;/span&gt; 1080 &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt; user@your-server.com

&lt;span class="c"&gt;# Route any CLI tool&lt;/span&gt;
proxychains4 curl https://ipinfo.io/ip
proxychains4 git clone https://github.com/someorg/private-repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  sshuttle: Transparent Full-System Proxy (No Config Required)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sshuttle&lt;/code&gt; routes &lt;strong&gt;all TCP traffic&lt;/strong&gt; via OS-level interception:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;sshuttle           &lt;span class="c"&gt;# macOS&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;sshuttle       &lt;span class="c"&gt;# Ubuntu&lt;/span&gt;

&lt;span class="c"&gt;# Route everything, exclude the SSH server to avoid a loop&lt;/span&gt;
sshuttle &lt;span class="nt"&gt;-r&lt;/span&gt; user@your-server.com 0.0.0.0/0 &lt;span class="nt"&gt;--exclude&lt;/span&gt; your-server.com

&lt;span class="c"&gt;# Route only a private subnet behind the server&lt;/span&gt;
sshuttle &lt;span class="nt"&gt;-r&lt;/span&gt; user@your-server.com 10.0.0.0/8

&lt;span class="c"&gt;# Stop with Ctrl+C&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No browser config. Every TCP connection is intercepted transparently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows: Bitvise + Proxifier
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://bitvise.com/ssh-client" rel="noopener noreferrer"&gt;Bitvise SSH Client&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Services &amp;gt; SOCKS/HTTP Proxy Forwarding&lt;/strong&gt;, enable SOCKS5 on &lt;code&gt;127.0.0.1:1080&lt;/code&gt;. Log in.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://proxifier.com/" rel="noopener noreferrer"&gt;Proxifier&lt;/a&gt;:

&lt;ul&gt;
&lt;li&gt;Add proxy: &lt;code&gt;127.0.0.1:1080&lt;/code&gt;, SOCKS5&lt;/li&gt;
&lt;li&gt;Add rule targeting the apps you want to route (e.g., &lt;code&gt;chrome.exe&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  SSH Config for Reliability
&lt;/h2&gt;

&lt;p&gt;Add to &lt;code&gt;~/.ssh/config&lt;/code&gt; to keep the tunnel alive through network idle timeouts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;Host&lt;/span&gt; tunnel-server
  &lt;span class="k"&gt;HostName&lt;/span&gt; your-server.com
  &lt;span class="k"&gt;User&lt;/span&gt; youruser
  &lt;span class="k"&gt;IdentityFile&lt;/span&gt; ~/.ssh/id_ed25519
  &lt;span class="k"&gt;ServerAliveInterval&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
  &lt;span class="k"&gt;ServerAliveCountMax&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="k"&gt;Compression&lt;/span&gt; &lt;span class="no"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start with: &lt;code&gt;ssh -D 1080 -f -C -q -N tunnel-server&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH -D vs sshuttle vs WireGuard
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;SSH -D&lt;/th&gt;
&lt;th&gt;sshuttle&lt;/th&gt;
&lt;th&gt;WireGuard&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup complexity&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routes all traffic&lt;/td&gt;
&lt;td&gt;No (per-app SOCKS)&lt;/td&gt;
&lt;td&gt;Yes (all TCP)&lt;/td&gt;
&lt;td&gt;Yes (all protocols)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UDP support&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server prerequisites&lt;/td&gt;
&lt;td&gt;SSH only&lt;/td&gt;
&lt;td&gt;SSH only&lt;/td&gt;
&lt;td&gt;wireguard-tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Single-app routing&lt;/td&gt;
&lt;td&gt;Full TCP proxy&lt;/td&gt;
&lt;td&gt;Permanent VPN&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Security Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Key-based auth only: &lt;code&gt;ssh-keygen -t ed25519&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Restrict server to your user: &lt;code&gt;AllowUsers youruser&lt;/code&gt; in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use a non-standard port to reduce automated brute-force: &lt;code&gt;Port 2222&lt;/code&gt; in &lt;code&gt;sshd_config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Rotate SSH keys annually&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>network</category>
      <category>vpn</category>
      <category>ssh</category>
      <category>security</category>
    </item>
    <item>
      <title>Software Developer Job Market Recovery: What the Data Shows in 2026</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:07:46 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/software-developer-job-market-recovery-what-the-data-shows-in-2026-2b52</link>
      <guid>https://forem.com/pooyagolchian/software-developer-job-market-recovery-what-the-data-shows-in-2026-2b52</guid>
      <description>&lt;p&gt;Software developer job postings have increased 15% since mid-2025. After two years of layoffs, hiring freezes, and economic uncertainty, the tech job market is showing signs of recovery.&lt;/p&gt;

&lt;p&gt;The data comes from the Federal Reserve Economic Data (FRED), which tracks job postings across industries. The trend line tells a story of resilience in the software development sector despite broader economic challenges &lt;a href="https://fred.stlouisfed.org/series/IHLIDXUSTPSOFTDEVE" rel="noopener noreferrer"&gt;FRED, 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 2024-2025 Tech Job Market Recession
&lt;/h2&gt;

&lt;p&gt;To understand the recovery, we must first examine the downturn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layoff Numbers:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2024 saw over 260,000 tech workers laid off globally. Major companies including Google, Amazon, Meta, and Microsoft reduced headcounts by 5-15%. Startups faced extinction-level events as venture funding dried up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hiring Freeze Impact:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Job postings for software developers dropped 35% from peak levels in early 2024. Entry-level positions were hit hardest, with new graduate hiring down 60% at major tech companies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Economic Factors:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rising interest rates, inflation concerns, and geopolitical tensions created a perfect storm. Companies prioritized profitability over growth. Technical debt reduction replaced new feature development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Bottom:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The market reached its lowest point in Q2 2025. Developer job postings were 40% below 2023 levels. Unemployment in tech reached 3.2%, historically high for the sector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Recovery Indicators
&lt;/h2&gt;

&lt;p&gt;The 15% increase since mid-2025 signals genuine recovery, not just statistical noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job Posting Volume:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Current levels are approaching 85% of 2023 peaks. While not fully recovered, the trajectory is positive. Month-over-month growth has been consistent for three consecutive quarters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sector Variations:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not all tech sectors are recovering equally. Some industries are booming while others remain stagnant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Geographic Distribution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remote job postings have increased disproportionately. Companies have accepted distributed teams as permanent fixtures. Traditional tech hubs (SF, Seattle, NYC) are recovering faster than secondary markets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Salary Trends:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Compensation is stabilizing after 2024's downward pressure. Average software engineer salaries have increased 4% year-over-year. Senior roles command premiums again after a brief compression.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Sectors Are Hiring
&lt;/h2&gt;

&lt;p&gt;The recovery is uneven across industry verticals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI/ML Engineering:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The clear winner. Job postings for AI/ML engineers are up 85% year-over-year. Companies are investing heavily in AI capabilities. Salaries for AI specialists have increased 20-30%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Healthcare Technology:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Digital health continues growing. Electronic health records, telemedicine platforms, and health data analytics drive demand. Regulatory compliance requirements create specialized roles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Financial Technology:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fintech is rebounding strongly. Payment processing, blockchain applications, and automated trading systems require engineering talent. Traditional banks are competing with startups for developers.&lt;/p&gt;

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

&lt;p&gt;Security engineers remain in high demand. Breach headlines drive corporate investment. Zero-trust architecture implementations create sustained hiring needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E-commerce:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Online retail platforms are expanding engineering teams. Personalization engines, logistics optimization, and mobile commerce drive growth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Struggling Sectors:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Social media platforms, ad-tech, and consumer apps remain cautious. Metaverse-related roles have declined 70% from 2023 hype peaks. Cryptocurrency companies have stabilized at much lower headcounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  In-Demand Skills for 2026
&lt;/h2&gt;

&lt;p&gt;The skills employers want have shifted during the recovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI/ML Integration:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not just building models, but integrating AI into existing products. Prompt engineering, LLM fine-tuning, and AI safety are emerging specializations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud Architecture:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Multi-cloud expertise is valued. Kubernetes, Terraform, and cloud-native development are table stakes. Cost optimization skills are particularly prized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full-Stack Development:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Versatility wins. Developers who can work across frontend, backend, and infrastructure are in demand. TypeScript, React, Node.js, and Python dominate job postings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Engineering:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building data pipelines, warehouses, and analytics platforms. Real-time processing and streaming architectures are growth areas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Engineering:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Application security, secure coding practices, and compliance automation. DevSecOps integration is standard expectation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Soft Skills:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Communication, business acumen, and adaptability are increasingly valued. Remote work requires self-management capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entry-Level Market Conditions
&lt;/h2&gt;

&lt;p&gt;New graduates face the most challenging conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Experience Paradox:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Employers want experienced developers but laid off junior staff disproportionately. Entry-level postings remain 45% below 2023 levels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alternative Pathways:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bootcamps and alternative credentials are losing favor. Traditional computer science degrees are regaining prestige. Internship experience is critical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advice for New Developers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build public portfolios with real-world projects&lt;/li&gt;
&lt;li&gt;Contribute to open source&lt;/li&gt;
&lt;li&gt;Network aggressively through communities&lt;/li&gt;
&lt;li&gt;Consider adjacent roles (QA, support, DevOps) as entry points&lt;/li&gt;
&lt;li&gt;Be geographically flexible&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Remote Work Normalization
&lt;/h2&gt;

&lt;p&gt;The pandemic-era remote work experiment has become permanent policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hybrid Models:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most companies (68%) have settled on hybrid arrangements. Two to three days in office is standard. Fully remote roles are available but competitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global Competition:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remote work means competing globally. Developers in lower-cost regions compete for US salaries. Companies arbitrage geographic salary differences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collaboration Challenges:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Onboarding and mentorship suffer remotely. Junior developers report slower career progression. Companies are investing in virtual collaboration tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Salary Expectations in 2026
&lt;/h2&gt;

&lt;p&gt;Compensation is recovering but remains below 2022 peaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;United States:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entry-level: $75,000 - $95,000&lt;/li&gt;
&lt;li&gt;Mid-level: $110,000 - $150,000&lt;/li&gt;
&lt;li&gt;Senior: $160,000 - $220,000&lt;/li&gt;
&lt;li&gt;Staff/Principal: $250,000+&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Entry-level: €45,000 - €60,000&lt;/li&gt;
&lt;li&gt;Mid-level: €65,000 - €85,000&lt;/li&gt;
&lt;li&gt;Senior: €90,000 - €120,000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Remote/Global:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Salaries are trending toward regional averages rather than location premiums. US-based remote roles pay 15-20% less than SF/NYC office roles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Equity Compensation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Startup equity packages are less generous than 2021. Vesting schedules are longer. Liquidity events are rarer.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is the tech job market recovering?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, software developer job postings are up 15% since mid-2025 according to Federal Reserve data. The recovery is uneven across sectors, with AI/ML roles leading growth while traditional software engineering is recovering more slowly &lt;a href="https://fred.stlouisfed.org/series/IHLIDXUSTPSOFTDEVE" rel="noopener noreferrer"&gt;FRED, 2026&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which programming skills are most in demand?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI/ML integration, cloud architecture (Kubernetes, Terraform), full-stack development (TypeScript, React, Node.js), data engineering, and security engineering are most sought-after. Python and JavaScript/TypeScript dominate job postings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are tech salaries increasing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Average software engineer salaries have increased 4% year-over-year after stabilizing in 2024. AI/ML specialists see 20-30% increases. Senior roles command premiums again after brief compression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is remote work still available?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, but the landscape has shifted. Fully remote roles are competitive. Most companies (68%) offer hybrid arrangements with 2-3 days in office. Remote work now means global competition for positions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How hard is it to get an entry-level developer job?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Entry-level remains challenging with postings 45% below 2023 levels. Candidates need strong portfolios, internship experience, and networking. Alternative credentials have lost favor to traditional CS degrees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sectors are hiring most aggressively?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI/ML engineering (up 85%), healthcare technology, fintech, cybersecurity, and e-commerce are hiring. Social media, ad-tech, and metaverse-related roles remain depressed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I specialize or stay general?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Current market favors specialists in high-demand areas (AI/ML, security, data). However, full-stack versatility remains valuable for smaller companies. Consider T-shaped skills: deep expertise in one area with broad general knowledge.&lt;/p&gt;

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

&lt;p&gt;The software developer job market is recovering, but it is not the same market as 2022. The AI boom has created new specializations. Remote work has globalized competition. Economic caution has made efficiency a priority.&lt;/p&gt;

&lt;p&gt;For developers, the message is clear: adapt to AI integration, build demonstrable expertise, and remain flexible about work arrangements. The days of easy job hopping and inflated salaries are over. The new market rewards skill, specialization, and business acumen.&lt;/p&gt;

&lt;p&gt;The 15% increase in job postings is a leading indicator. Hiring precedes economic confidence by several months. If the trend continues, 2026 could mark the return of a healthy, sustainable tech job market.&lt;/p&gt;

&lt;p&gt;The industry has matured. So must the developers who power it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pooya Golchian is an AI Engineer and Full Stack Developer analyzing technology trends and career development. Follow him on Twitter &lt;a href="https://twitter.com/pooyagolchian" rel="noopener noreferrer"&gt;@pooyagolchian&lt;/a&gt; for more insights on the tech industry.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>jobmarket</category>
      <category>softwaredevelopment</category>
      <category>dataanalysis</category>
    </item>
    <item>
      <title>Self-Hosting AI in 2026: 55% TCO Reduction, 18ms Latency, and the Open Source Stack That Replaces Cloud APIs</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:07:31 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/self-hosting-ai-in-2026-55-tco-reduction-18ms-latency-and-the-open-source-stack-that-replaces-40a6</link>
      <guid>https://forem.com/pooyagolchian/self-hosting-ai-in-2026-55-tco-reduction-18ms-latency-and-the-open-source-stack-that-replaces-40a6</guid>
      <description>&lt;p&gt;70-90% of AI operational costs come from inference, not training. Stanford's 2023 AI Index Report quantified what practitioners already knew: running models in production costs more than developing them. Cloud GPU instances at $32/hour compound into six-figure annual bills. API pricing per token scales linearly with usage and never gets cheaper at volume.&lt;/p&gt;

&lt;p&gt;Self-hosting flips that cost structure. You pay once for hardware. You optimize continuously on your own infrastructure. IDC data from 2024 confirms a 55% total cost of ownership reduction after 18 months for organizations running 10B+ parameter models.&lt;/p&gt;

&lt;p&gt;This article covers the cost math, the hardware benchmarks, and the open source tool stack that makes self-hosted AI infrastructure viable for organizations of every size.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost Case
&lt;/h2&gt;

&lt;p&gt;Cloud AI costs hit organizations in three layers: infrastructure, inference, and engineering. The total picture matters more than any single line item.&lt;/p&gt;

&lt;p&gt;Cloud infrastructure runs $420K over 18 months for a mid-scale deployment on AWS or GCP. That covers GPU instances (p4d.24xlarge at $32/hour), storage, networking, and load balancing. Inference costs add another $380K in API calls to OpenAI, Anthropic, or Google. Engineering overhead sits at $60K for integration and monitoring.&lt;/p&gt;

&lt;p&gt;Self-hosted infrastructure inverts the ratio. Hardware costs $180K upfront for a GPU cluster (4x H100, networking, storage). Inference drops to $45K because you own the GPUs. Engineering costs rise to $120K because you maintain the stack yourself. Total: $345K versus $860K.&lt;/p&gt;

&lt;p&gt;The 55% TCO reduction materializes after month 12-18 when the hardware investment amortizes against ongoing cloud costs. Before that break-even point, cloud remains cheaper for sporadic workloads that do not justify dedicated hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Latency: 19x Faster Than Cloud APIs
&lt;/h2&gt;

&lt;p&gt;Self-hosted H100 inference hits 18ms average latency. Cloud API endpoints from OpenAI and Anthropic average 350ms. Cloud GPU instances on AWS sit at 180ms. Self-hosted A100 delivers 45ms.&lt;/p&gt;

&lt;p&gt;The 19x latency improvement between self-hosted H100 and cloud APIs comes from eliminating network round trips, load balancer hops, and shared tenant scheduling. Your request goes directly from your application to your GPU with zero intermediaries.&lt;/p&gt;

&lt;p&gt;Goldman Sachs reported 40% latency reduction after moving inference in-house for risk modeling. Real-time trading systems require sub-100ms response times that cloud APIs cannot guarantee. Medical diagnostics systems at institutions like Mayo Clinic deployed on-premises AI clusters for the same reason.&lt;/p&gt;

&lt;p&gt;For applications where latency tolerance exceeds 500ms (batch processing, offline analysis, non-interactive summarization), cloud APIs remain perfectly adequate. The self-hosting advantage concentrates in real-time, interactive, and high-throughput use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPU Hardware ROI Timeline
&lt;/h2&gt;

&lt;p&gt;The break-even calculation determines whether self-hosting makes financial sense for a specific workload.&lt;/p&gt;

&lt;p&gt;NVIDIA H100 GPUs cost $30,000-$40,000 per unit. A production-ready cluster with 4 GPUs, networking, storage, and a host server runs $160,000 upfront. Monthly operational costs (power, cooling, maintenance, engineering time) add $10,000.&lt;/p&gt;

&lt;p&gt;Cloud GPU instances (AWS p4d.24xlarge) cost $23,000/month at continuous utilization. No upfront investment, but costs accumulate linearly.&lt;/p&gt;

&lt;p&gt;The crossover happens at month 9. By month 24, the self-hosted cluster saves $280K in cumulative costs compared to cloud. The gap widens with every additional month because cloud costs continue while self-hosted hardware costs are already paid.&lt;/p&gt;

&lt;p&gt;Organizations with intermittent GPU needs (less than 30% utilization) should stay on cloud. Self-hosting pays off when utilization exceeds 50% sustained.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Organizations Self-Host
&lt;/h2&gt;

&lt;p&gt;Five drivers push enterprises away from cloud AI services. Data privacy leads.&lt;/p&gt;

&lt;p&gt;67% of EU enterprises cite data residency as a critical barrier to cloud AI adoption (Gartner 2023). GDPR requires that personal data processing stays within jurisdictional boundaries. HIPAA mandates specific controls for protected health information. Financial regulations impose data handling requirements that cloud AI APIs cannot satisfy without complex data processing agreements.&lt;/p&gt;

&lt;p&gt;Cost control follows at 55%. Organizations running large models at scale watch their cloud inference bills grow linearly with usage. Cloud pricing never rewards volume. Self-hosted inference costs decline asymptotically as hardware amortizes.&lt;/p&gt;

&lt;p&gt;45% of enterprises prioritize open source stacks specifically to avoid vendor lock-in (Linux Foundation 2024). Cloud AI services impose rate limits, proprietary output formats, and egress fees that create switching costs. Self-hosted infrastructure with open source models eliminates all three.&lt;/p&gt;

&lt;p&gt;Latency requirements drive 40% of self-hosting decisions. Customization needs, including fine-tuning, quantization, and custom batching strategies, motivate the remaining 38%.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Open Source Tool Stack
&lt;/h2&gt;

&lt;p&gt;Five tools form the production self-hosting stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vLLM&lt;/strong&gt; is the default inference engine. Released by UC Berkeley in 2023, it achieves 2-4x throughput over Hugging Face Transformers through PagedAttention, a memory management technique that eliminates redundant KV-cache allocation. LinkedIn and Uber run vLLM in production. Apache 2.0 license. Supports NVIDIA GPUs with experimental AMD support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text Generation Inference (TGI)&lt;/strong&gt; from Hugging Face offers 1.5-3x throughput gains. It powers Hugging Face Inference Endpoints and supports Intel Gaudi accelerators alongside NVIDIA. The Flash Attention 2 integration reduces memory footprint for long-context generation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Triton Inference Server&lt;/strong&gt; from NVIDIA adds model serving with dynamic batching, model ensembling, and multi-model management. It pushes 3-5x throughput over naive serving through request queuing and GPU scheduling optimization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes with NVIDIA GPU Operator&lt;/strong&gt; handles orchestration. The GPU Operator automates driver installation, device plugin configuration, and monitoring setup. JPMorgan Chase and Goldman Sachs run AI workloads on Kubernetes clusters with this stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt; containers package models and their dependencies into reproducible deployments. A Dockerfile with vLLM, a quantized model, and an API wrapper gives you a single deployable artifact.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPU Performance Benchmarks
&lt;/h2&gt;

&lt;p&gt;The hardware choice determines throughput, cost per token, and model compatibility.&lt;/p&gt;

&lt;p&gt;NVIDIA H100 (80GB HBM3) delivers 580 tokens/second on LLaMA 70B inference at $0.18 per 1M tokens. It represents the price-performance sweet spot for production workloads.&lt;/p&gt;

&lt;p&gt;The H200 (141GB HBM3e) pushes 720 tokens/second with enough memory to run 70B parameter models without tensor parallelism across multiple GPUs. That simplifies deployment and reduces inter-GPU communication overhead.&lt;/p&gt;

&lt;p&gt;A100 (80GB HBM2e) remains viable at 180 tokens/second and $0.42 per 1M tokens. Used H100 pricing will push A100s into budget-tier territory through 2026-2027.&lt;/p&gt;

&lt;p&gt;L40S (48GB GDDR6) targets inference workloads that do not require HBM. At 120 tokens/second, it handles smaller models (7B-13B) efficiently and costs significantly less than the HBM-equipped options.&lt;/p&gt;

&lt;p&gt;MLPerf Inference v4.0 benchmarks confirm H100 delivers 3.2x the throughput of A100 for GPT-J inference. The H200 extends that gap further.&lt;/p&gt;

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

&lt;p&gt;A minimal self-hosted stack for local development and evaluation:&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;# Install vLLM&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;vllm

&lt;span class="c"&gt;# Start an OpenAI-compatible API server with a quantized model&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; vllm.entrypoints.openai.api_server &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--model&lt;/span&gt; TheBloke/Llama-2-70B-Chat-GPTQ &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--quantization&lt;/span&gt; gptq &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tensor-parallel-size&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--port&lt;/span&gt; 8000

&lt;span class="c"&gt;# Query the model&lt;/span&gt;
curl http://localhost:8000/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
        "model": "TheBloke/Llama-2-70B-Chat-GPTQ",
        "messages": [{"role": "user", "content": "Explain vLLM PagedAttention"}],
        "max_tokens": 512
    }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Kubernetes production deployments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm-inference&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm/vllm-openai:latest&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--model"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Llama-2-70b-chat-hf"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--tensor-parallel-size"&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4"&lt;/span&gt;
          &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;nvidia.com/gpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8000&lt;/span&gt;
      &lt;span class="na"&gt;nodeSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;nvidia.com/gpu.product&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NVIDIA-H100-80GB-HBM3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scale horizontally behind a load balancer. Add Prometheus metrics for latency, throughput, and GPU utilization monitoring. Set alerts at p99 latency above 100ms and GPU utilization below 40% (indicates over-provisioning).&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Self-hosting data sourced from IDC AI Infrastructure Report 2024, Stanford AI Index 2023, Gartner Cloud AI Survey 2023, MLPerf Inference v4.0 benchmarks, Linux Foundation Open Infrastructure Survey 2024, and NVIDIA DGX documentation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://pooyagolchian.github.io/subscribe" rel="noopener noreferrer"&gt;Subscribe to get new research articles with data visualizations&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>selfhostedai</category>
      <category>opensourceai</category>
      <category>aiinfrastructure</category>
      <category>gpuclusters</category>
    </item>
    <item>
      <title>scss-helper v5: A Modern SCSS Utility Toolkit for Tailwind's Gaps</title>
      <dc:creator>Pooya Golchian</dc:creator>
      <pubDate>Tue, 07 Apr 2026 22:07:15 +0000</pubDate>
      <link>https://forem.com/pooyagolchian/scss-helper-v5-a-modern-scss-utility-toolkit-for-tailwinds-gaps-42hn</link>
      <guid>https://forem.com/pooyagolchian/scss-helper-v5-a-modern-scss-utility-toolkit-for-tailwinds-gaps-42hn</guid>
      <description>&lt;p&gt;Tailwind CSS handles most styling needs well, but it doesn't cover everything. Fluid typography, CSS container queries, golden ratio layouts, and full 12-column grid control fall outside its scope. I built &lt;strong&gt;scss-helper&lt;/strong&gt; to fill exactly those gaps, a modular toolkit that complements Tailwind without competing with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pooyagolchian.github.io/scss-helper/" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Included
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;30+ CSS custom property tokens&lt;/strong&gt;: colors, spacing, typography&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;12-column CSS grid&lt;/strong&gt; with responsive breakpoints and auto-fit layouts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fluid &lt;code&gt;clamp()&lt;/code&gt; typography&lt;/strong&gt;: continuous scaling, no breakpoints needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dark mode&lt;/strong&gt;: dual strategy: &lt;code&gt;data-theme&lt;/code&gt; attribute + &lt;code&gt;prefers-color-scheme&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS container queries&lt;/strong&gt; for component-level responsiveness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Golden ratio&lt;/strong&gt; typography, spacing, and grid layouts (φ = 1.618)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;12 animations + 5 transition presets&lt;/strong&gt;, all &lt;code&gt;prefers-reduced-motion&lt;/code&gt; aware&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS v3/v4 plugin&lt;/strong&gt; to use tokens alongside Tailwind&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All classes use the &lt;code&gt;sh-&lt;/code&gt; prefix (configurable). Full bundle is &lt;strong&gt;5.1 KB gzipped&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add scss-helper
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; sass  &lt;span class="c"&gt;# Dart Sass &amp;gt;= 1.60 required&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SCSS (recommended)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Or cherry-pick modules&lt;/span&gt;
&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper/src/tokens/index'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper/src/typography/fluid'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper/src/golden/golden-ratio'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pre-compiled CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'scss-helper/css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c"&gt;/* Full bundle, 5.1 KB gzipped */&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'scss-helper/css/grid'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c"&gt;/* Grid only, 1.7 KB gzipped */&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;'scss-helper/css/tokens'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c"&gt;/* Tokens only, 583 B gzipped */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CDN
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://unpkg.com/scss-helper@5/dist/style.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Design Tokens
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0d6efd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--spacing-1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.25rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--spacing-4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--font-size-base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--line-height-base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5&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;30+ CSS custom properties generated from Sass variables. Compatible with Tailwind v4 &lt;code&gt;@theme&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Grid System
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Basic 12-column grid --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-grid sh-gap-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-col-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Main&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-col-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Sidebar&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Responsive, stacks on mobile, splits on desktop --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-grid sh-gap-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-col-12 sh-col-6-md sh-col-4-lg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-col-12 sh-col-6-md sh-col-4-lg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-col-12 sh-col-12-md sh-col-4-lg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Auto-fit: fills available space --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-grid-auto-md sh-gap-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Card&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Card&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Card&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breakpoint suffixes: &lt;code&gt;-xs&lt;/code&gt; (32rem) · &lt;code&gt;-sm&lt;/code&gt; (48rem) · &lt;code&gt;-md&lt;/code&gt; (64rem) · &lt;code&gt;-lg&lt;/code&gt; (80rem) · &lt;code&gt;-xl&lt;/code&gt; (90rem)&lt;/p&gt;

&lt;h2&gt;
  
  
  Fluid Typography
&lt;/h2&gt;

&lt;p&gt;Continuous font scaling using CSS &lt;code&gt;clamp()&lt;/code&gt;, no media queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-text-fluid-4xl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Headline&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-text-fluid-base"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Body text&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-xs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12px → 14px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-sm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;14px → 16px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-base&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16px → 18px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-lg&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;18px → 22px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-xl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;20px → 28px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-2xl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;24px → 36px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-3xl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;30px → 48px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sh-text-fluid-4xl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;36px → 64px&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Or call the SCSS function for arbitrary ranges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper/src/typography/fluid'&lt;/span&gt; &lt;span class="nt"&gt;as&lt;/span&gt; &lt;span class="nt"&gt;fluid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fluid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fluid-type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="mi"&gt;.5rem&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3rem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fluid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fluid-type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;30rem&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;90rem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Golden Ratio Layouts
&lt;/h2&gt;

&lt;p&gt;A full design system derived from phi (1.618):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"gs-text-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Display, 4.236rem&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"gs-text-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Section, 2.618rem&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"gs-text-0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Body, 1rem&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- 61.8% / 38.2% layout --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"gs-grid-golden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;Content&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;aside&amp;gt;&lt;/span&gt;Sidebar&lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper/src/golden/golden-ratio'&lt;/span&gt; &lt;span class="nt"&gt;as&lt;/span&gt; &lt;span class="nt"&gt;golden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;golden&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;golden-step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// 2.618rem&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;golden&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;golden-step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 1.618rem&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dark Mode
&lt;/h2&gt;

&lt;p&gt;Dual strategy, works with JS toggles and &lt;code&gt;prefers-color-scheme&lt;/code&gt; simultaneously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-dark-text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;White in dark mode&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper/src/dark/dark-mode'&lt;/span&gt; &lt;span class="nt"&gt;as&lt;/span&gt; &lt;span class="nt"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;@include&lt;/span&gt; &lt;span class="nd"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dark-mode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#1a1a1a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&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;h2&gt;
  
  
  Container Queries
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-cq"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-c-col-12 sh-c-col-6-sm sh-c-col-4-md"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Responds to container width, not viewport
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Animations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-animate-fade-in"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Fades in&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-animate-slide-up sh-delay-200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Slides up after 200ms&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sh-transition-colors sh-duration-fast"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Smooth color&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All 12 animation classes respect &lt;code&gt;prefers-reduced-motion&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind CSS Plugin
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scssHelper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scss-helper/plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;scssHelper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;injectTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper'&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;prefix&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'my-'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// -&amp;gt; .my-grid, .my-col-6, .my-animate-spin&lt;/span&gt;

&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper/src/variables'&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;primary&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;#8b5cf6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;grid-columns&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;16&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@use&lt;/span&gt; &lt;span class="s1"&gt;'scss-helper'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  v5 Migration from v4
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;v4&lt;/th&gt;
&lt;th&gt;v5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.grid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.sh-grid&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.col-6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.sh-col-6&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.text-fluid-lg&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.sh-text-fluid-lg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.animate-spin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.sh-animate-spin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.transition-colors&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.sh-transition-colors&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@import "scss-helper"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@use "scss-helper"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;-large&lt;/code&gt; suffix&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-lg&lt;/code&gt; suffix&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;a href="https://github.com/pooyagolchian/scss-helper" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://www.npmjs.com/package/scss-helper" rel="noopener noreferrer"&gt;npm&lt;/a&gt; · &lt;a href="https://pooyagolchian.github.io/scss-helper/" rel="noopener noreferrer"&gt;Full Documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>scss</category>
      <category>css</category>
      <category>opensource</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
