<?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: MO Slah</title>
    <description>The latest articles on DEV Community by MO Slah (@m0slah).</description>
    <link>https://dev.to/m0slah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1084735%2Fddfe32d4-e786-48ea-8696-0742c24c5c0a.jpeg</url>
      <title>DEV Community: MO Slah</title>
      <link>https://dev.to/m0slah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/m0slah"/>
    <language>en</language>
    <item>
      <title>Using `userAgent` in Next.js App Router — Device, Browser, OS &amp; Bot Detection</title>
      <dc:creator>MO Slah</dc:creator>
      <pubDate>Fri, 03 Apr 2026 21:29:21 +0000</pubDate>
      <link>https://dev.to/m0slah/using-useragent-in-nextjs-app-router-device-browser-os-bot-detection-1ho8</link>
      <guid>https://dev.to/m0slah/using-useragent-in-nextjs-app-router-device-browser-os-bot-detection-1ho8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpl88pkf3dw8n5hpotlr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpl88pkf3dw8n5hpotlr.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Server-side user-agent parsing without the manual string gymnastics.&lt;/p&gt;

&lt;p&gt;Ever needed to redirect mobile users or block bots before the page even renders? Next.js has a built-in helper for exactly that: userAgent. Instead of manually parsing raw header strings, you get a clean structured object with everything you need, right inside Middleware or a Route Handler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is userAgent?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;userAgent is a helper exported from next/server. Pass it the incoming NextRequest and it returns a parsed object with structured client data — no regex required.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { userAgent } from 'next/server'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's a minimal example inside middleware:&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;NextRequest&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="nx"&gt;userAgent&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="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&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;middleware&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;NextRequest&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;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isBot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;userAgent&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// { type: 'mobile', model: 'iPhone', vendor: 'Apple' }&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// { name: 'Safari', version: '17.0' }&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// { name: 'iOS', version: '17.0' }&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isBot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// false&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;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;What You Get&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;device&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Sample Values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;mobile, tablet, console, smarttv&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;model&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone, Galaxy S21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vendor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Apple, Samsung, Google&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobile&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;redirect&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/m&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;browser&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Sample Values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Chrome, Safari, Firefox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Major version string&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identifier&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Safari&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="c1"&gt;// implement fixes or headers specific to Safari&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OS&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Sample Values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iOS, Android, Windows, macOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OS version string&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iOS&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="c1"&gt;// manage behaviors specific to iOS&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;isBot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;boolean&lt;/strong&gt;. Returns true if the request originates from a recognized crawler. Useful for delivering streamlined, SEO-optimized responses or skipping analytics pings entirely.&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAutomated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// bypass heavy JS hydration, deliver static HTML only&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;rewrite&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/seo-version&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;cpu&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reveals the CPU architecture — useful when serving distinct WASM bundles for arm versus amd64 devices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cpu&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'arm', 'amd64', etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Practical Everyday Applications&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send mobile users to /m before the layout loads&lt;/li&gt;
&lt;li&gt;Serve simpler static HTML to bots to improve SEO performance&lt;/li&gt;
&lt;li&gt;Apply server-side response headers tailored to specific browsers&lt;/li&gt;
&lt;li&gt;Skip analytics pings for crawlers&lt;/li&gt;
&lt;li&gt;Deliver CPU architecture-specific WASM bundles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful starting point — reroute mobile users before the layout even loads:&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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&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;device&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobile&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;redirect&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&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="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;next&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;Key Things to Remember&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-exclusive&lt;/strong&gt;. You can use userAgent in Middleware and Route Handlers — not in Client Components. On the client side, use navigator.userAgent instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It makes your route dynamic&lt;/strong&gt;. Using userAgent opts your route out of full static generation. Next.js won't cache it at build time since the response depends on the incoming request. Keep that in mind for performance-sensitive pages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not entirely reliable&lt;/strong&gt;. The user-agent string comes from the client and can be spoofed or modified. Use it for progressive enhancement decisions, not hard security gating.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;userAgent&lt;/code&gt; (Next.js)&lt;/th&gt;
&lt;th&gt;&lt;code&gt;navigator.userAgent&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runs on&lt;/td&gt;
&lt;td&gt;Server (Middleware / SSR)&lt;/td&gt;
&lt;td&gt;Client only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parsing&lt;/td&gt;
&lt;td&gt;Built-in, structured&lt;/td&gt;
&lt;td&gt;Manual (string)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use case&lt;/td&gt;
&lt;td&gt;Redirect, rewrite, SSR logic&lt;/td&gt;
&lt;td&gt;Client-side UI logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bot detection&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;isBot&lt;/code&gt; included&lt;/td&gt;
&lt;td&gt;Manual regex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spoofable&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To understand your users at the request level in Next.js, userAgent is the right tool. It provides structured data about devices, browsers, operating systems, and bots — without depending on client-side APIs.&lt;/p&gt;

&lt;p&gt;A practical starting point: use it in middleware to direct mobile users to /m while keeping desktop traffic on the main layout — no client-side JavaScript, no layout shift for the user.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🚀Understanding JavaScript Strict Mode: Why You Should Always Use It</title>
      <dc:creator>MO Slah</dc:creator>
      <pubDate>Wed, 19 Nov 2025 21:19:23 +0000</pubDate>
      <link>https://dev.to/m0slah/understanding-javascript-strict-mode-why-you-should-always-use-it-p74</link>
      <guid>https://dev.to/m0slah/understanding-javascript-strict-mode-why-you-should-always-use-it-p74</guid>
      <description>&lt;p&gt;When ES5 was released, JavaScript introduced a new feature called "Strict Mode", designed to make the language safer, cleaner, and more predictable. While it might seem like a small thing, "use strict" can make a huge difference in the quality and stability of your code.&lt;/p&gt;

&lt;p&gt;Let’s dive into what strict mode is, why it exists, and why you should always use it in your programs.&lt;/p&gt;

&lt;p&gt;What Is Strict Mode?&lt;/p&gt;

&lt;p&gt;Strict Mode tightens JavaScript’s rules and removes some of the language’s silent errors. It helps you write better, more reliable code by enforcing stricter parsing and error handling.&lt;/p&gt;

&lt;p&gt;In short, strict mode:&lt;/p&gt;

&lt;p&gt;Prevents the use of undeclared variables&lt;/p&gt;

&lt;p&gt;Throws more meaningful errors&lt;/p&gt;

&lt;p&gt;Disables dangerous or confusing features&lt;/p&gt;

&lt;p&gt;Helps the JavaScript engine optimize performance&lt;/p&gt;

&lt;p&gt;As Kyle Simpson mentions in You Don’t Know JS: Types &amp;amp; Grammar:&lt;/p&gt;

&lt;p&gt;“Strict mode is a big win for code, and you should use it for all your programs.”&lt;/p&gt;

&lt;p&gt;How to Enable Strict Mode&lt;/p&gt;

&lt;p&gt;You can enable strict mode globally or per function, depending on where you place "use strict".&lt;/p&gt;

&lt;p&gt;Global Strict Mode&lt;/p&gt;

&lt;p&gt;When you place it at the top of your file, the entire file runs in strict mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use strict";

function foo() {
  // strict mode is active here
  function bar() {
    // strict mode is active here too
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Function-Level Strict Mode&lt;/p&gt;

&lt;p&gt;You can also enable strict mode inside an individual function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function foo() {
  "use strict";
  // only this function runs in strict mode

  function bar() {
    // not in strict mode
  }
}

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

&lt;/div&gt;



&lt;p&gt;What Happens When You Use Strict Mode&lt;/p&gt;

&lt;p&gt;Strict mode makes JavaScript behave in a more predictable and professional way. Here are some of the biggest improvements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No Implicit Global Variables&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without strict mode, assigning a value to an undeclared variable automatically creates a global variable — a common source of bugs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function foo() {
  a = 10; // creates a global variable (bad!)
}
foo();
console.log(a); // 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With strict mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function foo() {
  "use strict";
  a = 10; // ❌ ReferenceError: a is not defined
}
foo();

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

&lt;/div&gt;



&lt;p&gt;This forces you to declare variables properly with let, const, or var.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prevents Silent Failures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In non-strict mode, some operations fail silently. For example, assigning a value to a read-only property doesn’t throw an error — it just fails quietly.&lt;/p&gt;

&lt;p&gt;Strict mode changes that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use strict";

const obj = {};
Object.defineProperty(obj, "x", { value: 42, writable: false });

obj.x = 9; // ❌ TypeError

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Disallows Duplicate Parameter Names&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Strict mode doesn’t allow you to use the same parameter name more than once — which avoids confusion and improves readability.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use strict";
function sum(a, a, c) { // ❌ SyntaxError
  return a + a + c;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Prevents this from Being Global&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In non-strict mode, if you call a function without a context, this defaults to the global object (window in browsers).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function showThis() {
  console.log(this); // window
}
showThis();

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

&lt;/div&gt;



&lt;p&gt;But in strict mode, this stays undefined — which is safer and prevents accidental global variable leaks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use strict";
function showThis() {
  console.log(this); // undefined
}
showThis();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why You Shouldn’t Avoid Strict Mode&lt;/p&gt;

&lt;p&gt;If turning on strict mode makes your code break, that’s a good thing — it means strict mode is revealing potential issues in your program.&lt;/p&gt;

&lt;p&gt;“If strict mode causes issues in your program, it’s almost certainly a sign that you have things you should fix.”&lt;br&gt;
— You Don’t Know JS: Types &amp;amp; Grammar&lt;/p&gt;

&lt;p&gt;Fixing these issues will make your code cleaner, more maintainable, and more future-proof.&lt;/p&gt;

&lt;p&gt;🛠️ Strict Mode and Modern JavaScript&lt;/p&gt;

&lt;p&gt;If you’re using ES6 modules (import / export), you don’t need to manually enable strict mode — it’s automatically applied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This module is always in strict mode
export function greet() {
  message = "Hello!"; // ❌ ReferenceError
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So modern JavaScript essentially encourages best practices by default.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;Strict mode isn’t just a “developer annoyance” — it’s a tool for writing better JavaScript.&lt;/p&gt;

&lt;p&gt;It catches common mistakes early&lt;br&gt;
It improves performance&lt;br&gt;
It aligns with the modern direction of JavaScript&lt;/p&gt;

&lt;p&gt;So don’t delay — make "use strict" (or ES modules) your default. Your future self will thank you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Why typeof null === "object" in JavaScript? A Deep Dive into a Quirky Bug</title>
      <dc:creator>MO Slah</dc:creator>
      <pubDate>Sat, 17 May 2025 23:28:46 +0000</pubDate>
      <link>https://dev.to/m0slah/why-typeof-null-object-in-javascript-a-deep-dive-into-a-quirky-bug-n6p</link>
      <guid>https://dev.to/m0slah/why-typeof-null-object-in-javascript-a-deep-dive-into-a-quirky-bug-n6p</guid>
      <description>&lt;p&gt;If you’ve ever played around with JavaScript and used typeof, you may have stumbled upon this strange behavior:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;typeof null; // returns "object"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wait—what? &lt;strong&gt;Shouldn’t typeof null return "null"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is one of the most well-known and long-standing oddities in JavaScript. Let’s take a deep dive into why this happens, how it originated, and why it will likely never be fixed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Is typeof in JavaScript?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The typeof operator in JavaScript returns a string that represents the type of the operand:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;typeof 42;           // "number"&lt;br&gt;
typeof "hello";      // "string"&lt;br&gt;
typeof true;         // "boolean"&lt;br&gt;
typeof undefined;    // "undefined"&lt;br&gt;
typeof {};           // "object"&lt;br&gt;
typeof function(){}; // "function"&lt;br&gt;
typeof Symbol();     // "symbol"&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But then:&lt;br&gt;
&lt;code&gt;typeof null;         // "object"&lt;/code&gt;&lt;br&gt;
 &lt;em&gt;That looks... wrong.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Does typeof null Return "object"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This dates back to the early days of JavaScript, in the 1990s. JavaScript was designed in a hurry—literally in just 10 days—and the internal implementation details left some quirks behind.&lt;/p&gt;

&lt;p&gt;Here’s the technical reason:&lt;/p&gt;

&lt;p&gt;Internally, JavaScript values were represented using a type tag in their binary form.&lt;/p&gt;

&lt;p&gt;The type tag for objects was 000, and null also happened to be represented with a binary value of all zeroes (0x00).&lt;/p&gt;

&lt;p&gt;As a result, the typeof operation interpreted null as an object.&lt;/p&gt;

&lt;p&gt;So it’s essentially a bug in the original implementation that got locked into the language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Can’t This Be Fixed?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It seems simple—just fix the bug so that typeof null returns "null", right?&lt;/p&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;Here’s the problem: JavaScript is the most widely used programming language in the world, and it’s embedded in billions of websites and applications. Changing the return value of typeof null now would break backward compatibility for existing codebases that depend on it returning "object".&lt;/p&gt;

&lt;p&gt;In fact, this issue is so well-known that Brendan Eich (the creator of JavaScript) addressed it himself, admitting it’s a bug but also saying it’s too late to fix.&lt;/p&gt;

&lt;p&gt;Here’s a relevant quote:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“typeof null === "object" is a bug, but fixing it would break a lot of code on the web.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;— Brendan Eich, Creator of JavaScript&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;typeof null returns "object" — a historical bug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It originated from early binary representations of types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s too risky to fix now because it would break too much existing code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use strict equality to check for null.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JavaScript is full of quirks, and this one is a classic example. While it might seem strange at first, understanding these “gotchas” helps us write more robust and reliable code.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>website</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Evolution of LiveScript: The Precursor to JavaScript</title>
      <dc:creator>MO Slah</dc:creator>
      <pubDate>Mon, 23 Dec 2024 22:03:39 +0000</pubDate>
      <link>https://dev.to/m0slah/the-evolution-of-livescript-the-precursor-to-javascript-245i</link>
      <guid>https://dev.to/m0slah/the-evolution-of-livescript-the-precursor-to-javascript-245i</guid>
      <description>&lt;p&gt;When we think about web development, JavaScript is one of the first technologies that comes to mind. It’s hard to imagine a time when JavaScript wasn’t the backbone of interactivity on the web. But did you know that JavaScript wasn’t always called JavaScript? Its roots trace back to a language called LiveScript, and its journey is a fascinating chapter in programming history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Birth of LiveScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In 1995, Netscape Communications Corporation was at the forefront of web innovation. As the internet grew in popularity, there was a pressing need for a lightweight scripting language to make web pages more dynamic. This led to the creation of LiveScript, a scripting language designed to work within the browser.&lt;/p&gt;

&lt;p&gt;LiveScript was developed with a simple goal: to make web pages interactive without requiring extensive programming knowledge. It allowed developers to write small scripts directly in HTML to handle events like button clicks or form submissions. This simplicity made LiveScript an attractive option for web designers who wanted to add interactivity without delving into complex programming paradigms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LiveScript Becomes JavaScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In December 1995, shortly after its initial release, LiveScript underwent a significant rebranding. Netscape partnered with Sun Microsystems, the company behind the popular programming language Java. To capitalize on Java's growing popularity and marketing appeal, LiveScript was renamed to JavaScript.&lt;/p&gt;

&lt;p&gt;Despite the shared name, JavaScript and Java have very little in common. The renaming was primarily a marketing move, leading to some confusion that persists even today. While Java is a statically typed, object-oriented programming language, JavaScript is a dynamically typed, prototype-based scripting language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features of LiveScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LiveScript introduced several features that became foundational to JavaScript:&lt;/p&gt;

&lt;p&gt;Lightweight Syntax: Designed to be easy to use for web designers and developers alike.&lt;/p&gt;

&lt;p&gt;Event Handling: Allowed developers to respond to user actions like clicks, form submissions, and more.&lt;/p&gt;

&lt;p&gt;Browser Integration: Scripts could be embedded directly into HTML, making it accessible and straightforward.&lt;/p&gt;

&lt;p&gt;These features laid the groundwork for JavaScript’s role as a key player in web development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Legacy of LiveScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The transformation of LiveScript into JavaScript marked the beginning of one of the most significant developments in programming history. JavaScript has since evolved into a versatile, full-fledged programming language capable of:&lt;/p&gt;

&lt;p&gt;Powering dynamic user interfaces with frameworks like React, Vue, and Angular.&lt;/p&gt;

&lt;p&gt;Enabling server-side development with tools like Node.js.&lt;/p&gt;

&lt;p&gt;Supporting mobile and desktop applications through frameworks like React Native and Electron.&lt;/p&gt;

&lt;p&gt;But the influence of LiveScript doesn’t stop there. Its legacy reminds us of the importance of simplicity and accessibility in programming. By lowering the barrier to entry, LiveScript paved the way for countless developers to start their journey in web development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus: A Modern Twist&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Interestingly, there’s another language called LiveScript, released in 2011, which is unrelated to the original LiveScript. This modern LiveScript is a functional programming language that compiles to JavaScript, inspired by CoffeeScript. While it’s not the same as the 1995 version, it’s a testament to how JavaScript’s ecosystem continues to inspire new ideas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The story of LiveScript is a reminder of how technology evolves and adapts to meet the needs of its time. From its humble beginnings as a simple browser scripting language to its transformation into JavaScript, LiveScript played a crucial role in shaping the modern web.&lt;/p&gt;

&lt;p&gt;Whether you’re a seasoned developer or just starting out, understanding the history of LiveScript can give you a deeper appreciation for the tools we use today. So the next time you write a piece of JavaScript code, take a moment to reflect on the journey that started with LiveScript over two decades ago.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>website</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
