<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Hamid Raza</title>
    <description>The latest articles on DEV Community by Muhammad Hamid Raza (@hamidrazadev).</description>
    <link>https://dev.to/hamidrazadev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3131979%2Fb7099e70-ad31-427a-a339-c5f006874714.jpg</url>
      <title>DEV Community: Muhammad Hamid Raza</title>
      <link>https://dev.to/hamidrazadev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hamidrazadev"/>
    <language>en</language>
    <item>
      <title>How to Build a Next.js App That's Harder to Break in Penetration Testing 🔐</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Sat, 14 Nov 2026 10:40:52 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/how-to-build-a-nextjs-app-thats-harder-to-break-in-penetration-testing-27ae</link>
      <guid>https://dev.to/hamidrazadev/how-to-build-a-nextjs-app-thats-harder-to-break-in-penetration-testing-27ae</guid>
      <description>&lt;p&gt;You ship your Next.js app. It looks great and the Lighthouse score is green. Then a penetration tester sends you a report, and it's longer than your README.&lt;/p&gt;

&lt;p&gt;It happens to many of us. Security often feels like something to "add later," right after the feature is done. Later usually arrives as a surprise.&lt;/p&gt;

&lt;p&gt;So here's a question: what if your next pen test came back with only a few small notes instead of a wall of red? 😊&lt;/p&gt;

&lt;p&gt;No app is 100% unhackable, and anyone who promises that is selling something. But you can build a &lt;strong&gt;secure Next.js app&lt;/strong&gt; that is much harder to attack. Let's do it step by step.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does "Hard to Penetrate" Actually Mean?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Penetration testing&lt;/strong&gt; (pen testing) is when a security tester, with permission, tries to break into your app the way a real attacker would. They look for weak spots, then report them so you can fix them.&lt;/p&gt;

&lt;p&gt;Think of your app as a house:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;doors and windows&lt;/strong&gt; are your login, forms, and API routes.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;locks&lt;/strong&gt; are your authentication and authorization.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;security camera&lt;/strong&gt; is your logging and monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A pen tester walks around the house and tries every handle. A hard-to-penetrate app has strong locks, few unnecessary doors, and nothing valuable left on the porch.&lt;/p&gt;

&lt;p&gt;Your goal isn't a perfect house. It's a house where the easy tricks don't work, so attackers give up or get caught.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real users trust you with real data.&lt;/strong&gt; Emails, passwords, and messages deserve protection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixing early is cheaper.&lt;/strong&gt; A missing check found during development takes minutes. Found after launch, it can take days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client and employer confidence.&lt;/strong&gt; If you build for clients or want a strong portfolio, secure habits set you apart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer 2 a.m. emergencies.&lt;/strong&gt; Boring, solid security means calmer weekends. ✅&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  10 Practical Ways to Harden Your Next.js App
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Keep Next.js and your dependencies updated
&lt;/h3&gt;

&lt;p&gt;Security bugs get found in frameworks, and fixes ship in updates. For example, in 2025 a vulnerability (CVE-2025-29927) showed that apps relying only on middleware for authorization could be bypassed in some versions. Updating fixed it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer moment:&lt;/strong&gt; "I'll update later" is the most expensive sentence in web development. 😅&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update Next.js and React regularly.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;pnpm audit&lt;/code&gt; and read the results.&lt;/li&gt;
&lt;li&gt;Check the official Next.js security announcements now and then.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Check permissions close to the data
&lt;/h3&gt;

&lt;p&gt;This is the big one. Don't rely only on middleware or hidden buttons to protect things.&lt;/p&gt;

&lt;p&gt;Server Actions and Route Handlers are reachable over HTTP, so treat each one like a public API endpoint. Anyone can call them directly, not just through your UI.&lt;/p&gt;

&lt;p&gt;Check &lt;strong&gt;who the user is&lt;/strong&gt; and &lt;strong&gt;what they're allowed to do&lt;/strong&gt; right where the data is read or changed:&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="s2"&gt;"use server"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"zod"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;getCurrentUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"@/lib/auth"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"@/lib/db"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deletePost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FormData&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="n"&gt;user&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;getCurrentUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Unauthorized"&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="n"&gt;postId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"postId"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;postId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authorId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Forbidden"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;postId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice three things: login check, input validation, and ownership check. Skipping the ownership check is a classic pen-test finding, where user A can edit user B's data by changing an ID.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Validate every input on the server
&lt;/h3&gt;

&lt;p&gt;Browser validation is for user-friendliness, not security. Anyone can skip your form and send requests directly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate request bodies, query params, and form data on the server.&lt;/li&gt;
&lt;li&gt;A schema library like Zod makes this clean.&lt;/li&gt;
&lt;li&gt;Reject anything unexpected instead of trying to "fix" it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Add security headers
&lt;/h3&gt;

&lt;p&gt;Headers are a cheap way to close several doors at once. In Next.js you can set them in &lt;code&gt;next.config.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="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="nc"&gt;NextConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;securityHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"X-Content-Type-Options"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"nosniff"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"X-Frame-Options"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"DENY"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Referrer-Policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"strict-origin-when-cross-origin"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Strict-Transport-Security"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"max-age=63072000; includeSubDomains"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Permissions-Policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"camera=(), microphone=(), geolocation=()"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;NextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;poweredByHeader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/(.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;securityHeaders&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="n"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also consider a &lt;strong&gt;Content Security Policy (CSP)&lt;/strong&gt;. It tells the browser which scripts and resources are allowed, which reduces the damage if an XSS bug slips through. The Next.js docs explain how to set one up with nonces. Test it carefully, since a strict CSP can break scripts you forgot about.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Protect your cookies and sessions
&lt;/h3&gt;

&lt;p&gt;If you handle sessions yourself, set cookies with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;httpOnly&lt;/code&gt; so JavaScript can't read them&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;secure&lt;/code&gt; so they only travel over HTTPS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sameSite&lt;/code&gt; (usually &lt;code&gt;lax&lt;/code&gt; or &lt;code&gt;strict&lt;/code&gt;) to reduce CSRF risk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Better still, use a well-maintained auth library instead of writing session logic from scratch. Rolling your own auth is how many bugs are born.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Keep secrets out of the browser
&lt;/h3&gt;

&lt;p&gt;In Next.js, any environment variable starting with &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; is bundled into client code. Anyone can read it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never put API secrets, database URLs, or private keys behind &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;server-only&lt;/code&gt; package to stop server code from being imported into client components by accident.&lt;/li&gt;
&lt;li&gt;Never commit &lt;code&gt;.env&lt;/code&gt; files to Git.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Be careful with HTML you didn't write
&lt;/h3&gt;

&lt;p&gt;React escapes content by default, which protects you from a lot of XSS. The danger starts when you bypass it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt; unless you really need it.&lt;/li&gt;
&lt;li&gt;If you do need it, sanitize the HTML with a trusted library first.&lt;/li&gt;
&lt;li&gt;Never trust user-provided URLs blindly, especially in &lt;code&gt;href&lt;/code&gt; attributes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. Add rate limiting to sensitive routes
&lt;/h3&gt;

&lt;p&gt;Login, password reset, and signup endpoints attract automated guessing. Rate limiting slows that down.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limit attempts per IP or per account.&lt;/li&gt;
&lt;li&gt;Add small delays or temporary lockouts after repeated failures.&lt;/li&gt;
&lt;li&gt;Use the same generic message for "wrong email" and "wrong password" so attackers can't learn which accounts exist.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. Don't leak details in errors
&lt;/h3&gt;

&lt;p&gt;A stack trace is a gift to an attacker. It can reveal file paths, library versions, and database details.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show users a friendly, generic error.&lt;/li&gt;
&lt;li&gt;Log the real details on the server.&lt;/li&gt;
&lt;li&gt;Don't expose internal IDs or database error messages in API responses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10. Test your own app (with permission)
&lt;/h3&gt;

&lt;p&gt;Before a real pen tester shows up, try basic checks yourself. Only test apps you own or have written permission to test.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run an automated scanner like &lt;strong&gt;OWASP ZAP&lt;/strong&gt; against your staging site.&lt;/li&gt;
&lt;li&gt;Walk through the &lt;strong&gt;OWASP Top 10&lt;/strong&gt; list and ask, "Could this happen in my app?"&lt;/li&gt;
&lt;li&gt;Try to access another user's data by changing an ID in the URL. If it works, you've found a real bug. 👀&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comparison: Client-Side Checks vs Server-Side Checks
&lt;/h2&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;Client-side only&lt;/th&gt;
&lt;th&gt;Server-side enforced&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hiding an "Admin" button&lt;/td&gt;
&lt;td&gt;Looks secure&lt;/td&gt;
&lt;td&gt;Actually secure only if the server also checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form validation&lt;/td&gt;
&lt;td&gt;Good for UX&lt;/td&gt;
&lt;td&gt;Needed for security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pen-test result&lt;/td&gt;
&lt;td&gt;Easy to bypass&lt;/td&gt;
&lt;td&gt;Much harder to bypass&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The UI is the lobby, and the server is the locked vault. Pen testers skip the lobby and go straight to the vault.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Do's and Don'ts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do ✅&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check authorization on every Server Action and API route&lt;/li&gt;
&lt;li&gt;Validate all input on the server&lt;/li&gt;
&lt;li&gt;Keep dependencies updated&lt;/li&gt;
&lt;li&gt;Use trusted auth libraries&lt;/li&gt;
&lt;li&gt;Log suspicious activity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't ❌&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trust the frontend to enforce rules&lt;/li&gt;
&lt;li&gt;Put secrets in &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; variables&lt;/li&gt;
&lt;li&gt;Show raw error messages to users&lt;/li&gt;
&lt;li&gt;Disable security features just to make an error go away&lt;/li&gt;
&lt;li&gt;Assume "nobody will find this URL" is a security plan&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Protecting only the page, not the action.&lt;/strong&gt;&lt;br&gt;
The page is hidden from non-admins, but the API behind it is open. This happens because the UI feels like the whole app. Protect the data layer too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Trusting IDs from the client.&lt;/strong&gt;&lt;br&gt;
If the request says &lt;code&gt;userId: 42&lt;/code&gt;, don't believe it. Take the user from the session instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Treating security as a final-week task.&lt;/strong&gt;&lt;br&gt;
Adding it at the end means rewriting things. Build the habits in from day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Copy-pasting auth code you don't understand.&lt;/strong&gt;&lt;br&gt;
It works until it doesn't. Read what it does, or use a maintained library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Forgetting old routes and test endpoints.&lt;/strong&gt;&lt;br&gt;
That &lt;code&gt;/api/test&lt;/code&gt; route from last month may still be live. Clean up before deploying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Believing "my framework handles it."&lt;/strong&gt;&lt;br&gt;
Next.js gives you good defaults, but it can't know your business rules. Who can see what is your job.&lt;/p&gt;




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

&lt;p&gt;Building a &lt;strong&gt;Next.js app that's harder to penetrate&lt;/strong&gt; isn't about being a security genius. It's about a handful of solid habits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep everything updated&lt;/li&gt;
&lt;li&gt;Check permissions on the server, close to the data&lt;/li&gt;
&lt;li&gt;Validate all input&lt;/li&gt;
&lt;li&gt;Set security headers&lt;/li&gt;
&lt;li&gt;Protect cookies and secrets&lt;/li&gt;
&lt;li&gt;Limit abuse with rate limiting&lt;/li&gt;
&lt;li&gt;Test your own work before someone else does&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start with one or two of these today. Secure apps are built one small, boring, careful step at a time. 🚀&lt;/p&gt;

&lt;p&gt;If this helped, you can read more developer-friendly posts on &lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;. And if you know someone shipping a Next.js app, share this with them. What's the most surprising security bug you've seen in a project? Drop it in the comments. 😊&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>security</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How Claude Code Can Edit Video Without You Knowing Video Editing</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Thu, 12 Nov 2026 17:52:47 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/how-claude-code-can-edit-video-without-you-knowing-video-editing-19ln</link>
      <guid>https://dev.to/hamidrazadev/how-claude-code-can-edit-video-without-you-knowing-video-editing-19ln</guid>
      <description>&lt;p&gt;Ever opened a video editor, stared at the timeline, and quietly closed it again? 😅&lt;/p&gt;

&lt;p&gt;Many developers have been there. We can build apps, but trimming a 10-second clip feels harder than it should.&lt;/p&gt;

&lt;p&gt;Here is the good news. &lt;strong&gt;Claude Code can edit video&lt;/strong&gt; through code and command-line tools, so you describe what you want in plain English and it works out the technical steps. Image generation is already common. Video is next, and you can try it with tools that exist today. 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Video Editing With Claude Code?
&lt;/h2&gt;

&lt;p&gt;Claude Code is a coding assistant that works in your terminal. It can read your files, write code, and run commands.&lt;/p&gt;

&lt;p&gt;It does not "watch" your video and click around a timeline like a human editor. Instead, it uses tools that edit video through text commands.&lt;/p&gt;

&lt;p&gt;Think of it like a kitchen. You are the customer, Claude Code is the chef, and the tools are the stove and knives. You say what you want to eat, and the chef picks the tools.&lt;/p&gt;

&lt;p&gt;The three tools most people would reach for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FFmpeg&lt;/strong&gt;: a command-line tool for trimming, joining, converting, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remotion&lt;/strong&gt;: a framework that creates videos from React code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MoviePy&lt;/strong&gt;: a Python library for editing video in scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Video is everywhere: tutorials, demos, social posts, product walkthroughs. But learning editing software and FFmpeg's long commands takes time.&lt;/p&gt;

&lt;p&gt;With this approach, you can skip memorizing flags and focus on what you want the final video to look like. It also makes repeated jobs easier, because code can be run again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits With Real-Life Examples
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No need to memorize commands.&lt;/strong&gt; Ask for "cut seconds 10 to 25 from this clip" and Claude Code can write the FFmpeg command for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeatable work.&lt;/strong&gt; Need the same intro on 20 videos? A script can do it in one go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Videos as code.&lt;/strong&gt; With Remotion, you can build a title animation using React, a skill many frontend developers already have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy small fixes.&lt;/strong&gt; Extract audio, resize for social media, or convert formats without opening heavy software.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning by reading.&lt;/strong&gt; You can ask it to explain each command, so you learn while you work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the kind of prompt you might give:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trim input.mp4 from 00:00:10 to 00:00:25 and save it as clip.mp4.
Explain the command you used.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a command it might produce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg -i input.mp4 -ss 00:00:10 -to 00:00:25 -c copy clip.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Using &lt;code&gt;-c copy&lt;/code&gt; is fast, but cuts can land slightly off because of how video is stored. If you need exact cuts, ask it to re-encode.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison: Which Tool Fits Which Job?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Skill it leans on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FFmpeg&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quick edits: trim, join, convert, extract audio&lt;/td&gt;
&lt;td&gt;Command line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MoviePy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scripted edits and simple effects&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Remotion&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Designed, animated videos&lt;/td&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A simple rule: start with FFmpeg for editing existing footage. Choose Remotion when you want to &lt;em&gt;create&lt;/em&gt; a video from scratch with text and animation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Tips: Do's and Don'ts
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ Work on &lt;strong&gt;copies&lt;/strong&gt; of your files, never the originals.&lt;/li&gt;
&lt;li&gt;✅ Ask for one small change at a time.&lt;/li&gt;
&lt;li&gt;✅ Ask Claude Code to explain commands before you run them.&lt;/li&gt;
&lt;li&gt;✅ Watch the output yourself. You are the final reviewer. 👀&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Expect it to "see" your video like a person.&lt;/li&gt;
&lt;li&gt;❌ Paste huge requests like "make this viral."&lt;/li&gt;
&lt;li&gt;❌ Skip checking audio sync and quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vague prompts.&lt;/strong&gt; "Make it better" gives vague results. Say what to change: trim, resize, add captions, speed up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overwriting the original file.&lt;/strong&gt; One wrong command and your footage is gone. Always keep a backup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not having the tools installed.&lt;/strong&gt; FFmpeg, Python, or Node must exist on your machine. If something fails, ask Claude Code to check what is missing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trusting the first result blindly.&lt;/strong&gt; Always preview. A cut a second too early is easy to miss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Starting too big.&lt;/strong&gt; Try a 10-second clip first, then scale up. 💡&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Learning how Claude Code can edit video does not mean becoming a professional editor. It means knowing the right tools exist (FFmpeg, MoviePy, Remotion) and letting Claude Code handle the technical typing while you guide the vision.&lt;/p&gt;

&lt;p&gt;Start small, keep backups, and check your results. You may be surprised how far a few plain-English prompts can take you. ⚡&lt;/p&gt;

&lt;p&gt;If this helped, feel free to share it with a developer friend who avoids video editing. For more practical dev guides, visit &lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;. And tell me in the comments: what video task would you try first? 😊&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What Are t9n, l10n, i18n, and g11n? A Simple Guide for Developers</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Mon, 09 Nov 2026 10:58:16 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/what-are-t9n-l10n-i18n-and-g11n-a-simple-guide-for-developers-3f74</link>
      <guid>https://dev.to/hamidrazadev/what-are-t9n-l10n-i18n-and-g11n-a-simple-guide-for-developers-3f74</guid>
      <description>&lt;p&gt;You open a codebase and see folders named &lt;code&gt;i18n&lt;/code&gt;. Then a teammate mentions &lt;code&gt;l10n&lt;/code&gt; in a pull request. Someone else says "we need better g11n." And you quietly nod, hoping nobody asks you to explain. 😅&lt;/p&gt;

&lt;p&gt;Been there? You're not alone. These strange abbreviations show up in almost every app that serves more than one language. So what do &lt;strong&gt;t9n, l10n, i18n, and g11n&lt;/strong&gt; actually mean, and how are they different?&lt;/p&gt;

&lt;p&gt;Let's break them down in plain English. 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are t9n, l10n, i18n, and g11n?
&lt;/h2&gt;

&lt;p&gt;First, the naming trick. Each abbreviation keeps the &lt;strong&gt;first letter&lt;/strong&gt;, the &lt;strong&gt;last letter&lt;/strong&gt;, and replaces everything in between with a &lt;strong&gt;number&lt;/strong&gt;. That number is how many letters were skipped.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;t9n&lt;/strong&gt; = &lt;strong&gt;t&lt;/strong&gt;ranslatio*&lt;em&gt;n&lt;/em&gt;* (9 letters between t and n)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;l10n&lt;/strong&gt; = &lt;strong&gt;l&lt;/strong&gt;ocalizatio*&lt;em&gt;n&lt;/em&gt;* (10 letters between l and n)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;i18n&lt;/strong&gt; = &lt;strong&gt;i&lt;/strong&gt;nternationalizatio*&lt;em&gt;n&lt;/em&gt;* (18 letters between i and n)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;g11n&lt;/strong&gt; = &lt;strong&gt;g&lt;/strong&gt;lobalizatio*&lt;em&gt;n&lt;/em&gt;* (11 letters between g and n)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers did this because the full words are long, and typing "internationalization" fifty times gets old fast.&lt;/p&gt;

&lt;p&gt;Now the meanings:&lt;/p&gt;

&lt;h3&gt;
  
  
  t9n: Translation
&lt;/h3&gt;

&lt;p&gt;Turning text from one language into another. "Welcome" becomes "Bienvenido." That's it. Translation is just about &lt;strong&gt;words&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  l10n: Localization
&lt;/h3&gt;

&lt;p&gt;Adapting your product for a specific &lt;strong&gt;language and region&lt;/strong&gt;. This includes translation, but also dates, times, currency, number formats, images, and cultural details.&lt;/p&gt;

&lt;h3&gt;
  
  
  i18n: Internationalization
&lt;/h3&gt;

&lt;p&gt;Building your app so it &lt;strong&gt;can&lt;/strong&gt; support many languages and regions without rewriting the code each time. Think of it as preparing the house before the guests arrive.&lt;/p&gt;

&lt;h3&gt;
  
  
  g11n: Globalization
&lt;/h3&gt;

&lt;p&gt;The big-picture term. It usually means the whole process of making a product work for a worldwide audience, and it commonly covers both i18n and l10n. 🌍&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick note:&lt;/strong&gt; these terms are used a little differently from team to team, and &lt;code&gt;t9n&lt;/code&gt; in particular is less standardized than the others. If something is unclear, ask what your team means by it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A Simple Analogy: Opening a Restaurant
&lt;/h2&gt;

&lt;p&gt;Imagine you run a restaurant and want to serve customers in many countries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;i18n:&lt;/strong&gt; You design the kitchen so the menu can be swapped easily, instead of painting dishes on the wall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;t9n:&lt;/strong&gt; You translate the menu into other languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;l10n:&lt;/strong&gt; You also adjust prices, portion sizes, and local dishes for each country.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;g11n:&lt;/strong&gt; The whole plan of serving customers worldwide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same restaurant, different layers of work. 😊&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Not everyone reads English, and even people who do often prefer their own language. Even within one language, details differ. For example, &lt;code&gt;07/11/2026&lt;/code&gt; can mean 7 November or July 11 depending on where you live. That small difference can cause real confusion.&lt;/p&gt;

&lt;p&gt;If you ignore this early, you may end up with text hardcoded all over your components. Fixing that later is painful. 🔧&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits with Real-Life Examples
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reach more users.&lt;/strong&gt; A learning app that offers Urdu and English can serve more students than one that offers only English.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer confusing moments.&lt;/strong&gt; Showing prices as "$1,000.50" to one user and "1.000,50 €" to another matches what each person expects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easier maintenance.&lt;/strong&gt; With i18n done right, adding a new language often means adding a translation file, not touching component logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More trust.&lt;/strong&gt; Users usually feel more comfortable when an app feels made for them, not just translated at them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports different writing directions.&lt;/strong&gt; Languages like Arabic and Urdu are written right to left, and a well-prepared layout can handle that.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Comparison: i18n vs l10n vs t9n
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;th&gt;Who usually does it&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;t9n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Words only&lt;/td&gt;
&lt;td&gt;Translators&lt;/td&gt;
&lt;td&gt;"Cart" → "Carrito"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;l10n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Language + region details&lt;/td&gt;
&lt;td&gt;Translators, designers, developers&lt;/td&gt;
&lt;td&gt;Local date, currency, images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;i18n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Making the code ready&lt;/td&gt;
&lt;td&gt;Developers&lt;/td&gt;
&lt;td&gt;Using translation keys instead of hardcoded text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;g11n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The overall strategy&lt;/td&gt;
&lt;td&gt;Product and engineering teams&lt;/td&gt;
&lt;td&gt;Planning a worldwide launch&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A handy memory trick: &lt;strong&gt;i18n is the foundation, l10n is the finishing touch, and t9n is one part of l10n.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Tips: Do's and Don'ts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Do
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use translation keys.&lt;/strong&gt; Write &lt;code&gt;t("cart.title")&lt;/code&gt; instead of the raw string "Your Cart."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use built-in formatting tools.&lt;/strong&gt; JavaScript's &lt;code&gt;Intl&lt;/code&gt; API can format dates, numbers, and currencies for different locales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave room in your layout.&lt;/strong&gt; Translated text can be longer or shorter than English.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan for plurals.&lt;/strong&gt; "1 item" and "2 items" don't work the same way in every language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start early.&lt;/strong&gt; Even if you launch in one language, prepare for more.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Don't
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Don't build sentences by gluing words together. Word order changes between languages.&lt;/li&gt;
&lt;li&gt;Don't assume everyone uses the same date or number format.&lt;/li&gt;
&lt;li&gt;Don't put text inside images if you can avoid it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a tiny example of the idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Hardcoded (hard to translate)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="nx"&gt;back&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// With a translation key (i18n-ready)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;home.welcome&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Formatting a price for a locale&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&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="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EUR&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="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1000.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Mixing up the terms.&lt;/strong&gt; Many people use "translation" and "localization" as if they mean the same thing. They don't. Translation is one piece of localization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Hardcoding text.&lt;/strong&gt; It feels faster at the start. It becomes a headache when a second language arrives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Translating word for word.&lt;/strong&gt; Literal translations can sound awkward or confusing. Good localization considers meaning and context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Forgetting layout changes.&lt;/strong&gt; A button that fits "Save" may break with a longer translated word.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Treating language and country as the same thing.&lt;/strong&gt; One language can be used in many regions, with different formats and spelling.&lt;/p&gt;




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

&lt;p&gt;Let's recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;t9n&lt;/strong&gt; is translation: converting words.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;l10n&lt;/strong&gt; is localization: adapting for a language and region.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;i18n&lt;/strong&gt; is internationalization: building your app to support that adaptation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;g11n&lt;/strong&gt; is globalization: the overall effort of serving a worldwide audience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next time you see these abbreviations in a codebase, you'll know exactly what's going on. And if you're starting a new project, a little i18n preparation now can save you a lot of pain later. 💡&lt;/p&gt;

&lt;p&gt;If this guide helped, share it with a teammate who's still nodding politely at "l10n." 😄 Want more practical dev content? Read more blogs at &lt;strong&gt;&lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;&lt;/strong&gt;. And if you have a localization story or question, drop it in the comments. I'd love to hear it!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>i18n</category>
    </item>
    <item>
      <title>How to Apply Multiple Themes in Next.js (Blue, Green, Red and More) Without Refreshing or Using `dark:` Classes</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Sat, 07 Nov 2026 13:39:15 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/how-to-apply-multiple-themes-in-nextjs-blue-green-red-and-more-without-refreshing-or-using-bi0</link>
      <guid>https://dev.to/hamidrazadev/how-to-apply-multiple-themes-in-nextjs-blue-green-red-and-more-without-refreshing-or-using-bi0</guid>
      <description>&lt;p&gt;Your site has a dark mode. Then a client asks, "Can we also have a blue theme? And a green one? Oh, and red!" 😅&lt;/p&gt;

&lt;p&gt;Suddenly you are staring at &lt;code&gt;dark:bg-gray-900 blue:bg-blue-900 green:bg-green-900 red:bg-red-900&lt;/code&gt; on every element. That is a lot of repeated classes.&lt;/p&gt;

&lt;p&gt;There is a cleaner way. You define every theme's colors &lt;strong&gt;once&lt;/strong&gt; in your global CSS. To switch themes, you change &lt;strong&gt;one class&lt;/strong&gt; on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element. No page refresh, no HTML changes, no per-element theme classes.&lt;/p&gt;

&lt;p&gt;Ready to see how it works? 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Multi-Theme System in Next.js?
&lt;/h2&gt;

&lt;p&gt;A multi-theme system lets users switch between more than two color schemes, such as light, dark, blue, green, and red. The switch happens instantly, with no reload.&lt;/p&gt;

&lt;p&gt;Think of a &lt;strong&gt;TV remote&lt;/strong&gt;. The TV (your HTML) stays exactly the same. You press a button (change one class) and the colors change.&lt;/p&gt;

&lt;p&gt;The idea has three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CSS variables&lt;/strong&gt; hold the colors, like &lt;code&gt;--background&lt;/code&gt; and &lt;code&gt;--primary&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A class on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;&lt;/strong&gt;, like &lt;code&gt;blue&lt;/code&gt; or &lt;code&gt;red&lt;/code&gt;, decides which set of values is active.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your components&lt;/strong&gt; use names like &lt;code&gt;bg-background&lt;/code&gt; and &lt;code&gt;text-foreground&lt;/code&gt;, never specific colors.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your components never know which theme is active. They just ask for "the background color" and the CSS answers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Topic Matters
&lt;/h2&gt;

&lt;p&gt;Theming gets messy fast when colors are written directly into components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a new theme means editing many files.&lt;/li&gt;
&lt;li&gt;Rebranding means hunting through the whole codebase for color classes.&lt;/li&gt;
&lt;li&gt;Markup gets longer and harder to read.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the variable approach, a new theme is one new block in one CSS file. Components stay untouched.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits with Real-Life Examples
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean HTML and JSX.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;className="bg-background text-foreground"&lt;/code&gt; replaces a long chain of per-theme classes. A card component looks the same in every theme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One place for all colors.&lt;/strong&gt;&lt;br&gt;
Your client says, "Make the green theme a bit softer." You change one value in &lt;code&gt;globals.css&lt;/code&gt;, and every button, card, and navbar follows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy to add new themes.&lt;/strong&gt;&lt;br&gt;
Want a purple theme? Add a &lt;code&gt;.purple { ... }&lt;/code&gt; block. No component changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Instant switching, no refresh.&lt;/strong&gt;&lt;br&gt;
Changing a class on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; makes the browser re-apply styles. There is no page reload, and React does not need to re-render your components just to change colors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less repeated code.&lt;/strong&gt;&lt;br&gt;
You are not generating and shipping theme-specific variants for every element, which keeps your markup and CSS leaner. (It will not magically shrink your app by half, but the duplication really does go away.)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step-by-Step: Build It
&lt;/h2&gt;

&lt;p&gt;This guide assumes the &lt;strong&gt;Next.js App Router&lt;/strong&gt; and &lt;strong&gt;Tailwind CSS v4&lt;/strong&gt;. A note for Tailwind v3 users appears later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define Your Themes in &lt;code&gt;globals.css&lt;/code&gt;
&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="s1"&gt;"tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;/* Default (light) theme */&lt;/span&gt;
&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#111827&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#f3f4f6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#4f46e5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.dark&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#0b0f19&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#e5e7eb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#151b2b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#818cf8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#0b0f19&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.blue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#eff6ff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#1e3a8a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#dbeafe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#2563eb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.green&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#f0fdf4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#14532d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#dcfce7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#16a34a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.red&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#fef2f2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#7f1d1d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#fee2e2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#dc2626&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--primary-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every theme defines the &lt;strong&gt;same variable names&lt;/strong&gt; with different values. That is the whole trick. 💡&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Connect the Variables to Tailwind
&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;@theme&lt;/span&gt; &lt;span class="nb"&gt;inline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="l"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="l"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="l"&gt;--card&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="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="l"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-primary-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="l"&gt;--primary-foreground&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;bg-background&lt;/code&gt;, &lt;code&gt;text-foreground&lt;/code&gt;, &lt;code&gt;bg-card&lt;/code&gt;, and &lt;code&gt;bg-primary&lt;/code&gt; work as normal Tailwind classes. They read the live CSS variable, so they follow whichever theme class is active.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Use Semantic Classes in Your Components
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PricingCard&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"rounded-xl bg-card p-6 text-foreground"&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;h3&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xl font-bold"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pro Plan&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Everything you need to ship faster.&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-4 rounded-lg bg-primary px-4 py-2 text-primary-foreground"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Get Started
      &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;There are no &lt;code&gt;dark:&lt;/code&gt;, &lt;code&gt;blue:&lt;/code&gt;, or &lt;code&gt;red:&lt;/code&gt; classes anywhere. This markup works for every theme you will ever add.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Create the Theme Switcher
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/theme-switcher.tsx&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&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;THEMES&lt;/span&gt; &lt;span class="o"&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;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="s2"&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="s2"&gt;blue&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;green&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;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kd"&gt;as const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;THEMES&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ThemeSwitcher&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;applyTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Theme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;root&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;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&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="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex gap-2"&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;THEMES&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;theme&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;button&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;theme&lt;/span&gt;&lt;span class="si"&gt;}&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;applyTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"rounded-md bg-primary px-3 py-1 text-sm capitalize text-primary-foreground"&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;theme&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;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clicking a button removes the old theme class and adds the new one. The colors change instantly. The choice is saved in &lt;code&gt;localStorage&lt;/code&gt; so it survives a reload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Avoid the "Flash of Wrong Theme"
&lt;/h3&gt;

&lt;p&gt;You have probably seen this: the page loads white, then flips to dark a moment later. It happens because the saved theme is applied only after React loads.&lt;/p&gt;

&lt;p&gt;The fix is a tiny inline script that runs &lt;strong&gt;before the page paints&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt; &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;
          &lt;span class="na"&gt;dangerouslySetInnerHTML&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="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
              try {
                var t = localStorage.getItem('theme');
                if (t) document.documentElement.classList.add(t);
              } catch (e) {}
            `&lt;/span&gt;&lt;span class="p"&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;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-background text-foreground"&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;children&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;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;suppressHydrationWarning&lt;/code&gt; on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; is needed because the script changes the &lt;code&gt;class&lt;/code&gt; before React hydrates. Without it, React may warn about a mismatch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparison: Per-Element Theme Classes vs CSS Variables
&lt;/h2&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;Per-element classes (&lt;code&gt;dark:&lt;/code&gt;, &lt;code&gt;red:&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;CSS variables + one class&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Markup length&lt;/td&gt;
&lt;td&gt;Grows with every theme&lt;/td&gt;
&lt;td&gt;Stays the same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adding a new theme&lt;/td&gt;
&lt;td&gt;Edit many components&lt;/td&gt;
&lt;td&gt;Add one CSS block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changing a color&lt;/td&gt;
&lt;td&gt;Search across files&lt;/td&gt;
&lt;td&gt;Edit one value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Quick one-off tweaks&lt;/td&gt;
&lt;td&gt;Real multi-theme apps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Per-element classes are not "wrong". For a simple light/dark site they work fine. But once you go beyond two themes, variables win on maintainability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Tips and Do's &amp;amp; Don'ts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do ✅&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;semantic names&lt;/strong&gt; (&lt;code&gt;background&lt;/code&gt;, &lt;code&gt;primary&lt;/code&gt;, &lt;code&gt;card&lt;/code&gt;) instead of color names (&lt;code&gt;blue-500&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Define &lt;strong&gt;the same set of variables in every theme&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;color-scheme&lt;/code&gt; for dark themes so native elements like scrollbars and form inputs match.&lt;/li&gt;
&lt;li&gt;Test text contrast in every theme. A readable blue theme can still hide text in the red one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't ❌&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't put theme-specific colors directly in components.&lt;/li&gt;
&lt;li&gt;Don't forget the pre-paint script, or users will see a flash.&lt;/li&gt;
&lt;li&gt;Don't skip &lt;code&gt;suppressHydrationWarning&lt;/code&gt; on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; if you use that script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tailwind v3 note:&lt;/strong&gt; v3 has no &lt;code&gt;@theme&lt;/code&gt; block. Map the variables in &lt;code&gt;tailwind.config.js&lt;/code&gt; instead, for example &lt;code&gt;background: "var(--background)"&lt;/code&gt;. If you want opacity modifiers like &lt;code&gt;bg-primary/50&lt;/code&gt; in v3, store the variables as RGB channels (like &lt;code&gt;253 110 78&lt;/code&gt;) and use &lt;code&gt;rgb(var(--primary) / &amp;lt;alpha-value&amp;gt;)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prefer a library?&lt;/strong&gt; &lt;a href="https://github.com/pacocoursey/next-themes" rel="noopener noreferrer"&gt;&lt;code&gt;next-themes&lt;/code&gt;&lt;/a&gt; supports custom theme names through its &lt;code&gt;themes&lt;/code&gt; prop and handles storage and the flash problem for you. The CSS-variable idea in this article works the same way with it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Using &lt;code&gt;dark:&lt;/code&gt; plus custom variants for every theme.&lt;/strong&gt;&lt;br&gt;
It feels natural because that is how dark mode is usually taught. The fix is to define semantic variables once.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Forgetting to remove the old class.&lt;/strong&gt;&lt;br&gt;
If you only add &lt;code&gt;red&lt;/code&gt; and never remove &lt;code&gt;blue&lt;/code&gt;, both classes stay on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;, and CSS order decides who wins. Always remove the old theme class first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Missing variables in one theme.&lt;/strong&gt;&lt;br&gt;
If &lt;code&gt;.green&lt;/code&gt; forgets &lt;code&gt;--card&lt;/code&gt;, it inherits the value from &lt;code&gt;:root&lt;/code&gt;, so you get odd colors. Keep every theme's variable list identical.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reading &lt;code&gt;localStorage&lt;/code&gt; during server rendering.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;localStorage&lt;/code&gt; only exists in the browser. Use it inside event handlers, effects, or the inline script, not in server components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ignoring accessibility.&lt;/strong&gt;&lt;br&gt;
A pretty theme with low contrast is a bad theme. Check readability for every one.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;Here is the recipe again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define each theme's colors &lt;strong&gt;once&lt;/strong&gt; in &lt;code&gt;globals.css&lt;/code&gt; using CSS variables.&lt;/li&gt;
&lt;li&gt;Map those variables to semantic Tailwind colors.&lt;/li&gt;
&lt;li&gt;Use classes like &lt;code&gt;bg-background&lt;/code&gt; and &lt;code&gt;text-primary&lt;/code&gt; in your components.&lt;/li&gt;
&lt;li&gt;Switch themes by changing &lt;strong&gt;one class&lt;/strong&gt; on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a tiny pre-paint script so users never see a flash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is cleaner JSX, a single place to manage colors, and instant theme switching with no refresh. Adding a new theme becomes a ten-line job. 😊&lt;/p&gt;

&lt;p&gt;If this helped, you can read more practical dev guides at &lt;strong&gt;&lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;&lt;/strong&gt;. Share it with a developer friend who is still typing &lt;code&gt;dark:&lt;/code&gt; on every div 😄, and tell me in the comments which theme you would add first.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tailwindcss</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What's New in AI Models Right Now? A Simple Guide for Late 2026</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Sat, 07 Nov 2026 10:59:04 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/whats-new-in-ai-models-right-now-a-simple-guide-for-late-2026-1cb2</link>
      <guid>https://dev.to/hamidrazadev/whats-new-in-ai-models-right-now-a-simple-guide-for-late-2026-1cb2</guid>
      <description>&lt;p&gt;You open your favorite AI tool on Monday. By Friday, there's a new model name in your feed, and a "this changes everything" post to go with it. 😅&lt;/p&gt;

&lt;p&gt;Sound familiar? So which of these new AI models actually matter to you? Let's sort it out together, without the hype.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are "New AI Models," Really?
&lt;/h2&gt;

&lt;p&gt;An AI model is the engine inside the tool you use. The chat app, the image generator, and the coding assistant are the car. The model is the engine under the hood.&lt;/p&gt;

&lt;p&gt;Labs keep building better engines, and they do it fast. One tracker counted 23 new models from 15 providers in September 2026, and another confirmed 20 models from 16 providers in October.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's New Right Now
&lt;/h2&gt;

&lt;p&gt;Here's a snapshot as of late October 2026. Names and access change quickly, so check official pages before you build on any of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chat, reasoning, and coding&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI:&lt;/strong&gt; the GPT-6 family, with Astra as the top tier, Sol as the balanced pick, and Luna as the low-cost option.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic:&lt;/strong&gt; Claude Opus 5.5, Sonnet 5.5, and Haiku 5.5 (the newest, released October 7), plus the premium Fable 5.1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google:&lt;/strong&gt; Gemini 3.8 Flash is the broadly available model, while Gemini 4 Argon is rolling out in phases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Open and budget-friendly&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kimi K3 has published weights and a 1M-token context window, and DeepSeek's V4.1 Flash targets low-cost coding and vision work.&lt;/li&gt;
&lt;li&gt;Meta released Muse Wonder and Muse Wonder Full on October 12.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Image and video&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google shipped Nano Banana 2.1 on October 6.&lt;/li&gt;
&lt;li&gt;FLUX 3 is built as one model that handles image, video, and audio.&lt;/li&gt;
&lt;li&gt;Newer video models like Seedance 2.5 and Kling 3.0 are also being compared head to head.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;New models change what's practical. A task that was too slow, too costly, or too error-prone last quarter might be easy now.&lt;/p&gt;

&lt;p&gt;For developers, that can mean cheaper features, better code help, and fewer workarounds. For students and beginners, it means more capable free and low-cost tools to learn with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trends Worth Knowing (With Real Examples)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Models come in sizes.&lt;/strong&gt; Most labs now offer a big model, a balanced one, and a cheap, fast one. Use the cheap one for sorting support emails and save the big one for hard debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Huge context windows.&lt;/strong&gt; The GPT-6 family supports a 1.05M-token context. That's roughly like handing the model a whole stack of documents instead of one page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open weights.&lt;/strong&gt; With models like Kimi K3, developers can inspect and experiment with the model itself, not just call an API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multimodal by default.&lt;/strong&gt; One model can often read text and images and generate media. Think screenshot in, bug explanation out. 🔧&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Quick Comparison: Which Tier Fits?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Good for&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Flagship&lt;/td&gt;
&lt;td&gt;Hardest reasoning, long tasks&lt;/td&gt;
&lt;td&gt;Debugging a tricky multi-file bug&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Balanced&lt;/td&gt;
&lt;td&gt;Daily coding and agents&lt;/td&gt;
&lt;td&gt;Building a feature with tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Small and fast&lt;/td&gt;
&lt;td&gt;High volume, simple jobs&lt;/td&gt;
&lt;td&gt;Tagging or summarizing hundreds of items&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Tips: Do's and Don'ts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Test models on your own tasks. One guide suggests scoring 20 to 50 real tasks on correctness, speed, tool-call reliability, and cost.&lt;/li&gt;
&lt;li&gt;✅ Check access first. Some frontier models are limited to approved users.&lt;/li&gt;
&lt;li&gt;✅ Start with the balanced tier, then move up or down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Switch models because of a headline alone.&lt;/li&gt;
&lt;li&gt;❌ Trust a single benchmark. It can't reproduce your prompts.&lt;/li&gt;
&lt;li&gt;❌ Hardcode a model name without a plan to update it. Names get retired.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chasing every release.&lt;/strong&gt; New isn't always better for your use case. Pick a stable default and review it monthly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using the biggest model for everything.&lt;/strong&gt; It's like driving a truck to buy milk. It works, but it costs more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring access limits.&lt;/strong&gt; A model that's "announced" may not be usable on your account yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixing up the model and the app.&lt;/strong&gt; The same model can behave differently across products.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The big picture is simple. There are more models, in more sizes, with longer context, better image and video tools, and more open options. You don't need to track them all. Pick a solid default, test on your real tasks, and keep learning. 🚀&lt;/p&gt;

&lt;p&gt;If this helped you make sense of the new AI models, read more posts on &lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;, share this with a friend who's lost in the model names, and tell me in the comments which model you're trying next. 😊&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>VS Code 1.144: Cloud Sessions, Copilot Fusion, Image Generation, and More (A Friendly Guide)</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Thu, 29 Oct 2026 19:25:09 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/vs-code-1144-cloud-sessions-copilot-fusion-image-generation-and-more-a-friendly-guide-4d0d</link>
      <guid>https://dev.to/hamidrazadev/vs-code-1144-cloud-sessions-copilot-fusion-image-generation-and-more-a-friendly-guide-4d0d</guid>
      <description>&lt;p&gt;You start an agent task, close your laptop, and the session stops with it. We've all been there. 😅&lt;/p&gt;

&lt;p&gt;VS Code 1.144 (released October 28, 2026) is built around fixing that kind of friction. It makes agent work keep going across environments, helps you pick the right model, and gives you more control over what agents change.&lt;/p&gt;

&lt;p&gt;So what actually changed, and what's worth trying first? Let's walk through it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is VS Code 1.144?
&lt;/h2&gt;

&lt;p&gt;VS Code 1.144 is the latest monthly-style update of Visual Studio Code, and it's mostly about &lt;strong&gt;agents&lt;/strong&gt;. An agent is an AI helper that can work on a task for you: read code, edit files, run tools, and report back.&lt;/p&gt;

&lt;p&gt;Here's a simple way to picture it. Think of an agent as a helpful teammate. Earlier, that teammate sat at your desk and left when you left. Now, that teammate can work somewhere else (like in the cloud) and you can check in from anywhere.&lt;/p&gt;

&lt;p&gt;The release highlights are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Session continuity:&lt;/strong&gt; keep sessions and automations running, even when your computer is off&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copilot Fusion and model comparisons:&lt;/strong&gt; let Copilot choose models, or compare them yourself&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image generation (Preview):&lt;/strong&gt; create and edit images in chat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Computer use (Experimental):&lt;/strong&gt; let agents use desktop apps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Working set (Experimental):&lt;/strong&gt; keep or undo agent file edits&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assisted permissions:&lt;/strong&gt; fewer interruptions, with a risk check&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization marketplace and Copilot connectors (Preview):&lt;/strong&gt; add skills, plugins, and context from services like Slack and Notion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these are marked Preview or Experimental, so expect them to keep changing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Update Matters
&lt;/h2&gt;

&lt;p&gt;Working with agents isn't only about writing code. It's about &lt;strong&gt;where&lt;/strong&gt; the work runs, &lt;strong&gt;which&lt;/strong&gt; model does it, and &lt;strong&gt;how much&lt;/strong&gt; you trust it to do on its own.&lt;/p&gt;

&lt;p&gt;Those three questions come up daily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Can I leave this running and go to lunch?"&lt;/li&gt;
&lt;li&gt;"Which model is best for this task?"&lt;/li&gt;
&lt;li&gt;"Do I really have to click Approve on every tiny action?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VS Code 1.144 gives a practical answer to each one. Fewer interruptions and less guesswork means more time for the actual problem. 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits With Real-Life Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Cloud sessions keep working when your laptop doesn't
&lt;/h3&gt;

&lt;p&gt;Cloud sessions let you run Copilot tasks from VS Code without keeping your development machine online. Your repository and tools run in a managed environment on GitHub's infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; You start a task, then head home. Later you check progress on GitHub.com or in the GitHub Mobile app, and continue in VS Code when you're back.&lt;/p&gt;

&lt;p&gt;One thing to know: cloud sessions use a &lt;strong&gt;separate workspace&lt;/strong&gt;, so local uncommitted changes aren't automatically copied. They also need a paid Copilot plan and follow your organization's policies.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. One place to manage your remote environments
&lt;/h3&gt;

&lt;p&gt;The new &lt;strong&gt;Remote Environments&lt;/strong&gt; dialog brings GitHub Environments, Dev Tunnels, WSL distributions, and SSH hosts together. You can see each remote's status, connect or disconnect, and choose which remotes show up in the pickers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; You have an SSH host and a WSL distro. Instead of hunting through menus, open &lt;strong&gt;Manage Remote Environments&lt;/strong&gt; at the bottom of the Environment picker and handle both.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cloud automations for repetitive work (Preview)
&lt;/h3&gt;

&lt;p&gt;Cloud automations run on GitHub infrastructure, on a schedule or in response to repository events, even when your computer is off. You can create one from the Automations view in the Agents window, or ask an agent to set it up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Trigger an automation when you're assigned an issue with a specific label, such as triaging it automatically. You can limit the allowed tools and add filters for tighter control.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Copilot Fusion picks the models for you
&lt;/h3&gt;

&lt;p&gt;Select &lt;strong&gt;Copilot Fusion&lt;/strong&gt; in the model picker and Copilot chooses the models, reasoning effort, and execution pattern per request. A simple task might use one model. A harder one might have one model draft a solution while others review it.&lt;/p&gt;

&lt;p&gt;You pick an effort level: &lt;strong&gt;Standard&lt;/strong&gt;, &lt;strong&gt;High&lt;/strong&gt;, or &lt;strong&gt;Max&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Renaming a variable doesn't need a heavy setup. A tricky refactor might. Fusion makes that call so you don't have to.&lt;/p&gt;

&lt;p&gt;Good to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're billed for each model Fusion uses, at its standard rate.&lt;/li&gt;
&lt;li&gt;Through November 30, 2026, paid Copilot plans get a 30% discount on Fusion.&lt;/li&gt;
&lt;li&gt;Fusion High and Max are offered on Copilot Pro+, Max, Business, and Enterprise plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Model comparisons: same prompt, different models
&lt;/h3&gt;

&lt;p&gt;Model comparisons run the same prompt across models (and harnesses) so you can review results side by side. They're enabled by default for eligible new sessions in the Agents window. This release expands them, so you can now compare from a folderless chat or from a local or empty repository with no commits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; You're unsure which model writes better tests for your code. Run the same prompt on four and compare. Note that model comparisons aren't supported in Dev Containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Image generation in chat (Preview)
&lt;/h3&gt;

&lt;p&gt;Agents can generate images with GPT Image 2.5 Flare. You can ask for an icon, a chat background, or a website wireframe, or attach an existing image and ask for changes or variations.&lt;/p&gt;

&lt;p&gt;You control it with settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;chat.copilot.imageGeneration.model&lt;/code&gt;: set to &lt;code&gt;off&lt;/code&gt; to disable it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chat.copilot.imageGeneration.watermark&lt;/code&gt;: set to &lt;code&gt;true&lt;/code&gt; to add a visible "Made with AI" watermark&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It uses AI credits in addition to those used by the conversation model.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Assisted permissions: fewer clicks, still safe
&lt;/h3&gt;

&lt;p&gt;Agents can make a lot of tool calls. Approving each one is safe but slow. Giving the agent full freedom can be risky.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assisted permissions&lt;/strong&gt; (now generally available for Copilot sessions) use an LLM-based risk check on each tool call. Low-risk calls are approved automatically. Higher-risk calls, or ones where the risk can't be determined, still ask you.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Working set: keep or undo agent edits (Experimental)
&lt;/h3&gt;

&lt;p&gt;In the Copilot harness, edits made through agent tools land in a working set. You can use inline &lt;strong&gt;Keep&lt;/strong&gt; and &lt;strong&gt;Undo&lt;/strong&gt; controls for single changes, or manage everything from the working set above the chat input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; The agent fixes your bug but also touches a file you didn't expect. Undo that one file and keep the rest. Edits made through terminal commands don't appear in the working set, so keep that in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Computer use for desktop-app tasks (Experimental)
&lt;/h3&gt;

&lt;p&gt;With Computer Use, the agent can see and control apps on your computer. It works in Copilot harness sessions on your own macOS or Windows machine. The agent asks permission to turn it on, or you can run &lt;code&gt;/computer on&lt;/code&gt; (and &lt;code&gt;/computer off&lt;/code&gt; to stop).&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Connectors and a customization marketplace (Preview)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Copilot connectors&lt;/strong&gt; are GitHub-managed MCP servers that connect your agent to services without local server setup. The release notes mention Slack, Notion, and Microsoft Learn as examples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browse&lt;/strong&gt; is the new home page for Customizations, with plugins and skills from marketplaces you or your enterprise configured. For Business and Enterprise, an administrator must enable Editor preview features.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Comparison: Permission Modes
&lt;/h2&gt;

&lt;p&gt;If you're wondering how the permission choices differ, here's a simple view:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Best when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Manual&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You approve every tool call&lt;/td&gt;
&lt;td&gt;You want full control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Assisted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low-risk calls auto-approve; others ask you&lt;/td&gt;
&lt;td&gt;You want fewer interruptions with a safety check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Allow All&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The agent has full autonomy&lt;/td&gt;
&lt;td&gt;You accept the risk of unintended actions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Assisted permissions require Folder isolation and might be restricted by your organization. If your admin disables it, it stays visible but greyed out, with an explanation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Tips and Do's &amp;amp; Don'ts
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Try model comparison on a real task&lt;/strong&gt; before deciding which model you like.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Commit your local changes&lt;/strong&gt; before starting a cloud session, since they aren't copied over automatically.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Use Assisted permissions&lt;/strong&gt; if constant approval prompts slow you down.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Set the image watermark setting&lt;/strong&gt; if you want AI-made images clearly labeled.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Use the Insiders build&lt;/strong&gt; if you want to try upcoming features early.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Don't assume Experimental features are final. Settings and behavior can change.&lt;/li&gt;
&lt;li&gt;❌ Don't forget that Fusion bills for each model it uses.&lt;/li&gt;
&lt;li&gt;❌ Don't install plugins from sources you don't trust. Plugins can run code on your machine.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Expecting cloud sessions to see local uncommitted work.&lt;/strong&gt;&lt;br&gt;
They use a separate workspace. Commit or push first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Looking for a feature that isn't showing up.&lt;/strong&gt;&lt;br&gt;
Many items are Preview or Experimental and behind settings. Examples: &lt;code&gt;chat.editor.workingSet.enabled&lt;/code&gt;, &lt;code&gt;chat.agentHost.computerUse.enabled&lt;/code&gt;, and &lt;code&gt;chat.canvases.enabled&lt;/code&gt;. Also, some features depend on your plan or organization policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Thinking the terminal is covered by the working set.&lt;/strong&gt;&lt;br&gt;
Edits from terminal commands don't appear there. Review those changes another way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Treating model choice as a one-time decision.&lt;/strong&gt;&lt;br&gt;
New models keep arriving. Comparisons and Fusion exist so you can re-check without guessing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Skipping the side notes for extension authors.&lt;/strong&gt;&lt;br&gt;
If you publish extensions, &lt;code&gt;vsce publish --oidc&lt;/code&gt; lets you publish from GitHub Actions without storing a PAT as a repository secret. It needs &lt;code&gt;@vscode/vsce&lt;/code&gt; 4.0.2 or later. Also, global PATs in Azure DevOps are retired on December 1, 2026, so Azure Pipelines users should move to Microsoft Entra ID with a service connection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Small Extras Worth Knowing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent Host Protocol v1.0&lt;/strong&gt; is published. It's an open protocol VS Code uses to talk to agents locally and remotely, so you can build custom UIs or agent platforms around it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copilot Memory&lt;/strong&gt; now works in the Copilot harness. It's enabled by default and respects your settings and organization policies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move chats between sessions&lt;/strong&gt; (Preview) lets you drag nested chats around. Enable &lt;code&gt;chat.agentHost.moveChats.enabled&lt;/code&gt; in Stable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New issue reporter:&lt;/strong&gt; turn it on with &lt;code&gt;issueReporter.wizard.enabled&lt;/code&gt; to capture screenshots and recordings without leaving VS Code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows terminal dialogs&lt;/strong&gt; (like the Azure PowerShell sign-in picker) now open in front of VS Code instead of behind it.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;VS Code 1.144 makes agent work feel less tied to one machine and one model. Cloud sessions and automations keep things moving, Copilot Fusion and model comparisons help you choose well, and Assisted permissions plus the working set keep you in control.&lt;/p&gt;

&lt;p&gt;My suggestion: don't try everything at once. Pick one or two things, like model comparison and Assisted permissions, and see how they fit your workflow. If you're not on the update yet, use &lt;strong&gt;Check for Updates&lt;/strong&gt; in VS Code. 😊&lt;/p&gt;

&lt;p&gt;If this guide helped, you can find more developer posts at &lt;strong&gt;&lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;&lt;/strong&gt;. Share it with a teammate who's still approving every tool call by hand. And tell me in the comments: which VS Code 1.144 feature are you trying first? 👀&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>githubcopilot</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>VS Code 1.143: Copilot Harness Default, Compare Models, and Other Updates Worth Knowing</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Fri, 23 Oct 2026 10:38:31 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/vs-code-1143-copilot-harness-default-compare-models-and-other-updates-worth-knowing-2l3j</link>
      <guid>https://dev.to/hamidrazadev/vs-code-1143-copilot-harness-default-compare-models-and-other-updates-worth-knowing-2l3j</guid>
      <description>&lt;p&gt;You open VS Code after an update and something feels different. A new picker here, a new setting there. You wonder: &lt;em&gt;"Did they move my stuff again?"&lt;/em&gt; 😅&lt;/p&gt;

&lt;p&gt;VS Code 1.143 has a few changes like that. Some are big, some are small, and several are still experimental. This post walks through the highlights in plain English so you know what changed and what to try first.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is VS Code 1.143?
&lt;/h2&gt;

&lt;p&gt;VS Code ships a new version regularly, and 1.143 is the latest release covered here. Think of it like a new season of your favorite show: same main characters, a few new storylines.&lt;/p&gt;

&lt;p&gt;The theme of this release is &lt;strong&gt;AI agents&lt;/strong&gt;. Agents are AI helpers that can work on coding tasks for you, and this release makes them easier to run, compare, review, and clean up after.&lt;/p&gt;

&lt;p&gt;Here are the headline items:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copilot harness by default&lt;/strong&gt; for new sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare models&lt;/strong&gt; (Preview)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reclaim worktree storage&lt;/strong&gt; (Experimental)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-device models&lt;/strong&gt; (Experimental)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-diff file list&lt;/strong&gt; (Experimental)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A quick note on the word "harness." It's the engine that runs your agent session. The Copilot harness is built on the Copilot SDK, a shared foundation meant to keep behavior and improvements consistent across Copilot products.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why VS Code 1.143 Matters
&lt;/h2&gt;

&lt;p&gt;Using AI agents is fun until the questions start:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which model is actually best for this task?&lt;/li&gt;
&lt;li&gt;What did the agent change in my files?&lt;/li&gt;
&lt;li&gt;Why is my disk suddenly full?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This release goes after those questions. It gives you ways to &lt;strong&gt;compare results&lt;/strong&gt;, &lt;strong&gt;review changes&lt;/strong&gt;, and &lt;strong&gt;clean up leftovers&lt;/strong&gt;. The release notes also describe performance work for people who keep very long chats.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits of the Main Features (With Real Examples)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Copilot harness is now the default
&lt;/h3&gt;

&lt;p&gt;New sessions use the Copilot harness. You can keep these sessions running in the background and reach them from both the editor window and the Agents window. They run through the Agent Host.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; You start a task in the editor, then switch to the Agents window to check on it. The same session is there.&lt;/p&gt;

&lt;p&gt;The release notes also mention reduced delays caused by MCP servers that don't finish loading their tools. If you ever waited a long time for a chat response, that fix is aimed at you.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Compare Models (Preview)
&lt;/h3&gt;

&lt;p&gt;You can run the same task with two or more models at the same time. Each attempt gets its own session, and you can mix Copilot, Claude, and Codex harnesses with different reasoning levels.&lt;/p&gt;

&lt;p&gt;You can also pick an optional &lt;strong&gt;Judge model&lt;/strong&gt;. It evaluates the attempts and shows a scorecard with time and token usage. If you like, you can select &lt;strong&gt;Synthesize&lt;/strong&gt; to build on the recommended attempt using ideas from the others. Synthesis only starts when you ask for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; You need a form validation helper. Instead of guessing which model writes the cleanest version, you run several and compare side by side.&lt;/p&gt;

&lt;p&gt;To try it, enable &lt;code&gt;sessions.chat.compareAgents.enabled&lt;/code&gt; in the Agents window, then choose &lt;strong&gt;Compare Models&lt;/strong&gt; in the model picker.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Reclaim worktree storage (Experimental)
&lt;/h3&gt;

&lt;p&gt;Worktrees let agents work on several features without stepping on each other. The catch is that inactive ones pile up and eat disk space.&lt;/p&gt;

&lt;p&gt;Run &lt;strong&gt;Chat: Open Worktree Cleanup&lt;/strong&gt; from the Command Palette to see how much space they use. You can filter by inactivity, review sizes, and pick what to remove. Cleaning up marks sessions as done and deletes their worktrees, and you can restore a session later to recreate its worktree. Active, running, needs-input, and pinned sessions are protected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; It's like cleaning your desk. You keep the papers you're using and clear the ones from three weeks ago.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Easier review of agent changes
&lt;/h3&gt;

&lt;p&gt;Two changes help here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File-level Keep (Experimental).&lt;/strong&gt; Enable &lt;code&gt;chat.editor.workingSet.enabled&lt;/code&gt; and you get a working set above the chat input. Select &lt;strong&gt;Keep&lt;/strong&gt; on a file to mark it as reviewed. The edits stay on disk, and the file comes back if the agent changes it again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More Discard options in the Agents window.&lt;/strong&gt; Discard Changes now works in more changesets, not just Uncommitted Changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Faster large chats
&lt;/h3&gt;

&lt;p&gt;Opening a long Agent Host chat used to freeze the window for a long time. In the release notes' measurements (median of three runs on macOS), one chat with about 1,150 requests went from &lt;strong&gt;35.6 s to 9.0 s&lt;/strong&gt; on a cold open, and the unresponsive time dropped from &lt;strong&gt;28.3 s to 0.6 s&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Smaller but useful upgrades
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Detached background shells:&lt;/strong&gt; You can now see output from things like dev servers and file watchers, and stop them from the shell's details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diagnostics:&lt;/strong&gt; The editor highlight limit went from 500 to 5,000 per file, with a warning in the language status indicator if limits are hit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-diff file list (Experimental):&lt;/strong&gt; Enable &lt;code&gt;multiDiffEditor.experimental.fileList&lt;/code&gt; to get a file list beside the diff view, with A, M, D, and R status letters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copilot CLI setup:&lt;/strong&gt; The VS Code installer on Windows can now install GitHub Copilot CLI, Linux installers add a &lt;code&gt;copilot&lt;/code&gt; executable to your path, and macOS prompts you when you add VS Code to &lt;code&gt;$PATH&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comparison: What "Discard Changes" Does in Each Changeset
&lt;/h2&gt;

&lt;p&gt;The same button behaves differently depending on where you click it. This is worth knowing before you click:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Changeset&lt;/th&gt;
&lt;th&gt;What Discard Changes does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Branch Changes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Restores the file to its version where the branch diverged from its base branch, and deletes files the branch added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Session Changes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reverts the session's edits to the file and keeps changes made outside the session, such as your own edits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Last Turn Changes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reverts only the latest turn's edits and keeps all other changes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you only want to undo the agent's most recent attempt, &lt;strong&gt;Last Turn Changes&lt;/strong&gt; is the narrowest option.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Tips and Do's and Don'ts
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ Try experimental features on a side project first, since they can change.&lt;/li&gt;
&lt;li&gt;✅ Use &lt;strong&gt;Compare Models&lt;/strong&gt; when a task matters and you're unsure which model fits.&lt;/li&gt;
&lt;li&gt;✅ Check the changeset name before discarding anything.&lt;/li&gt;
&lt;li&gt;✅ Run &lt;strong&gt;Chat: Open Worktree Cleanup&lt;/strong&gt; now and then if you use many agent sessions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Don't assume every feature is on by default. Several need a setting. The Session Activity Bar, for example, is off by default in Stable.&lt;/li&gt;
&lt;li&gt;❌ Don't expect on-device models on any laptop. More on that below.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Mixing up Keep and Discard.&lt;/strong&gt; Keep marks changes as reviewed and leaves them on disk. Discard reverts them. Read the label before you click. 👀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Forgetting a feature is experimental or preview.&lt;/strong&gt; If something looks different from the docs, check whether it's a Preview or Experimental feature behind a setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Trying on-device models without the hardware.&lt;/strong&gt; MAI Code 1.1 Flash requires GitHub sign-in and an NVIDIA GPU with &lt;strong&gt;96 GB or more of GPU memory&lt;/strong&gt;. You also need a compatible llama.cpp build, plus &lt;code&gt;chat.copilot.localModel.llamaServerPath&lt;/code&gt; and &lt;code&gt;chat.copilot.localModel.enabled&lt;/code&gt; set. Responses that run on your device are labeled On-device and don't use AI credits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Ignoring cleanup until the disk is full.&lt;/strong&gt; Worktrees add up quietly. A quick review is easier than an emergency one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Skipping the enterprise notes.&lt;/strong&gt; If you work in a company setup, admins can control things like managed defaults, sandbox bypass, and whether the Local harness is allowed. If a toggle is locked, policy is probably the reason.&lt;/p&gt;




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

&lt;p&gt;VS Code 1.143 is a practical release for anyone working with AI agents. The Copilot harness is now the default, Compare Models helps you pick the best result, worktree cleanup keeps your disk tidy, and the new review tools make agent edits easier to manage. Several of these are still Preview or Experimental, so try them with curiosity and keep your expectations realistic. 🚀&lt;/p&gt;

&lt;p&gt;If this helped, share it with a developer friend who's wondering what changed in VS Code 1.143. For more practical dev posts, visit &lt;strong&gt;&lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;&lt;/strong&gt;. And tell me in the comments: which feature are you trying first? 😊&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>ai</category>
      <category>githubcopilot</category>
      <category>github</category>
    </item>
    <item>
      <title>What Is a Serverless Backend? A Simple Explanation, Example, and Starter Server 🚀</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Thu, 22 Oct 2026 18:28:28 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/what-is-a-serverless-backend-a-simple-explanation-example-and-starter-server-3ogo</link>
      <guid>https://dev.to/hamidrazadev/what-is-a-serverless-backend-a-simple-explanation-example-and-starter-server-3ogo</guid>
      <description>&lt;p&gt;You build a small app. It works great on your laptop. Then someone asks, "Cool, where is it hosted?" and suddenly you're reading about servers, ports, uptime, and updates when you just wanted to ship a feature. 😅&lt;/p&gt;

&lt;p&gt;That's the moment many developers first hear about a &lt;strong&gt;serverless backend&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The name sounds like magic, as if the servers vanished. They didn't. So what does serverless actually mean, and how can you build a small one today? Let's find out. 😊&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Serverless Backend?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;serverless backend&lt;/strong&gt; is a backend where you write your code as small functions, and a cloud provider runs them for you only when they're needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Servers still exist.&lt;/strong&gt; You just don't set them up, patch them, or keep them running. The provider handles that.&lt;/p&gt;

&lt;h3&gt;
  
  
  A simple analogy 🍕
&lt;/h3&gt;

&lt;p&gt;Imagine you want pizza.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traditional server:&lt;/strong&gt; You rent a whole kitchen and a chef. They wait around all day, even when nobody orders. You pay for the kitchen either way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless:&lt;/strong&gt; You order from a pizza place. The kitchen starts working when your order arrives, and you pay for that order.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In serverless, your "order" is a request, like someone opening your app or submitting a form. Your function wakes up, does its job, sends the response, and goes back to sleep.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where you'll see this
&lt;/h3&gt;

&lt;p&gt;Several platforms offer this model, including AWS Lambda, Vercel Functions, Netlify Functions, and Cloudflare Workers. The details differ, but the idea is the same: &lt;strong&gt;you write a function, they run it on demand.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You'll also hear the term &lt;strong&gt;FaaS&lt;/strong&gt; (Functions as a Service). It's the part of serverless that deals with running your functions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Serverless Backends Matter
&lt;/h2&gt;

&lt;p&gt;Here's why it's worth learning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Less setup.&lt;/strong&gt; You can go from idea to a working API quickly, without configuring a machine first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less maintenance.&lt;/strong&gt; The provider handles the underlying servers, so you spend more time on your actual product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Good for learning.&lt;/strong&gt; Students and beginners can build real APIs without learning server administration first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Common in modern stacks.&lt;/strong&gt; If you use a framework like Next.js, you may already be writing serverless-style API routes without calling them that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It won't replace every kind of backend. But it's a useful tool to have.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits of Serverless (With Real-Life Examples)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You pay for what you use (on most platforms)&lt;/strong&gt;&lt;br&gt;
Many providers bill based on usage, such as the number of requests and how long your code runs, and often include a free tier. &lt;em&gt;Example:&lt;/em&gt; a small portfolio contact form that gets a few messages a week doesn't need a machine running 24/7. Always check the current pricing of your provider, since it changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No server maintenance&lt;/strong&gt;&lt;br&gt;
You don't manage operating system updates or server patches. &lt;em&gt;Example:&lt;/em&gt; instead of fixing a server at 2 a.m., you push code and move on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scaling is handled for you&lt;/strong&gt;&lt;br&gt;
If more people visit, the platform can run more copies of your function. &lt;em&gt;Example:&lt;/em&gt; a newsletter signup endpoint shouldn't need a rewrite just because a post got shared more than usual. Platforms have limits and settings, so read their docs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast to start&lt;/strong&gt;&lt;br&gt;
A small function is often just one file. &lt;em&gt;Example:&lt;/em&gt; a "send a thank-you email" function can be live the same afternoon you write it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Great for small, focused jobs&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Example:&lt;/em&gt; resizing an uploaded image, validating a form, or receiving a webhook from a payment service.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Serverless vs Traditional Server: A Quick Comparison
&lt;/h2&gt;

&lt;p&gt;Neither is "better" in every case. They fit different situations.&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;Traditional Server&lt;/th&gt;
&lt;th&gt;Serverless Backend&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You configure and manage the machine&lt;/td&gt;
&lt;td&gt;Provider manages the infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Running&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always on&lt;/td&gt;
&lt;td&gt;Runs when a request arrives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Billing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Usually fixed or reserved capacity&lt;/td&gt;
&lt;td&gt;Usually based on usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can keep things in memory&lt;/td&gt;
&lt;td&gt;Don't rely on memory between requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Long tasks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Comfortable&lt;/td&gt;
&lt;td&gt;Often limited by execution time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Steady traffic, long-running work&lt;/td&gt;
&lt;td&gt;Small APIs, bursts of traffic, quick jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Honest nuance:&lt;/strong&gt; serverless functions can have a short delay on the first request after being idle. This is commonly called a &lt;strong&gt;cold start&lt;/strong&gt;. For many apps it's barely noticeable, but it's good to know it exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's Build a Tiny Serverless Backend 🔧
&lt;/h2&gt;

&lt;p&gt;Since this blog should be practical, here's a small starter you can run today.&lt;/p&gt;

&lt;p&gt;We'll use a &lt;strong&gt;Next.js Route Handler&lt;/strong&gt;. On platforms like Vercel, route handlers can run as serverless functions. We'll build two endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /api/hello&lt;/code&gt; returns a greeting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /api/subscribe&lt;/code&gt; validates an email and responds&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Next.js project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm create next-app@latest my-serverless-api
&lt;span class="nb"&gt;cd &lt;/span&gt;my-serverless-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pick TypeScript and the App Router when asked. (You can use &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt; too.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create your first function
&lt;/h3&gt;

&lt;p&gt;Create this file: &lt;code&gt;app/api/hello/route.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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// GET /api/hello?name=Sara&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&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;searchParams&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;friend&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="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;! 👋`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a working backend endpoint. No server setup. No port configuration in your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Add a POST endpoint
&lt;/h3&gt;

&lt;p&gt;Create: &lt;code&gt;app/api/subscribe/route.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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// POST /api/subscribe&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// If the body isn't valid JSON, treat it as empty&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@&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;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please send a valid email.&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// In a real app, save the email to a database or email service here.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ok&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Thanks! We'll write to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the comment inside the function. We're &lt;strong&gt;not&lt;/strong&gt; storing the email in a variable that lives between requests. In serverless, that wouldn't be reliable. Real data belongs in a database. More on that below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Run it locally
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;Then test it:&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;# GET request&lt;/span&gt;
curl &lt;span class="s2"&gt;"http://localhost:3000/api/hello?name=Sara"&lt;/span&gt;

&lt;span class="c"&gt;# POST request&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3000/api/subscribe &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;'{"email":"sara@example.com"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see JSON responses for both. 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Deploy it
&lt;/h3&gt;

&lt;p&gt;One simple way is to push your project to GitHub and import it into &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;. Your route handlers get deployed as serverless functions. You can also use the Vercel CLI if you prefer the terminal.&lt;/p&gt;

&lt;p&gt;Other hosts work too. Just check how each one supports Next.js route handlers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not using Next.js? Here's a plain AWS Lambda version
&lt;/h3&gt;

&lt;p&gt;The idea is the same: a function that receives an event and returns a response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// index.mjs&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryStringParameters&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;friend&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="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On AWS, you'd connect this function to an HTTP endpoint (for example, using API Gateway or a Lambda function URL). Setup steps vary, so follow the current AWS docs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Tips and Do's &amp;amp; Don'ts ✅
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep functions small and focused.&lt;/strong&gt; One function, one job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store data in a database or storage service.&lt;/strong&gt; Don't rely on memory between requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate input.&lt;/strong&gt; Never trust whatever the client sends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use environment variables for secrets.&lt;/strong&gt; API keys should never sit in your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check your provider's limits.&lt;/strong&gt; Timeouts, payload sizes, and memory limits differ between platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log useful information.&lt;/strong&gt; It makes debugging much easier when you can't "look inside" the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't put secrets in your repo.&lt;/strong&gt; Not even "just for testing."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't run very long jobs in a single function&lt;/strong&gt; unless your platform clearly supports it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't assume local behavior equals production behavior.&lt;/strong&gt; Test after deploying.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Thinking "serverless" means "no servers"
&lt;/h3&gt;

&lt;p&gt;Servers exist. You just don't manage them. Knowing this helps you understand limits like timeouts and cold starts.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Saving data in a variable and expecting it to stay
&lt;/h3&gt;

&lt;p&gt;This is a classic. It seems to work on your machine, then data disappears in production. Why? Your function may run in different instances, and instances can start and stop. &lt;strong&gt;Fix:&lt;/strong&gt; use a database.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ignoring cold starts
&lt;/h3&gt;

&lt;p&gt;The first request after a quiet period can be a little slower. &lt;strong&gt;Fix:&lt;/strong&gt; keep functions lightweight, and measure before worrying.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Forgetting about timeouts
&lt;/h3&gt;

&lt;p&gt;Functions usually have a maximum run time. A heavy job that works locally might get cut off. &lt;strong&gt;Fix:&lt;/strong&gt; check your provider's limits and break big jobs into smaller pieces.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Skipping input validation
&lt;/h3&gt;

&lt;p&gt;It's tempting to trust the request body. Don't. &lt;strong&gt;Fix:&lt;/strong&gt; validate everything, like we did with the email check above.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Hardcoding secrets
&lt;/h3&gt;

&lt;p&gt;It happens when we're in a hurry. &lt;strong&gt;Fix:&lt;/strong&gt; use environment variables from day one.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Choosing serverless for everything
&lt;/h3&gt;

&lt;p&gt;It's a great fit for many things, but not all. &lt;strong&gt;Fix:&lt;/strong&gt; pick the tool that fits the job, not the one that's trending.&lt;/p&gt;




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

&lt;p&gt;A &lt;strong&gt;serverless backend&lt;/strong&gt; lets you write small functions and let a cloud provider run them when needed. You skip much of the server management, start quickly, and focus on building features.&lt;/p&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Servers still exist, you just don't manage them.&lt;/li&gt;
&lt;li&gt;Functions run on demand, and billing is often based on usage.&lt;/li&gt;
&lt;li&gt;Don't store important data in memory. Use a database.&lt;/li&gt;
&lt;li&gt;Watch out for cold starts, timeouts, and provider limits.&lt;/li&gt;
&lt;li&gt;It's a great way to build small APIs, forms, and webhooks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You've already seen how little code a working serverless backend takes. Try the starter above, change the message, add a field, and make it yours. 😊&lt;/p&gt;

&lt;p&gt;If this post helped, you can read more developer-friendly articles on &lt;strong&gt;&lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;&lt;/strong&gt;. And if you know someone who's curious about serverless, share it with them. 🚀&lt;/p&gt;

&lt;p&gt;Got questions, or want to share what you built? Drop a comment. I'd love to hear how it goes!&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Stop Comparing Android and iOS — They Were Never Meant to Compete</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Sat, 26 Sep 2026 10:34:59 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/stop-comparing-android-and-ios-they-were-never-meant-to-compete-1inp</link>
      <guid>https://dev.to/hamidrazadev/stop-comparing-android-and-ios-they-were-never-meant-to-compete-1inp</guid>
      <description>&lt;p&gt;You've seen the arguments. Someone tweets that iPhone is overpriced, and within minutes the replies are on fire. Android fans say it gives you freedom. iOS fans say it just works. Round and round we go.&lt;/p&gt;

&lt;p&gt;Here's the thing: &lt;strong&gt;this debate has been running for over a decade, and nobody has won.&lt;/strong&gt; That's not an accident.&lt;/p&gt;

&lt;p&gt;Android and iOS were not built to beat each other. They were built for completely different goals, different people, and different visions of what a smartphone should be. So every time we compare them like they're competing for the same crown, we miss the whole point.&lt;/p&gt;

&lt;p&gt;Have you ever compared a hammer to a screwdriver? Both are tools. Both are useful. But they were never meant to do the same job. 🔧&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does "Comparing Android and iOS" Actually Mean?
&lt;/h2&gt;

&lt;p&gt;When most people compare Android and iOS, they usually mean one of two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Which is better for everyday use?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Which should I pick?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both are fair questions. But they're personal questions, not universal ones.&lt;/p&gt;

&lt;p&gt;Android is an open-source mobile operating system developed by Google. It runs on devices made by Samsung, Google, OnePlus, Xiaomi, and hundreds of other manufacturers. You can customize almost everything.&lt;/p&gt;

&lt;p&gt;iOS is Apple's mobile operating system. It runs only on iPhones and iPads. Apple controls the hardware and software together, which gives it a unique level of polish and consistency.&lt;/p&gt;

&lt;p&gt;They are two completely different philosophies wrapped in the shape of a phone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Topic Actually Matters
&lt;/h2&gt;

&lt;p&gt;If you're a developer, this debate affects your decisions every day.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which platform should you build for first?&lt;/li&gt;
&lt;li&gt;Should you go native, cross-platform, or web-first?&lt;/li&gt;
&lt;li&gt;How do you test your app on both ecosystems?&lt;/li&gt;
&lt;li&gt;Which users are you actually targeting?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if you're just someone buying a phone, the comparison still matters — but in a very different way. Choosing the wrong platform for &lt;em&gt;your life&lt;/em&gt; can cause real friction.&lt;/p&gt;

&lt;p&gt;The problem isn't that people compare the two. The problem is that most comparisons assume one must be better than the other. &lt;strong&gt;That assumption is wrong, and it leads to bad decisions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Understanding why they're different — not which is better — is what actually helps you make smart choices.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Android and iOS Are Not the Same Kind of Thing
&lt;/h2&gt;

&lt;p&gt;Here's an analogy that might help.&lt;/p&gt;

&lt;p&gt;Imagine two restaurants. One is a five-star hotel restaurant. The menu is fixed, the portions are perfect, the service is flawless, and everything feels like it was designed together. You cannot ask for substitutions. You trust the chef.&lt;/p&gt;

&lt;p&gt;The other is a bustling city market. There are dozens of stalls. You can mix and match. You can find rare flavors from around the world. Nothing is perfectly coordinated, but the variety and freedom are unmatched.&lt;/p&gt;

&lt;p&gt;Which restaurant is better? That depends entirely on what you want tonight.&lt;/p&gt;

&lt;p&gt;iOS is the hotel restaurant. Android is the city market.&lt;/p&gt;

&lt;p&gt;Neither is wrong. They simply offer different experiences for different people.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Reasons Why Comparing Them Is Misleading
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ 1. They Serve Different User Bases
&lt;/h3&gt;

&lt;p&gt;iOS users tend to value simplicity, privacy, seamless integration across Apple devices, and a consistent experience. Many are professionals, creatives, or people who want tech that "just works."&lt;/p&gt;

&lt;p&gt;Android users often value choice, flexibility, price range, and the ability to customize their experience. Many are power users, developers, or people in markets where mid-range phones dominate.&lt;/p&gt;

&lt;p&gt;When you declare one "better," you are really saying "better for people like me." That's fine. But it's not a universal truth.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ 2. Android Is Not One Thing
&lt;/h3&gt;

&lt;p&gt;This is one of the most overlooked points in the debate. Android runs on thousands of devices across every price point. Saying "Android is better than iOS" is like saying "cars are better than iPhones." Which car? A budget hatchback or a luxury SUV?&lt;/p&gt;

&lt;p&gt;A Samsung Galaxy S series is a very different experience from a budget Xiaomi phone. Both run Android. Comparing either to an iPhone without specifying the model makes the whole comparison unreliable.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ 3. iOS Is a Closed System by Design, Not Mistake
&lt;/h3&gt;

&lt;p&gt;Apple's control over its ecosystem is a deliberate choice. It allows them to optimize performance, guarantee security updates, and create smooth integration between iPhone, Mac, iPad, Apple Watch, and AirPods.&lt;/p&gt;

&lt;p&gt;That closed nature frustrates some users. But for many others, especially those already in the Apple ecosystem, it is exactly the feature — not the flaw.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ 4. The "Better" Answer Depends on Your Life
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Are your friends and family on iMessage? iOS might feel smoother.&lt;/li&gt;
&lt;li&gt;Do you need a phone under $200? Android gives you more options.&lt;/li&gt;
&lt;li&gt;Are you a developer building apps? You might need both.&lt;/li&gt;
&lt;li&gt;Do you live in a Google Workspace office? Android might feel more natural.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Context drives the answer. Stripping context out of the comparison makes it meaningless.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ 5. Each Keeps the Other Better
&lt;/h3&gt;

&lt;p&gt;This is the quiet truth nobody says enough. The existence of iOS makes Android better. The existence of Android makes iOS better. Competition pushes both platforms forward.&lt;/p&gt;

&lt;p&gt;When Android introduced widgets, Apple eventually added them too. When Apple pioneered Face ID, Android followed. When Google brought real-time translation, Apple improved Siri. They are watching each other — and both of us benefit.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Look at What Each Does Well
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Customization&lt;/td&gt;
&lt;td&gt;🏆 Highly flexible&lt;/td&gt;
&lt;td&gt;Limited but clean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware Choice&lt;/td&gt;
&lt;td&gt;🏆 Hundreds of options&lt;/td&gt;
&lt;td&gt;Only Apple devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy Controls&lt;/td&gt;
&lt;td&gt;Strong (improving)&lt;/td&gt;
&lt;td&gt;🏆 Industry-leading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App Ecosystem&lt;/td&gt;
&lt;td&gt;Massive&lt;/td&gt;
&lt;td&gt;🏆 Higher app revenue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Software Updates&lt;/td&gt;
&lt;td&gt;Fragmented&lt;/td&gt;
&lt;td&gt;🏆 Fast and consistent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price Range&lt;/td&gt;
&lt;td&gt;🏆 Budget to premium&lt;/td&gt;
&lt;td&gt;Premium only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer Experience&lt;/td&gt;
&lt;td&gt;Strong tools&lt;/td&gt;
&lt;td&gt;🏆 Great for SwiftUI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-device Sync&lt;/td&gt;
&lt;td&gt;Good with Google&lt;/td&gt;
&lt;td&gt;🏆 Seamless with Apple&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The takeaway:&lt;/strong&gt; Neither column dominates. Each wins where its philosophy shines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Tips for Developers and Users
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Developers 💡
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build for both from day one.&lt;/strong&gt; Use React Native, Flutter, or a web-first strategy if your budget allows. Ignoring one platform means ignoring half your potential users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't assume behavior.&lt;/strong&gt; iOS and Android handle navigation, permissions, notifications, and even font rendering differently. Test on real devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respect each platform's design language.&lt;/strong&gt; iOS users expect the feel of UIKit/SwiftUI conventions. Android users expect Material Design patterns. Forcing one on the other causes friction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize based on your market.&lt;/strong&gt; In South Asia and Southeast Asia, Android dominates. In North America and Japan, iOS has a strong share. Data should drive your decision.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Everyday Users 💡
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Think about your ecosystem.&lt;/strong&gt; If you own a MacBook, Apple Watch, or AirPods, iOS will feel dramatically smoother. If you use Google Docs, Drive, and Gmail heavily, Android might feel more natural.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try before you decide.&lt;/strong&gt; If you have a friend with the other platform, spend an hour using it. Your preference might surprise you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't switch just to win an argument.&lt;/strong&gt; Switch if your current phone genuinely isn't meeting your needs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes People Make in This Debate
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Mistake 1: Generalizing Android as One Platform
&lt;/h3&gt;

&lt;p&gt;Many people say "Android crashes more" or "Android feels slow." But they're usually talking about a specific budget phone from three years ago. A Pixel 9 or Galaxy S25 is a completely different experience. Be specific.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Mistake 2: Assuming iOS Is Just About Status
&lt;/h3&gt;

&lt;p&gt;Yes, iPhones are expensive. But dismissing iOS users as people who "just want to look rich" ignores real technical reasons many developers, videographers, and professionals choose Apple — like Final Cut Pro integration, Apple Silicon performance, or consistent security updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Mistake 3: Picking a Side and Ignoring the Trade-offs
&lt;/h3&gt;

&lt;p&gt;Every platform has trade-offs. iOS restricts sideloading apps. Android is fragmented across updates. Pretending your preferred platform has no downsides makes you less informed, not more confident.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Mistake 4: Using Old Information
&lt;/h3&gt;

&lt;p&gt;The mobile landscape changes every year. Android's privacy controls have improved significantly. iOS has opened up more customization than ever before. Don't make decisions based on a 2016 Reddit thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Mistake 5: Making It Personal
&lt;/h3&gt;

&lt;p&gt;You can love your phone and still acknowledge the other one does some things well. It's not loyalty. It's just honesty. 😊&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Use the Right Tool, Not the Popular Opinion
&lt;/h2&gt;

&lt;p&gt;Android and iOS are both remarkable pieces of technology. They've changed how billions of people communicate, work, learn, and create. Neither is inferior. Neither is perfect.&lt;/p&gt;

&lt;p&gt;The real question was never "which is better?" The real question is &lt;strong&gt;"which is better for you, right now, given your needs?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a developer, understanding both platforms makes you more employable, more empathetic to your users, and more capable of building things people actually love to use.&lt;/p&gt;

&lt;p&gt;As a regular user, understanding both platforms helps you make a smarter purchase — one based on your actual life, not the loudest voice in the comment section.&lt;/p&gt;

&lt;p&gt;So next time someone tries to start the Android vs iOS argument, you can smile and say: "They're different tools. I know which one works for me."&lt;/p&gt;

&lt;p&gt;That's a more useful answer than anything a 200-comment thread ever produced. 🚀&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want more practical developer content like this?&lt;/strong&gt;&lt;br&gt;
Head over to &lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt; for articles, tools, and insights built for developers who want to keep learning and building smarter.&lt;/p&gt;

&lt;p&gt;If this post helped you see things differently, share it — you might save someone from a very long and very pointless argument. 😄&lt;/p&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>mobile</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Ollama vs LM Studio vs llama.cpp: Which One Should You Actually Use to Run Local LLMs? 🚀</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Fri, 18 Sep 2026 07:42:24 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/ollama-vs-lm-studio-vs-llamacpp-which-one-should-you-actually-use-to-run-local-llms-1e13</link>
      <guid>https://dev.to/hamidrazadev/ollama-vs-lm-studio-vs-llamacpp-which-one-should-you-actually-use-to-run-local-llms-1e13</guid>
      <description>&lt;p&gt;You finally decided to run an AI model on your own machine. No API keys, no per-token billing, no "you've hit your limit" popup at 2 AM.&lt;/p&gt;

&lt;p&gt;Then you open Google and get hit with three names at once: &lt;strong&gt;Ollama&lt;/strong&gt;, &lt;strong&gt;LM Studio&lt;/strong&gt;, and &lt;strong&gt;llama.cpp&lt;/strong&gt;. Every tutorial swears by a different one. Every Reddit thread contradicts the last.&lt;/p&gt;

&lt;p&gt;So you do what we all do. You install all three, burn 40 GB of disk space, and still aren't sure which one you're supposed to keep. 😅&lt;/p&gt;

&lt;p&gt;Here's the part nobody tells you upfront: these three tools are not really competing the way it looks. They sit at different layers of the same stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So the real question isn't "which one is best?" — it's "which one matches the way you work?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's clear it up, simply.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, What Are We Even Comparing?
&lt;/h2&gt;

&lt;p&gt;Imagine you want to drive somewhere.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;llama.cpp&lt;/strong&gt; is the &lt;strong&gt;engine&lt;/strong&gt;. Raw, powerful, and you're expected to know where the bolts go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; is the &lt;strong&gt;car with an automatic gearbox&lt;/strong&gt;. Turn the key, drive, done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LM Studio&lt;/strong&gt; is the &lt;strong&gt;car with a big touchscreen dashboard&lt;/strong&gt;. Same driving, but you can see and tap everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three run the same kind of local language models. The difference is how much of the machinery you touch.&lt;/p&gt;

&lt;p&gt;Let's meet them one by one.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔧 llama.cpp — The Engine Underneath
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;llama.cpp&lt;/strong&gt; is an open-source project (started by Georgi Gerganov) that runs large language models efficiently in C/C++. It's the reason running a decent model on a normal laptop became realistic at all.&lt;/p&gt;

&lt;p&gt;It introduced and popularised the &lt;strong&gt;GGUF&lt;/strong&gt; model format — a single file containing the model weights plus the metadata needed to load it.&lt;/p&gt;

&lt;p&gt;It ships with command-line tools, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;llama-cli&lt;/code&gt; for chatting in the terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;llama-server&lt;/code&gt; for exposing a local HTTP API&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;llama-quantize&lt;/code&gt; for shrinking models to smaller formats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It supports CPU-only machines and can accelerate on GPUs through backends like Metal (Apple), CUDA (NVIDIA), and Vulkan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The catch:&lt;/strong&gt; you either build it yourself or grab a prebuilt release, and you download model files manually. Flags matter. Paths matter. It's not hostile, but it does assume you're comfortable in a terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who it's for:&lt;/strong&gt; people who want control, are building something custom, or genuinely want to understand what's happening under the hood.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚡ Ollama — The "Just Run It" Tool
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Ollama&lt;/strong&gt; wraps local model running into something that feels like Docker for LLMs.&lt;/p&gt;

&lt;p&gt;You install it, then:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That's it. It downloads the model, loads it, and drops you into a chat prompt.&lt;/p&gt;

&lt;p&gt;It also runs a &lt;strong&gt;local HTTP server&lt;/strong&gt; (by default on port &lt;code&gt;11434&lt;/code&gt;) with an &lt;strong&gt;OpenAI-compatible endpoint&lt;/strong&gt;, which is the part developers actually fall in love with. You can point existing code at your own machine by changing a base URL:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:11434/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ollama&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# required by the client, not actually checked
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explain recursion to a 10-year-old.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&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="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ollama also supports a &lt;strong&gt;Modelfile&lt;/strong&gt; — a small config file where you set a system prompt and parameters, then save it as your own named model. Think "Dockerfile, but for model behaviour."&lt;/p&gt;

&lt;p&gt;It's available on macOS, Linux, and Windows, and there's a desktop app alongside the CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worth knowing:&lt;/strong&gt; Ollama has historically built on llama.cpp for inference. So when you use Ollama, you're often benefiting from llama.cpp's work with a much friendlier wrapper on top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who it's for:&lt;/strong&gt; developers who want local models inside their apps and scripts, with minimum setup friction.&lt;/p&gt;




&lt;h3&gt;
  
  
  👀 LM Studio — The Desktop App With a Real UI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LM Studio&lt;/strong&gt; is a desktop application (macOS, Windows, Linux) built around a graphical interface.&lt;/p&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;model browser&lt;/strong&gt; that searches and downloads GGUF models from Hugging Face&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;chat window&lt;/strong&gt; with settings you can see and adjust&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;local server mode&lt;/strong&gt; that exposes an OpenAI-compatible API, same idea as Ollama&lt;/li&gt;
&lt;li&gt;On Apple Silicon, support for &lt;strong&gt;MLX&lt;/strong&gt; models in addition to GGUF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real advantage is visibility. Context length, temperature, GPU offload — they're sliders and fields, not flags you have to remember. When a model fails to load, you can usually &lt;em&gt;see&lt;/em&gt; why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-off:&lt;/strong&gt; it's a GUI-first app, so it's a less natural fit for a headless server. And unlike llama.cpp, the app itself isn't an open-source project you can freely fork, so check the current licence if you're deploying it at work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who it's for:&lt;/strong&gt; beginners, students, designers, prompt engineers, and anyone who wants to test models quickly without living in the terminal.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters More Than It Used To
&lt;/h2&gt;

&lt;p&gt;Running models locally isn't just a hobbyist flex. It solves real problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Your data stays on your machine.&lt;/strong&gt;&lt;br&gt;
Debugging a bug in code covered by an NDA? A local model means that code never leaves your laptop. No policy review needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. No usage bill while you experiment.&lt;/strong&gt;&lt;br&gt;
Testing 300 prompt variations against a paid API gets expensive fast. Locally, the only cost is your electricity and your patience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. It works offline.&lt;/strong&gt;&lt;br&gt;
Flights, trains, bad hotel Wi-Fi, a conference venue with 400 people on one router. Your model doesn't care.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. You learn how the thing actually works.&lt;/strong&gt;&lt;br&gt;
Once you've watched a model fail to load because your context window was too big for your VRAM, you understand LLM memory in a way no blog post can teach you. (Including this one. 😄)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. It's a genuinely useful skill.&lt;/strong&gt;&lt;br&gt;
"Set up a private local LLM workflow for the team" is a real task at real companies now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Comparison Table
&lt;/h2&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;&lt;strong&gt;llama.cpp&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Ollama&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;LM Studio&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interface&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Command line&lt;/td&gt;
&lt;td&gt;Command line + desktop app&lt;/td&gt;
&lt;td&gt;Graphical desktop app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup effort&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Highest&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Lowest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model downloads&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual (you fetch GGUF files)&lt;/td&gt;
&lt;td&gt;Built-in (&lt;code&gt;ollama pull&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Built-in browser UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local API server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes (&lt;code&gt;llama-server&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Yes, OpenAI-compatible&lt;/td&gt;
&lt;td&gt;Yes, OpenAI-compatible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Control over settings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Maximum&lt;/td&gt;
&lt;td&gt;Good (Modelfile + params)&lt;/td&gt;
&lt;td&gt;Good, and visible in the UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Open source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;App is not open source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom builds, deep control&lt;/td&gt;
&lt;td&gt;App development, automation&lt;/td&gt;
&lt;td&gt;Learning, testing, quick chats&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Short version:&lt;/strong&gt;&lt;br&gt;
Learning and exploring → &lt;strong&gt;LM Studio&lt;/strong&gt;.&lt;br&gt;
Building apps and scripts → &lt;strong&gt;Ollama&lt;/strong&gt;.&lt;br&gt;
Custom control, embedding, or squeezing out performance → &lt;strong&gt;llama.cpp&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And honestly? Many people use two. LM Studio to browse and test models, Ollama to serve the one they picked. That's not indecision — that's using the right tool for each job. ✅&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Tips (Learned the Slightly Painful Way)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Start with a small model.&lt;/strong&gt;&lt;br&gt;
Begin with something in the 3B–8B range. If it works, go bigger. Starting with a 70B model on a 16 GB laptop is how you end up thinking "local AI is broken."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Understand quantization before you download.&lt;/strong&gt;&lt;br&gt;
Those &lt;code&gt;Q4_K_M&lt;/code&gt; and &lt;code&gt;Q8_0&lt;/code&gt; labels are compression levels. Lower numbers = smaller file, less memory, some quality loss. &lt;code&gt;Q4_K_M&lt;/code&gt; is a popular balanced starting point. &lt;code&gt;Q8_0&lt;/code&gt; is closer to the original but much heavier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Check your RAM/VRAM against the file size.&lt;/strong&gt;&lt;br&gt;
Rough rule: the model file needs to fit in memory, plus extra headroom for the context. A ~4.5 GB file on a machine with 8 GB total RAM will be tight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Lower your context length if loading fails.&lt;/strong&gt;&lt;br&gt;
Context isn't free. A large context window eats memory before you've typed a single word.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Use the OpenAI-compatible endpoint.&lt;/strong&gt;&lt;br&gt;
Both Ollama and LM Studio expose one. That means you can prototype locally and switch to a hosted API later by changing one base URL. Your code barely changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ Don't judge a model from one bad reply.&lt;/strong&gt;&lt;br&gt;
Try a different prompt, a different quantization, or a different model. First impressions of small models are often unfair.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❌ Don't leave a 30 GB model on your SSD "just in case."&lt;/strong&gt;&lt;br&gt;
You know you won't use it. Your disk knows too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes People Make
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Expecting frontier-model quality from a 7B model on a laptop.&lt;/strong&gt;&lt;br&gt;
Small local models are genuinely useful for summarising, drafting, classifying, and answering routine questions. They will not match the biggest hosted models on hard reasoning. Knowing that upfront saves a lot of disappointment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Thinking these three tools are rivals.&lt;/strong&gt;&lt;br&gt;
They overlap, but they're layered. Ollama being easier doesn't make llama.cpp obsolete — Ollama has leaned on llama.cpp's engine work. Picking one doesn't mean the others were wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Forgetting the local server is already running.&lt;/strong&gt;&lt;br&gt;
"Port 11434 already in use" usually means Ollama is doing exactly what you asked it to, in the background, from yesterday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Ignoring the model's licence.&lt;/strong&gt;&lt;br&gt;
"Open weights" doesn't automatically mean "free for commercial use." Different models ship with different terms. Check before you build a product on one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Downloading five models before testing one.&lt;/strong&gt;&lt;br&gt;
Classic developer behaviour. Test one properly, then decide. Your bandwidth will thank you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Blaming the tool for a hardware limit.&lt;/strong&gt;&lt;br&gt;
If a model is slow, it's usually memory or GPU offload, not the app. Switching from Ollama to LM Studio won't add VRAM. 💡&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Here's the honest summary of &lt;strong&gt;Ollama vs LM Studio vs llama.cpp&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;llama.cpp&lt;/strong&gt; gives you the most control and powers a lot of what the others do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; gives you the smoothest path from "installed" to "in my app."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LM Studio&lt;/strong&gt; gives you the friendliest way to see, test, and understand models.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of them is the "wrong" answer. They're three different doors into the same room.&lt;/p&gt;

&lt;p&gt;If you're totally new, install &lt;strong&gt;LM Studio&lt;/strong&gt; tonight, download one small model, and just chat with it. That single step teaches you more than a week of reading comparisons.&lt;/p&gt;

&lt;p&gt;If you're a developer with a project in mind, install &lt;strong&gt;Ollama&lt;/strong&gt; and point your existing OpenAI client at &lt;code&gt;localhost&lt;/code&gt;. It takes about ten minutes and it feels a little bit like magic. ⚡&lt;/p&gt;

&lt;p&gt;And if you love knowing exactly how things work, clone &lt;strong&gt;llama.cpp&lt;/strong&gt; and go exploring. It's worth it.&lt;/p&gt;

&lt;p&gt;Running AI on your own machine used to be a research-lab thing. Now it's an afternoon. That's a genuinely good time to be a developer. 😊&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;If this helped, pass it along.&lt;/strong&gt; Share it with the teammate who's been meaning to try local models, or drop it in your group chat.&lt;/p&gt;

&lt;p&gt;📚 More practical developer guides at &lt;strong&gt;&lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Now tell me in the comments:&lt;/strong&gt; which one did you end up keeping — Ollama, LM Studio, or llama.cpp? And what model are you running? I'm always curious what's working on other people's machines.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>VS Code 1.137 Is Here: Automations, Voice Mode, and the Features That'll Change How You Code</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Sat, 12 Sep 2026 21:29:02 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/vs-code-1137-is-here-automations-voice-mode-and-the-features-thatll-change-how-you-code-lgg</link>
      <guid>https://dev.to/hamidrazadev/vs-code-1137-is-here-automations-voice-mode-and-the-features-thatll-change-how-you-code-lgg</guid>
      <description>&lt;p&gt;VS Code just dropped another release, and this one feels different. 🚀&lt;/p&gt;

&lt;p&gt;Not in a "they changed a color somewhere" kind of way. More like "wait, the editor just started doing things I used to do manually, and I can now &lt;em&gt;talk&lt;/em&gt; to it." VS Code 1.137, released on September 9, 2026, is packed with features that push the editor closer to a real AI-powered coding partner.&lt;/p&gt;

&lt;p&gt;If you've ever thought, "I wish my editor could just handle this on its own while I grab a coffee" — this release was made for you.&lt;/p&gt;

&lt;p&gt;Let's break down everything that's new, what it actually means for your workflow, and how to get the most out of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is VS Code 1.137?
&lt;/h2&gt;

&lt;p&gt;VS Code 1.137 is the latest stable update to Visual Studio Code, Microsoft's widely used free code editor. This version focuses heavily on &lt;strong&gt;agent-powered automation&lt;/strong&gt;, smarter chat workflows, voice interaction, and better GitHub integration — all without ever leaving your editor.&lt;/p&gt;

&lt;p&gt;Think of it as VS Code leveling up from "smart assistant" to "proactive team member." It's still your editor. It just does more now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Release Matters
&lt;/h2&gt;

&lt;p&gt;Here's the thing: most developers spend a big chunk of their day on repetitive work. Triaging issues. Catching up on recent changes. Reviewing pull requests. Switching between tools — editor, browser, GitHub, back to editor.&lt;/p&gt;

&lt;p&gt;VS Code 1.137 tackles all of that head-on. You can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schedule agent tasks to run on a timer, like a cron job but for AI&lt;/li&gt;
&lt;li&gt;Talk to the agent with your voice and interrupt it while it's working&lt;/li&gt;
&lt;li&gt;Review GitHub issues and pull requests right inside the editor&lt;/li&gt;
&lt;li&gt;Continue a quick chat even after deciding it needs a full workspace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just a list of shiny features. These are actual developer pain points getting solved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features — What's New and Why It's Useful
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡ Automations (Preview): Let the Agent Handle the Routine Stuff
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Setting:&lt;/strong&gt; &lt;code&gt;chat.automations.enabled&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You know those Monday morning tasks that are the same every single week? Checking what changed over the weekend, scanning for new bugs, triaging open issues? You can now schedule a Copilot agent task to handle those automatically — hourly, daily, or weekly.&lt;/p&gt;

&lt;p&gt;You pick a template (catching up on changes, triaging issues, finding bugs) or write your own prompt. Set the schedule. Done.&lt;/p&gt;

&lt;p&gt;This is genuinely one of those features where the first time it runs and saves you 20 minutes, you'll wonder how you worked without it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to try it:&lt;/strong&gt; Enable &lt;code&gt;chat.automations.enabled&lt;/code&gt;, open the Agents window, and select &lt;strong&gt;Automations&lt;/strong&gt; in the sidebar.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Automations is in Preview and rolling out gradually.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🎙️ Voice Mode (Experimental): Talk to Your Agent Like a Human
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Setting:&lt;/strong&gt; &lt;code&gt;agents.voice.enabled&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is the feature people will demo at meetups. Voice Mode lets you have a real spoken conversation with the Copilot agent while it works on your code.&lt;/p&gt;

&lt;p&gt;And the useful part? You can &lt;strong&gt;interrupt it&lt;/strong&gt;. While the agent is speaking or working, you can jump in with a new instruction or correction — just like you would with a teammate. No waiting for it to finish before you can redirect it.&lt;/p&gt;

&lt;p&gt;You can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show a live transcript in the chat input (&lt;code&gt;agents.voice.showTranscript&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Choose which voice reads responses aloud (&lt;code&gt;agents.voice.voice&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Pick your input microphone from the Command Palette&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's aware of your active session too — so you can ask things like "which model are we using?" or "what files are attached?" and it'll answer correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to try it:&lt;/strong&gt; Enable &lt;code&gt;agents.voice.enabled&lt;/code&gt;, then select the Voice Mode button in the chat input.&lt;/p&gt;




&lt;h3&gt;
  
  
  🐙 GitHub Issues and Pull Requests, Right in the Agents Window (Experimental)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Setting:&lt;/strong&gt; &lt;code&gt;extensions.experimental.enableAgentsWindowCapability&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This one is a workflow changer for teams using GitHub.&lt;/p&gt;

&lt;p&gt;Normally, when a chat conversation references a GitHub issue or PR, you'd click the link, open it in the browser, read through it, come back. VS Code 1.137 removes that detour. Select a &lt;code&gt;github.com&lt;/code&gt; issue or pull request link and its details open &lt;strong&gt;directly in the Agents window&lt;/strong&gt; — even if the repository isn't open locally.&lt;/p&gt;

&lt;p&gt;You can also add GitHub issues or pull requests as context using the &lt;strong&gt;Add Context...&lt;/strong&gt; menu in any chat input. The description, comments, or PR changes become available to the agent without you copy-pasting anything.&lt;/p&gt;

&lt;p&gt;Or paste a GitHub URL directly into the chat — VS Code automatically adds it as a context attachment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To enable:&lt;/strong&gt; Install the GitHub Pull Requests extension and enable &lt;code&gt;extensions.experimental.enableAgentsWindowCapability&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  💬 Continue Quick Chats in a Workspace
&lt;/h3&gt;

&lt;p&gt;This one's subtle but genuinely useful.&lt;/p&gt;

&lt;p&gt;You start a quick chat to explore an idea — maybe you're not sure if it's project-specific yet. The conversation develops, and it turns out you do need access to project files. &lt;/p&gt;

&lt;p&gt;Before, you'd have to start over in a workspace session and lose your chat history. Now, you just ask the Copilot agent to attach a local folder. After you confirm, the chat converts into a workspace session — keeping its &lt;strong&gt;title, conversation history, and current request&lt;/strong&gt;. The agent picks up right where it left off, now with access to your files.&lt;/p&gt;




&lt;h3&gt;
  
  
  🤖 Agent Host and Parallel Agent Workflows
&lt;/h3&gt;

&lt;p&gt;VS Code 1.137 introduces a few important agent infrastructure improvements worth knowing about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent-queued messages&lt;/strong&gt; let you keep agents working in parallel. If an agent tries to contact a busy chat, VS Code queues the message and processes it in order once the active turn finishes. No interruptions, no lost messages.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;agent host&lt;/strong&gt; lets you connect to the same agent session from multiple VS Code windows. It runs agent harnesses in a dedicated process and aligns behavior with the Copilot CLI and the standalone GitHub Copilot app.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔀 Smart Diff Editor and Binary Files in Diffs
&lt;/h3&gt;

&lt;p&gt;Small but polished improvements to the diff editor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can now choose Inline, Side by Side, or Automatic layout consistently across regular diffs, multi-file diffs, and the Agents window Changes editor.&lt;/li&gt;
&lt;li&gt;Binary files (like images) now &lt;strong&gt;stay visible&lt;/strong&gt; in multi-file diffs instead of disappearing. You'll see a "Binary file changed" placeholder, and you can select &lt;strong&gt;Open Diff&lt;/strong&gt; to review the file properly.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔗 GitHub Rich Links in the Markdown Editor (Experimental)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Settings:&lt;/strong&gt; &lt;code&gt;markdown.experimental.richLinks.enabled&lt;/code&gt;, &lt;code&gt;chat.experimental.richLinks.enabled&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Paste a GitHub issue or PR link in your Markdown editor and it shows the &lt;strong&gt;current title and status&lt;/strong&gt; inline — including CI updates. No more opening the browser just to check if an issue is still open or a PR was merged.&lt;/p&gt;

&lt;p&gt;Set &lt;code&gt;chat.experimental.richLinks.enabled&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; to get the same behavior in chat.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before vs. After: How 1.137 Changes Your Daily Workflow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Before 1.137&lt;/th&gt;
&lt;th&gt;After 1.137&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Weekly issue triage&lt;/td&gt;
&lt;td&gt;Manual, every time&lt;/td&gt;
&lt;td&gt;Scheduled automation handles it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redirect an agent mid-task&lt;/td&gt;
&lt;td&gt;Wait for it to finish&lt;/td&gt;
&lt;td&gt;Interrupt with Voice Mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review a PR in a chat context&lt;/td&gt;
&lt;td&gt;Open browser, copy info, paste back&lt;/td&gt;
&lt;td&gt;Add as context or click the link in Agents window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quick chat → workspace&lt;/td&gt;
&lt;td&gt;Restart conversation&lt;/td&gt;
&lt;td&gt;Continue same chat, history intact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary file in multi-file diff&lt;/td&gt;
&lt;td&gt;Invisible — just missing&lt;/td&gt;
&lt;td&gt;Placeholder shown, Open Diff available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub link in Markdown&lt;/td&gt;
&lt;td&gt;Just a URL&lt;/td&gt;
&lt;td&gt;Live title and status inline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Practical Tips for Getting the Most Out of VS Code 1.137
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Do's&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enable Automations for recurring tasks first.&lt;/strong&gt; Start with one of the built-in templates. See what it does automatically before writing your own prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try Voice Mode with a clear workspace.&lt;/strong&gt; It works best when you have a session active and files attached. Give it a focused task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install the GitHub Pull Requests extension&lt;/strong&gt; before trying the Agents window GitHub integration. It's required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Add Context from the chat menu&lt;/strong&gt; when discussing GitHub issues. It's cleaner than copy-pasting descriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update to 1.137 immediately&lt;/strong&gt; using Check for Updates, or download the Insiders build if you want the latest features even earlier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Don'ts&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't expect Voice Mode to replace the keyboard entirely — it's a conversation layer, not a full replacement.&lt;/li&gt;
&lt;li&gt;Don't skip reading the automation output. Even scheduled agent tasks need a human review occasionally.&lt;/li&gt;
&lt;li&gt;Don't paste GitHub URLs into chat expecting context without the GitHub Pull Requests extension installed.&lt;/li&gt;
&lt;li&gt;Don't use the Agents window GitHub integration without enabling &lt;code&gt;extensions.experimental.enableAgentsWindowCapability&lt;/code&gt; first — nothing will work.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes Developers Make with New VS Code Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Enabling everything at once and getting confused
&lt;/h3&gt;

&lt;p&gt;It's tempting to flip on every experimental setting and see what happens. The problem is, when something doesn't work as expected, you won't know why. Enable features one at a time so you understand what each one does.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ignoring the "rolling out gradually" note
&lt;/h3&gt;

&lt;p&gt;Some features in 1.137, like Automations, are not available to everyone on day one. If you enable the setting and don't see the feature, wait a day or check the Insiders build.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Writing automation prompts that are too vague
&lt;/h3&gt;

&lt;p&gt;"Check things" is not a useful automation prompt. "Summarize any new issues opened in the last 24 hours and flag ones labeled 'bug'" is. The agent follows the prompt you give it. Be specific.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Forgetting to install the required extension
&lt;/h3&gt;

&lt;p&gt;The GitHub integration in the Agents window needs the &lt;strong&gt;GitHub Pull Requests extension&lt;/strong&gt; installed in your &lt;strong&gt;default VS Code profile&lt;/strong&gt;. If you use separate profiles, make sure it's in the right one.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Not trying the quick-chat-to-workspace transition
&lt;/h3&gt;

&lt;p&gt;This feature is easy to overlook because it solves a problem you might not realize you're having. Next time you start a quick chat that grows into something project-specific, try attaching a workspace instead of starting over.&lt;/p&gt;




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

&lt;p&gt;VS Code 1.137 is a thoughtful release. It's not just adding features for the sake of it — it's solving the annoying, repetitive, context-switching parts of a developer's day.&lt;/p&gt;

&lt;p&gt;Scheduled automations mean your routine tasks can run without you. Voice Mode means you can direct the agent without stopping to type. GitHub integration means you never have to leave your editor to check an issue. And continuing quick chats in a workspace means your conversational momentum doesn't get lost when work gets real.&lt;/p&gt;

&lt;p&gt;It's a genuinely good update. 😊&lt;/p&gt;

&lt;p&gt;Give it a try, explore the experimental features, and see which ones fit naturally into your workflow. Chances are at least two of them will stick.&lt;/p&gt;

&lt;p&gt;If you found this helpful, share it with a teammate who still manually triages issues every Monday morning. They'll thank you.&lt;/p&gt;

&lt;p&gt;For more practical dev tutorials, tools, and blog posts like this, head over to &lt;strong&gt;&lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;&lt;/strong&gt; — there's plenty more where this came from. 🔧&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>VS Code 1.134 Is Here — Side-by-Side Chats, Prompt Timeline, and More Features You'll Actually Use</title>
      <dc:creator>Muhammad Hamid Raza</dc:creator>
      <pubDate>Thu, 20 Aug 2026 09:03:11 +0000</pubDate>
      <link>https://dev.to/hamidrazadev/vs-code-1134-is-here-side-by-side-chats-prompt-timeline-and-more-features-youll-actually-use-2ck2</link>
      <guid>https://dev.to/hamidrazadev/vs-code-1134-is-here-side-by-side-chats-prompt-timeline-and-more-features-youll-actually-use-2ck2</guid>
      <description>&lt;p&gt;If you've ever scrolled forever trying to find something you typed ten minutes ago in a long chat session... VS Code 1.134 just heard your pain. 😅&lt;/p&gt;

&lt;p&gt;Released on &lt;strong&gt;August 19, 2026&lt;/strong&gt;, this update is one of those rare releases that feels like the team was watching over your shoulder while you worked. It fixes small but real annoyances, adds tools for managing complex agent sessions, and makes the whole editor feel a bit more like a smart workspace and less like a blank canvas you have to fight every day.&lt;/p&gt;

&lt;p&gt;So what exactly changed? Let's break it down in plain English.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is VS Code 1.134?
&lt;/h2&gt;

&lt;p&gt;Visual Studio Code is the most popular free code editor in the world. Millions of developers use it daily — from students writing their first Python script to professionals building large-scale apps.&lt;/p&gt;

&lt;p&gt;Every month or so, the VS Code team ships a new version packed with bug fixes, performance improvements, and new features. Version &lt;strong&gt;1.134&lt;/strong&gt; is the latest of those updates, focused on three main areas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Agents&lt;/strong&gt; — how VS Code handles AI-powered sessions and multi-window workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chat&lt;/strong&gt; — organizing and navigating your conversations with AI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editor Experience&lt;/strong&gt; — small quality-of-life improvements that make daily work smoother&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think of it like a phone software update — except instead of fixing battery drain, it fixes the things that slow you down while writing code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Update Matters
&lt;/h2&gt;

&lt;p&gt;AI-powered coding tools have become a normal part of most developers' workflows. But as those tools get more powerful, the conversations get longer, the sessions get more complex, and managing everything becomes its own challenge.&lt;/p&gt;

&lt;p&gt;VS Code 1.134 addresses that challenge head-on.&lt;/p&gt;

&lt;p&gt;If you've used GitHub Copilot inside VS Code for any extended session, you know the feeling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're mid-task and can't remember what you asked earlier&lt;/li&gt;
&lt;li&gt;You want to compare two different agent responses&lt;/li&gt;
&lt;li&gt;You made a bunch of file changes but can't trace which prompt caused them&lt;/li&gt;
&lt;li&gt;You need to find a specific line from your conversation but scrolling takes forever&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This release tackles all of those problems — not with flashy features, but with practical, focused solutions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features in VS Code 1.134 — With Real-Life Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 🗂️ Side-by-Side Chats (Grid Layout)
&lt;/h3&gt;

&lt;p&gt;Imagine you're comparing two approaches for the same problem. You ask the agent one way, then another. But switching between those conversations constantly is frustrating — like flipping between two browser tabs when you wish you could just split the screen.&lt;/p&gt;

&lt;p&gt;VS Code 1.134 lets you do exactly that. You can now &lt;strong&gt;arrange chats in horizontal or vertical groups&lt;/strong&gt; inside a session. Drag a chat — or a subagent chat — into a group and view them side by side.&lt;/p&gt;

&lt;p&gt;You can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hold &lt;code&gt;Alt&lt;/code&gt; and click a chat in the Chats picker to open it directly to the side&lt;/li&gt;
&lt;li&gt;Create a "side chat" to start a fresh conversation beside your current one&lt;/li&gt;
&lt;li&gt;Restore the exact same layout when you reload the window or return to the session&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is genuinely useful when you're running parallel tasks or comparing results from different agent prompts without losing context.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. ⏱️ Prompt Timeline
&lt;/h3&gt;

&lt;p&gt;Long agent sessions are powerful — but they also produce a wall of conversation that's hard to navigate. Which prompt caused those file changes? Where did you start exploring that feature? Which earlier idea should you revisit?&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Prompt Timeline&lt;/strong&gt; solves this with a clean timeline in the transcript gutter of the Agents window. Each dot represents one of your prompts. The highlighted dot shows where you are right now.&lt;/p&gt;

&lt;p&gt;Hover over the timeline to see a list of your prompts. Click one to jump to it instantly. And if a prompt changed any files, the timeline shows you exactly &lt;strong&gt;how many lines were added or removed&lt;/strong&gt; — and lets you open the diff right there.&lt;/p&gt;

&lt;p&gt;You can control how the timeline appears using the &lt;code&gt;sessions.chatTimeline.display&lt;/code&gt; setting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ruler&lt;/code&gt; — shows the timeline beside the scrollbar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;off&lt;/code&gt; — hides it completely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like a chapter list for your agent session. You can finally stop scrolling through everything just to find where you were.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. 🔍 Find in Chat
&lt;/h3&gt;

&lt;p&gt;This one is simple but long overdue.&lt;/p&gt;

&lt;p&gt;You can now use &lt;code&gt;workbench.action.chat.find&lt;/code&gt; to &lt;strong&gt;search your entire conversation&lt;/strong&gt; — including content that's not currently visible on screen. It works in the Chat view, chat editors, and the Agents window.&lt;/p&gt;

&lt;p&gt;It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Case-sensitive matching&lt;/li&gt;
&lt;li&gt;Whole-word matching&lt;/li&gt;
&lt;li&gt;Regular expressions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you jump to a match, VS Code scrolls it into view and even &lt;strong&gt;expands collapsed work summaries&lt;/strong&gt; if the match is inside them.&lt;/p&gt;

&lt;p&gt;If you've ever said "I know I typed this somewhere earlier..." — this feature is for you.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. 🌐 Open HTML Files in the Integrated Browser by Default
&lt;/h3&gt;

&lt;p&gt;Frontend developers, this one's for you.&lt;/p&gt;

&lt;p&gt;If your workflow involves frequently previewing local HTML files rather than editing them, you can now set the &lt;strong&gt;integrated browser as the default editor&lt;/strong&gt; for HTML files. Configure it through &lt;code&gt;workbench.editorAssociations&lt;/code&gt; or directly from the editor header.&lt;/p&gt;

&lt;p&gt;The integrated browser works just like a standalone browser tab — but it stays connected to your HTML file. Any links inside the file open in new tabs so the association is preserved.&lt;/p&gt;

&lt;p&gt;No more switching to Chrome just to check if your layout looks right. 💡&lt;/p&gt;




&lt;h3&gt;
  
  
  5. 🏠 Agent Host — Connect Multiple Windows to One Session
&lt;/h3&gt;

&lt;p&gt;This is a more advanced feature, but worth knowing about.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Agent Host&lt;/strong&gt; lets you connect to the same agent session from multiple VS Code windows. It runs agent processes in a dedicated environment using the Agent Host Protocol (AHP), and the Copilot agent inside it is powered by the Copilot SDK — so its behavior is consistent with the CLI, the standalone Copilot app, and other Copilot tools.&lt;/p&gt;

&lt;p&gt;If you work across multiple monitors or windows, this means your agent session doesn't have to be isolated to one window. You can attach to it from wherever you're working.&lt;/p&gt;

&lt;p&gt;The feature is still actively being developed, and the team is welcoming feedback through GitHub issues.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. 🪟 Improved Side Pane Layout
&lt;/h3&gt;

&lt;p&gt;The single-pane layout now follows your &lt;code&gt;workbench.editor.showTabs&lt;/code&gt; setting more naturally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With &lt;strong&gt;multiple tabs&lt;/strong&gt; visible, the layout stays familiar&lt;/li&gt;
&lt;li&gt;With &lt;strong&gt;single&lt;/strong&gt; or &lt;strong&gt;none&lt;/strong&gt; settings, a compact single-title header takes over — much cleaner for minimal setups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Text file editors in this mode now use &lt;strong&gt;file breadcrumbs in the header&lt;/strong&gt;, just like the Changes editor — so you always know exactly what you're looking at.&lt;/p&gt;

&lt;p&gt;The side pane also holds its size and visibility when you switch between sessions. No more unexpected layout jumps.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. ✖️ Close Other Editors with Alt+Click
&lt;/h3&gt;

&lt;p&gt;Small feature, real time-saver.&lt;/p&gt;

&lt;p&gt;You know how you sometimes end up with eight tabs open and you just want to keep one? Normally you'd right-click a tab and dig through a context menu.&lt;/p&gt;

&lt;p&gt;Now you can just hold &lt;code&gt;Alt&lt;/code&gt; and the close button on any tab &lt;strong&gt;transforms into "Close Other Editors"&lt;/strong&gt;. Click it, and every other tab closes except the one you clicked on.&lt;/p&gt;

&lt;p&gt;That's it. Clean and fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before vs. After — What Actually Changed for Daily Work
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Before 1.134&lt;/th&gt;
&lt;th&gt;After 1.134&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Comparing two agent responses&lt;/td&gt;
&lt;td&gt;Open one, close it, open the other&lt;/td&gt;
&lt;td&gt;Drag both into a side-by-side group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finding an earlier prompt&lt;/td&gt;
&lt;td&gt;Scroll through the whole session&lt;/td&gt;
&lt;td&gt;Jump directly using the Prompt Timeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Searching conversation history&lt;/td&gt;
&lt;td&gt;Manual scrolling&lt;/td&gt;
&lt;td&gt;Ctrl+F style search with regex support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Previewing HTML files&lt;/td&gt;
&lt;td&gt;Switch to an external browser&lt;/td&gt;
&lt;td&gt;Use the integrated browser as default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keeping one tab, closing the rest&lt;/td&gt;
&lt;td&gt;Right-click → context menu&lt;/td&gt;
&lt;td&gt;Alt+click the close button&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of these changes are dramatic on their own. But together they remove a surprising amount of friction from the daily workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tips and Do's &amp;amp; Don'ts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable the Prompt Timeline (&lt;code&gt;sessions.chatTimeline.display: ruler&lt;/code&gt;) if you run long agent sessions — it pays off immediately&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Alt+click&lt;/code&gt; on chat items in the Chats picker to open them to the side instead of navigating away&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;workbench.editorAssociations&lt;/code&gt; for HTML if you're a frontend developer previewing files regularly&lt;/li&gt;
&lt;li&gt;Check for updates manually if you want 1.134 now — VS Code rolls out updates gradually, so use &lt;strong&gt;Help → Check for Updates&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ignore the Agent Host documentation if you work with multiple windows — it's worth a quick read&lt;/li&gt;
&lt;li&gt;Forget that the Find in Chat tool supports regex — it's more powerful than a plain text search&lt;/li&gt;
&lt;li&gt;Close the side pane between sessions if you're actively comparing chats — 1.134 now preserves its size and position&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Waiting for the update to appear automatically&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VS Code uses a gradual rollout, so not everyone gets the update on day one. If you want 1.134 right now, go to &lt;code&gt;Help → Check for Updates&lt;/code&gt; and grab it manually. Waiting and wondering why you don't see the new features is a common time-waster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Overlooking the Prompt Timeline setting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Prompt Timeline defaults to showing beside the scrollbar. If you don't see it, check &lt;code&gt;sessions.chatTimeline.display&lt;/code&gt; in your settings. Some users enable the single-pane layout without realizing the timeline is available — don't miss it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Not using Find in Chat for long conversations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's natural to scroll when looking for something — because that's how we've always done it. But the new Find in Chat works across the entire conversation, including collapsed summaries. Make it a habit early so you stop wasting time scrolling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Forgetting that the Agent Host is still in development&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Agent Host is genuinely useful, but it's early stage. If something doesn't work as expected, file an issue rather than assuming it's a permanent limitation. The team is actively improving it.&lt;/p&gt;




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

&lt;p&gt;VS Code 1.134 is not a "wow, everything changed" release. But it is a &lt;strong&gt;well-thought-out, practical improvement&lt;/strong&gt; to how you work with AI-powered sessions, long conversations, and everyday editor tasks.&lt;/p&gt;

&lt;p&gt;Side-by-side chats, the Prompt Timeline, Find in Chat, HTML preview by default, the Alt+click tab shortcut — each of these is small on its own. But if you spend hours every day in VS Code, these are exactly the kinds of improvements that add up.&lt;/p&gt;

&lt;p&gt;The team is clearly paying attention to how developers actually use the editor — not just adding features, but fixing the rough edges. 🚀&lt;/p&gt;

&lt;p&gt;If you want to try the latest features before the next stable release, grab the &lt;a href="https://code.visualstudio.com/insiders/" rel="noopener noreferrer"&gt;Insiders build&lt;/a&gt; — it gets updates as soon as they're ready.&lt;/p&gt;




&lt;p&gt;👉 &lt;strong&gt;Want more posts like this?&lt;/strong&gt; I cover the latest in VS Code, frontend development, and developer tools at &lt;a href="https://hamidrazadev.com" rel="noopener noreferrer"&gt;hamidrazadev.com&lt;/a&gt;. Come check it out, and if this post saved you some time, share it with a developer friend who might find it useful. ✌️&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
