<?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: Azad Shukor</title>
    <description>The latest articles on DEV Community by Azad Shukor (@azadshukor).</description>
    <link>https://dev.to/azadshukor</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%2F1035198%2F42ef8a08-4c61-40ae-b4f5-8497b4cb5316.jpeg</url>
      <title>DEV Community: Azad Shukor</title>
      <link>https://dev.to/azadshukor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/azadshukor"/>
    <language>en</language>
    <item>
      <title>Understanding CIDR Notation</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Sun, 12 Apr 2026 02:05:48 +0000</pubDate>
      <link>https://dev.to/azadshukor/understanding-cidr-notation-585o</link>
      <guid>https://dev.to/azadshukor/understanding-cidr-notation-585o</guid>
      <description>&lt;h2&gt;
  
  
  Understanding IPv4 CIDR Blocks
&lt;/h2&gt;

&lt;p&gt;A CIDR block looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0/16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has two parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IP address&lt;/strong&gt; → starting point&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefix (/16)&lt;/strong&gt; → how many bits are fixed&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Core Idea (Memorize This First)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;IPv4 = &lt;strong&gt;32 bits total&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;CIDR &lt;code&gt;/N&lt;/code&gt; = &lt;strong&gt;N bits are fixed (network)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Remaining bits = &lt;strong&gt;host bits (free to change)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total addresses = 2^(32 - N)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  IPv4 Structure
&lt;/h3&gt;

&lt;p&gt;An IPv4 address:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Breakdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10       . 0       . 0       . 0
8 bits     8 bits    8 bits    8 bits

Total = 32 bits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each block:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;8 bits = values from 0 to 255&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt;   → &lt;code&gt;00000000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;255&lt;/code&gt; → &lt;code&gt;11111111&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Think in Terms of LOCKED vs FREE
&lt;/h3&gt;

&lt;p&gt;Instead of memorizing formulas, think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Locked bits&lt;/strong&gt; = define the network&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free bits&lt;/strong&gt; = generate all possible addresses&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Example: &lt;code&gt;10.0.0.0/16&lt;/code&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: Count free bits
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;32 - 16 = 16 free bits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Calculate total addresses
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2^16 = 65,536
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Visualize
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10       . 0       . 0       . 0
[LOCKED]   [LOCKED]   [FREE]    [FREE]
  8 bits     8 bits     8 bits    8 bits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;First 2 blocks fixed → &lt;code&gt;10.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Last 2 blocks vary → &lt;code&gt;0.0&lt;/code&gt; to &lt;code&gt;255.255&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Range:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0 → 10.0.255.255
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  How to Read Any CIDR Quickly
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Rule:
&lt;/h4&gt;

&lt;p&gt;Move left to right, filling &lt;strong&gt;8 bits per block&lt;/strong&gt;, until you reach &lt;code&gt;/N&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example: &lt;code&gt;/10&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0/10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10       . 0       . 0       . 0
[8 LOCK]   [2 LOCK]   [FREE]    [FREE]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;8 bits from first block&lt;/li&gt;
&lt;li&gt;2 bits from second block
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total locked = 10 bits
Free = 22 bits
Total addresses = 2^22 = 4,194,304
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Example: &lt;code&gt;/20&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0/20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10       . 0       . 0       . 0
[8 LOCK]   [8 LOCK]   [4 LOCK]   [FREE]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Locked = 20 bits
Free = 12 bits
Total = 2^12 = 4,096
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Example: &lt;code&gt;/26&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0/26
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10       . 0       . 0       . 0
[8 LOCK]   [8 LOCK]   [8 LOCK]   [2 LOCK]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Locked = 26 bits
Free = 6 bits
Total = 2^6 = 64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Example: &lt;code&gt;/30&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0/30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10       . 0       . 0       . 0
[8 LOCK]   [8 LOCK]   [8 LOCK]   [6 LOCK]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Free bits = 2
Total = 2^2 = 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0 → 10.0.0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Shortcut Patterns (High Value)
&lt;/h3&gt;

&lt;p&gt;Instead of recalculating every time:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CIDR&lt;/th&gt;
&lt;th&gt;Free Bits&lt;/th&gt;
&lt;th&gt;Total IPs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;/16&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;65,536&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/24&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/26&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/30&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Important Practical Note
&lt;/h3&gt;

&lt;p&gt;Not all addresses are usable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First IP&lt;/strong&gt; → network address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Last IP&lt;/strong&gt; → broadcast address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example &lt;code&gt;/30&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0 → network
10.0.0.1 → usable
10.0.0.2 → usable
10.0.0.3 → broadcast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Mental Model (Best Way to Think)
&lt;/h3&gt;

&lt;p&gt;Treat CIDR like a &lt;strong&gt;binary lock&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/N&lt;/code&gt; = how many switches are locked&lt;/li&gt;
&lt;li&gt;Remaining switches = combinations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More free bits → bigger network&lt;br&gt;
Fewer free bits → smaller network&lt;/p&gt;




&lt;h3&gt;
  
  
  One-Line Summary
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;CIDR is just: how many bits are fixed vs how many bits can vary.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>networking</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Next.js ConnectRPC Proxy Pattern</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Wed, 04 Feb 2026 14:05:13 +0000</pubDate>
      <link>https://dev.to/azadshukor/nextjs-connectrpc-proxy-pattern-2hpn</link>
      <guid>https://dev.to/azadshukor/nextjs-connectrpc-proxy-pattern-2hpn</guid>
      <description>&lt;p&gt;This article demonstrates a strictly typed gRPC implementation in Next.js using &lt;strong&gt;ConnectRPC&lt;/strong&gt; and &lt;strong&gt;TanStack Query&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The core architectural goal is to unify the Server and Client definitions. It achieves this by implementing a &lt;strong&gt;Proxy Pattern&lt;/strong&gt;: the Next.js API route exposes a local &lt;code&gt;GreetService&lt;/code&gt; that acts as a typed gateway, forwarding requests to a remote &lt;code&gt;ElizaService&lt;/code&gt; while reusing the exact same Proto definitions.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Dependencies
&lt;/h2&gt;

&lt;p&gt;Required packages for ConnectRPC v2, Next.js 15, and TanStack Query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"airborneo-grpc-proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"private"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"generate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"buf generate proto"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@bufbuild/protobuf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.2.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@connectrpc/connect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@connectrpc/connect-next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@connectrpc/connect-node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.1.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@connectrpc/connect-query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@connectrpc/connect-web"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.1.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@tanstack/react-query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"15.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^19.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^19.0.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@bufbuild/buf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.47.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@bufbuild/protoc-gen-es"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.2.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@connectrpc/protoc-gen-connect-query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@types/node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^20"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@types/react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^19"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@types/react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^19"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Proto Definition &amp;amp; Generation
&lt;/h2&gt;

&lt;p&gt;We define two proto files. &lt;code&gt;GreetService&lt;/code&gt; imports &lt;code&gt;ElizaService&lt;/code&gt; messages to ensure strict type parity between the proxy and the upstream backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;proto/connectrpc/eliza/v1/eliza.proto&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;connectrpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eliza.v1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;SayRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;sentence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;SayResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;sentence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;ElizaService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SayRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SayResponse&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;&lt;strong&gt;&lt;code&gt;proto/greet/v1/greet.proto&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;greet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"connectrpc/eliza/v1/eliza.proto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="c1"&gt;// This service mimics the remote service but is exposed locally&lt;/span&gt;
&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;GreetService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Say&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectrpc.eliza.v1.SayRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectrpc.eliza.v1.SayResponse&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;&lt;strong&gt;&lt;code&gt;buf.gen.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# 1. Generates Types AND Service Definitions (v2 Standard)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;plugin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;es&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./node_modules/.bin/protoc-gen-es&lt;/span&gt;
    &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gen&lt;/span&gt;
    &lt;span class="na"&gt;opt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target=ts&lt;/span&gt;

  &lt;span class="c1"&gt;# 2. Generates React Hooks (TanStack Query)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;plugin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;connect-query&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./node_modules/.bin/protoc-gen-connect-query&lt;/span&gt;
    &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gen&lt;/span&gt;
    &lt;span class="na"&gt;opt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target=ts&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Run the generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run generate

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. The Proxy Utility
&lt;/h2&gt;

&lt;p&gt;This utility dynamically implements a service definition by forwarding method calls to a target client. This allows us to "mount" the remote backend onto our local API route without manually rewriting every resolver.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/utils/proxy.ts&lt;/code&gt;&lt;/strong&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DescService&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;@bufbuild/protobuf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Client&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;@connectrpc/connect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createProxy&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DescService&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;)&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;implementation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;for &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;method&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methods&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;fnName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fnName&lt;/span&gt;&lt;span class="p"&gt;]&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[Proxy] Forwarding &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fnName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;typeName&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="c1"&gt;// Call the client dynamically&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="nx"&gt;fnName&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="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`[Proxy] Built methods for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;typeName&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;implementation&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;implementation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. API Route Implementation
&lt;/h2&gt;

&lt;p&gt;We create a backend connection to the demo Eliza service, then route our local &lt;code&gt;GreetService&lt;/code&gt; to proxy that connection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pages/api/[[...connect]].ts&lt;/code&gt;&lt;/strong&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;nextJsApiRouter&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;@connectrpc/connect-next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ConnectRouter&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;@connectrpc/connect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createClient&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;@connectrpc/connect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createConnectTransport&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;@connectrpc/connect-node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Generated Code&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GreetService&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;@/gen/greet/v1/greet_pb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ElizaService&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;@/gen/connectrpc/eliza/v1/eliza_pb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createProxy&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;@/src/utils/proxy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 1. The Backend Connection (Target)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elizaBackend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ElizaService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;createConnectTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://demo.connectrpc.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;httpVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.1&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="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConnectRouter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ---------------------------------------------------------&lt;/span&gt;
  &lt;span class="c1"&gt;// ROUTE 1: GreetService (Proxy -&amp;gt; ElizaService)&lt;/span&gt;
  &lt;span class="c1"&gt;// URL: /api/greet.v1.GreetService/Say&lt;/span&gt;
  &lt;span class="c1"&gt;// ---------------------------------------------------------&lt;/span&gt;
  &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GreetService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;createProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GreetService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;elizaBackend&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;nextJsApiRouter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;routes&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="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Client Consumption
&lt;/h2&gt;

&lt;p&gt;The frontend uses &lt;code&gt;connect-web&lt;/code&gt; to talk to the local Next.js API. Note that we are using the &lt;code&gt;GreetService&lt;/code&gt; definition here, but the data types (&lt;code&gt;sentence&lt;/code&gt;) are strictly typed to the original Eliza definition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;app/page.tsx&lt;/code&gt;&lt;/strong&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="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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&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;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMutation&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;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createClient&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;@connectrpc/connect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createConnectTransport&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;@connectrpc/connect-web&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GreetService&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;@/gen/greet/v1/greet_pb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Point to YOUR local API&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createConnectTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GreetService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;transport&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ChatPage&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;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHistory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;mutationFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Input is typed as SayRequest (from Eliza)&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;say&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="c1"&gt;// Output is typed as SayResponse (from Eliza)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;answer&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="nf"&gt;setHistory&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Eliza (via Proxy): &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;50px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sans-serif&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;gt;&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="nb"&gt;Proxy&lt;/span&gt; &lt;span class="nx"&gt;Chat&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10px&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;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
          &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&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;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Say something...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;flexGrow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sending...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Send&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;marginTop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;20px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#f5f5f5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;20px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8px&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;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;history&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;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;borderBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1px solid #ddd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8px 0&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;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;line&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;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;



</description>
      <category>nextjs</category>
      <category>proxy</category>
      <category>webdev</category>
      <category>gprc</category>
    </item>
    <item>
      <title>Understanding SSL/TLS Certificates</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Thu, 15 Jan 2026 05:47:38 +0000</pubDate>
      <link>https://dev.to/azadshukor/understanding-ssltls-certificates-3lb7</link>
      <guid>https://dev.to/azadshukor/understanding-ssltls-certificates-3lb7</guid>
      <description>&lt;h2&gt;
  
  
  The Name Game: SSL vs TLS
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SSL&lt;/strong&gt; (Secure Sockets Layer) and &lt;strong&gt;TLS&lt;/strong&gt; (Transport Layer Security) are often used interchangeably, but here's the reality: SSL is dead. It hasn't been updated since 1996 and is riddled with security vulnerabilities. Everything we use today is actually TLS.&lt;/p&gt;

&lt;p&gt;So why do we still hear "SSL" everywhere? Simple—it was the first name people learned, so the industry stuck with it for marketing. When you purchase an "SSL Certificate" today, you're actually getting a certificate that enables TLS.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does TLS Actually Do?
&lt;/h2&gt;

&lt;p&gt;Think of TLS as a secure tunnel between two computers. When you click "Proceed to Payment" on a website, TLS creates an encrypted tunnel to transmit your payment information to the payment processor (like Visa or Stripe). Without TLS, anyone could intercept and read that data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trust Problem: Certificate Authorities
&lt;/h2&gt;

&lt;p&gt;Here's the million-dollar question: how do you know the tunnel is actually secure and going to the right place? You need someone to verify the certificate's legitimacy—kind of like an immigration officer checking your passport at the border.&lt;/p&gt;

&lt;p&gt;In the TLS world, these "immigration officers" are called &lt;strong&gt;Certificate Authorities (CAs)&lt;/strong&gt;. Popular CAs include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's Encrypt&lt;/li&gt;
&lt;li&gt;Google Trust Services&lt;/li&gt;
&lt;li&gt;Cloudflare&lt;/li&gt;
&lt;li&gt;DigiCert&lt;/li&gt;
&lt;li&gt;GoDaddy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Works: The Certificate Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Generate the Certificate Signing Request (CSR)
&lt;/h3&gt;

&lt;p&gt;First, you generate a certificate locally or on your server. This creates two files:&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;# Generate a private key&lt;/span&gt;
openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; private.key 2048

&lt;span class="c"&gt;# Generate a CSR using the private key&lt;/span&gt;
openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; private.key &lt;span class="nt"&gt;-out&lt;/span&gt; certificate.csr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Private Key&lt;/strong&gt; (&lt;code&gt;private.key&lt;/code&gt;) - Keep this SECRET on your server, never share it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certificate Signing Request&lt;/strong&gt; (&lt;code&gt;certificate.csr&lt;/code&gt;) - Send this to the CA&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: CA Verification
&lt;/h3&gt;

&lt;p&gt;You submit your CSR to a Certificate Authority. They'll verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this a legitimate company?&lt;/li&gt;
&lt;li&gt;Do you actually own/control this domain?&lt;/li&gt;
&lt;li&gt;Is the information accurate?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For domain validation, the CA might ask you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a DNS record&lt;/li&gt;
&lt;li&gt;Upload a specific file to your website&lt;/li&gt;
&lt;li&gt;Respond to an email sent to your domain&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Receive the Signed Certificate
&lt;/h3&gt;

&lt;p&gt;After verification, the CA returns a signed certificate with their cryptographic signature. This is your "stamped passport."&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;# You'll receive something like this&lt;/span&gt;
certificate.crt  &lt;span class="c"&gt;# Your signed certificate&lt;/span&gt;
ca-bundle.crt    &lt;span class="c"&gt;# The CA's chain of trust&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Install on Your Server
&lt;/h3&gt;

&lt;p&gt;Now you configure your server to use both the private key and the signed certificate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example for Nginx:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/path/to/certificate.crt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/path/to/private.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Modern TLS configuration&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;on&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;Example for Apache:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nl"&gt;VirtualHost&lt;/span&gt;&lt;span class="sr"&gt; *:443&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="nc"&gt;ServerName&lt;/span&gt; yourdomain.com

    &lt;span class="nc"&gt;SSLEngine&lt;/span&gt; &lt;span class="ss"&gt;on&lt;/span&gt;
    &lt;span class="nc"&gt;SSLCertificateFile&lt;/span&gt; /path/to/certificate.crt
    &lt;span class="nc"&gt;SSLCertificateKeyFile&lt;/span&gt; /path/to/private.key
    &lt;span class="nc"&gt;SSLCertificateChainFile&lt;/span&gt; /path/to/ca-bundle.crt
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nl"&gt;VirtualHost&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Full Handshake (What Happens Behind the Scenes)
&lt;/h2&gt;

&lt;p&gt;When a user visits your site:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client Hello&lt;/strong&gt;: Browser says "Hey, I want to connect securely"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Hello&lt;/strong&gt;: Server responds with its certificate (the one signed by the CA)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certificate Verification&lt;/strong&gt;: Browser checks if the certificate is signed by a trusted CA&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Exchange&lt;/strong&gt;: They agree on encryption keys for the session&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypted Communication&lt;/strong&gt;: All data flows through the secure tunnel
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is what happens when you make an HTTPS request&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/payment&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&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="s1"&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="s1"&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="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;cardNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4242424242424242&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;99.99&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// TLS encrypts everything in that request body automatically&lt;/span&gt;
&lt;span class="c1"&gt;// Without TLS, anyone on the network could read your card number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why You Should Care
&lt;/h2&gt;

&lt;p&gt;Without TLS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Passwords sent in plain text&lt;/li&gt;
&lt;li&gt;❌ Credit cards visible to attackers&lt;/li&gt;
&lt;li&gt;❌ Session tokens can be stolen&lt;/li&gt;
&lt;li&gt;❌ Data can be modified in transit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With TLS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Everything encrypted end-to-end&lt;/li&gt;
&lt;li&gt;✅ Authenticity verified by CAs&lt;/li&gt;
&lt;li&gt;✅ Protection from man-in-the-middle attacks&lt;/li&gt;
&lt;li&gt;✅ That reassuring padlock in the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start with Let's Encrypt (Free!)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install Certbot&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx

&lt;span class="c"&gt;# Get a certificate and auto-configure Nginx&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; yourdomain.com &lt;span class="nt"&gt;-d&lt;/span&gt; www.yourdomain.com

&lt;span class="c"&gt;# Auto-renewal is set up automatically&lt;/span&gt;
&lt;span class="c"&gt;# Certificates are valid for 90 days&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You now have TLS up and running, and your users can browse safely through that secure tunnel.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What is display "block" and display "inline"?</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Sat, 10 Jan 2026 13:26:02 +0000</pubDate>
      <link>https://dev.to/azadshukor/what-is-display-block-and-display-inline-1mkm</link>
      <guid>https://dev.to/azadshukor/what-is-display-block-and-display-inline-1mkm</guid>
      <description>&lt;h2&gt;
  
  
  Phase 1: The "Why" (The Context)
&lt;/h2&gt;

&lt;p&gt;I am surprised when I put a &lt;code&gt;div&lt;/code&gt; and a &lt;code&gt;span&lt;/code&gt; side by side, and it isn't what I imagined. The &lt;code&gt;span&lt;/code&gt; doesn't behave exactly like a &lt;code&gt;div&lt;/code&gt;. You can't set the &lt;code&gt;width&lt;/code&gt; on a &lt;code&gt;span&lt;/code&gt; the same way you do on a &lt;code&gt;div&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you inspect the elements closely in your browser, you might notice they have different display properties: &lt;code&gt;div&lt;/code&gt; has &lt;code&gt;display: block&lt;/code&gt; and &lt;code&gt;span&lt;/code&gt; has &lt;code&gt;display: inline&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Does it really matter to understand this? Yes, it does. It is the DNA of the website. Without this, you are just guessing why your layout is breaking.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Phase 2: The Block Element
&lt;/h2&gt;

&lt;p&gt;The block element will take the whole row for himself. You can imagine it like building with Lego blocks that are always the same width as the floor. Even if you put a tiny bit of text inside a &lt;code&gt;div&lt;/code&gt;, that &lt;code&gt;div&lt;/code&gt; acts like a greedy person on a bus—he sits in the middle and puts his bags on the seats next to him so nobody else can sit there.&lt;/p&gt;

&lt;p&gt;Each block element will try to fit itself on its own row. If you put two &lt;code&gt;div&lt;/code&gt; tags in your code, the second one will always jump to the next line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The good part?&lt;/strong&gt; Because a block element is "solid," it listens to you. If you tell it to be &lt;code&gt;width: 200px&lt;/code&gt; or &lt;code&gt;height: 100px&lt;/code&gt;, it will obey. It respects your rules for margins and padding on all four sides.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 3: The Inline Element
&lt;/h2&gt;

&lt;p&gt;Now, look at the &lt;code&gt;inline&lt;/code&gt; element (like your &lt;code&gt;span&lt;/code&gt; or an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag). These are the "team players." They only take up as much space as they actually need. If the word is "Hello," the element is only as wide as those five letters.&lt;/p&gt;

&lt;p&gt;This is why they can sit side-by-side on the same line. They flow just like words in a sentence.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;The trap:&lt;/strong&gt; Beginners get frustrated here because &lt;code&gt;inline&lt;/code&gt; elements are stubborn. If you try to give a &lt;code&gt;span&lt;/code&gt; a &lt;code&gt;width&lt;/code&gt; of &lt;code&gt;500px&lt;/code&gt;, &lt;strong&gt;nothing happens.&lt;/strong&gt; The browser ignores you. It also acts weird with vertical space—if you give it a top margin, it won't push the other elements away like a &lt;code&gt;div&lt;/code&gt; would. It only cares about left and right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 4: The Middle Ground (Inline-Block)
&lt;/h2&gt;

&lt;p&gt;So what if you want the best of both worlds? You want elements to sit next to each other (inline), but you also want to control their width and height (block)?&lt;/p&gt;

&lt;p&gt;That’s where &lt;code&gt;display: inline-block&lt;/code&gt; comes in. It’s the "hybrid" setting. It stays on the same line as other elements, but it finally starts listening to your &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; commands.&lt;/p&gt;

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




&lt;h3&gt;
  
  
  Summary Table for your Memory:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Takes full width?&lt;/th&gt;
&lt;th&gt;Can set Width/Height?&lt;/th&gt;
&lt;th&gt;Sits next to others?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Block&lt;/strong&gt; (&lt;code&gt;div&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;h1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Inline&lt;/strong&gt; (&lt;code&gt;span&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inline-Block&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&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;Everything happens for a reason in CSS. Once you know if an element is a "greedy block" or a "flowing inline," you stop asking "what the hell is going on" and start actually building.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Simplest Chrome Extension Tutorial for 2024 Using Manifest V3</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Sun, 14 Jul 2024 00:41:51 +0000</pubDate>
      <link>https://dev.to/azadshukor/simplest-chrome-extension-tutorial-for-2024-using-manifest-v3-h3m</link>
      <guid>https://dev.to/azadshukor/simplest-chrome-extension-tutorial-for-2024-using-manifest-v3-h3m</guid>
      <description>&lt;h2&gt;
  
  
  Creating a Color Changer Chrome Extension
&lt;/h2&gt;

&lt;p&gt;This tutorial will guide you through creating a Chrome extension that changes the background color of web pages and keeps track of how many times the color has been changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Set Up the Folder Structure
&lt;/h3&gt;

&lt;p&gt;First, create a new folder for your extension with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-extension/
│
├── manifest.json
├── background.js
├── popup/
│   ├── popup.html
│   └── popup.js
└── content_scripts/
    └── content.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Create the Manifest File
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;manifest.json&lt;/code&gt; file is the heart of your Chrome extension. It tells Chrome about your extension, its capabilities, and the files it needs to function.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;manifest.json&lt;/code&gt; in the root of your extension folder with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "manifest_version": 3,
  "name": "Color Changer",
  "version": "1.0",
  "description": "Changes webpage background color",
  "permissions": ["activeTab", "storage"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["&amp;lt;all_urls&amp;gt;"],
      "js": ["content_scripts/content.js"]
    }
  ],
  "action": {
    "default_popup": "popup/popup.html"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;manifest_version&lt;/code&gt;: Specifies we're using Manifest V3, the latest version for Chrome extensions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permissions&lt;/code&gt;: Requests access to the active tab and storage API.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;background&lt;/code&gt;: Specifies the background script file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;content_scripts&lt;/code&gt;: Defines which script should be injected into web pages.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;action&lt;/code&gt;: Specifies the HTML file for the extension's popup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Create the Popup HTML
&lt;/h3&gt;

&lt;p&gt;Create a file named popup.html in the popup folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Color Changer&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
    body {
      width: 200px;
      padding: 10px;
    }
    button {
      width: 100%;
      padding: 5px;
      margin-bottom: 10px;
    }
  &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;button id="changeColor"&amp;gt;Change Color&amp;lt;/button&amp;gt;
  &amp;lt;p&amp;gt;Color changed &amp;lt;span id="count"&amp;gt;0&amp;lt;/span&amp;gt; times&amp;lt;/p&amp;gt;
  &amp;lt;script src="popup.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a simple popup with a button and a counter. I've added some basic CSS to improve the layout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Create the Popup JavaScript
&lt;/h3&gt;

&lt;p&gt;Create a file named popup.js in the popup folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.addEventListener('DOMContentLoaded', function() {
  var changeColor = document.getElementById('changeColor');
  var countSpan = document.getElementById('count');

  // Load the current count
  chrome.storage.sync.get('colorCount', function(data) {
    countSpan.textContent = data.colorCount || 0;
  });

  changeColor.addEventListener('click', function() {
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      chrome.tabs.sendMessage(tabs[0].id, {action: "changeColor"}, function(response) {
        console.log(response);
      });
    });

    // Increment the count
    chrome.storage.sync.get('colorCount', function(data) {
      var newCount = (data.colorCount || 0) + 1;
      chrome.storage.sync.set({colorCount: newCount});
      countSpan.textContent = newCount;
    });

    // Notify background script
    chrome.runtime.sendMessage({action: "colorChanged"});
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We wait for the DOM to load before attaching event listeners.&lt;/li&gt;
&lt;li&gt;We retrieve the current color change count from storage and display it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the button is clicked, we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send a message to the content script to change the page color.&lt;/li&gt;
&lt;li&gt;Increment the color change count and update it in storage and on the popup.&lt;/li&gt;
&lt;li&gt;Send a message to the background script to log the change.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Create the Background Script
&lt;/h3&gt;

&lt;p&gt;Create a file named background.js in the root of your extension folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.onInstalled.addListener(function() {
  chrome.storage.sync.set({colorCount: 0});
});

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.action === "colorChanged") {
      console.log("Background color was changed");
    }
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the extension is installed, we initialize the color count to 0.&lt;/li&gt;
&lt;li&gt;We listen for messages from other parts of the extension. When a "colorChanged" message is received, we log it to the console.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 6: Create the Content Script
&lt;/h3&gt;

&lt;p&gt;Create a file named content.js in the content_scripts folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.action === "changeColor") {
      document.body.style.backgroundColor = getRandomColor();
      sendResponse({status: "Color changed"});
    }
  }
);

function getRandomColor() {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i &amp;lt; 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This script listens for messages from the popup.&lt;/li&gt;
&lt;li&gt;When it receives a "changeColor" message, it changes the page's background color to a random color.&lt;/li&gt;
&lt;li&gt;The getRandomColor() function generates a random hex color code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 7: Load and Test the Extension
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open Chrome and go to chrome://extensions/&lt;/li&gt;
&lt;li&gt;Enable "Developer mode" in the top right corner.&lt;/li&gt;
&lt;li&gt;Click "Load unpacked" and select your extension folder.&lt;/li&gt;
&lt;li&gt;Your extension should now appear in the Chrome toolbar.&lt;/li&gt;
&lt;li&gt;Open any webpage and click on your extension icon.&lt;/li&gt;
&lt;li&gt;Click the "Change Color" button and observe:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The webpage's background color should change.&lt;br&gt;
The count in the popup should increment.&lt;br&gt;
Check the background script's console (in the extensions page) for the log message.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Displaying dev.to Articles in a React Project with TypeScript</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Fri, 30 Jun 2023 08:46:54 +0000</pubDate>
      <link>https://dev.to/azadshukor/displaying-devto-articles-in-a-react-project-with-typescript-16gf</link>
      <guid>https://dev.to/azadshukor/displaying-devto-articles-in-a-react-project-with-typescript-16gf</guid>
      <description>&lt;p&gt;Let's go through a step-by-step tutorial on how to display dev.to articles in your own React project using TypeScript. &lt;/p&gt;

&lt;p&gt;The following instructions will help you understand the process clearly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a React application
&lt;/h2&gt;

&lt;p&gt;To begin, create a new React application by running the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Set up the Article Interface
&lt;/h2&gt;

&lt;p&gt;In your App.js file, you'll need to define an interface that represents the structure of dev.to articles. Paste the following interface code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface IArticle {
  type_of: string;
  id: number;
  title: string;
  description: string;
  readable_publish_date: string;
  slug: string;
  path: string;
  url: string;
  comments_count: number;
  public_reactions_count: number;
  collection_id: null | number;
  published_timestamp: string;
  positive_reactions_count: number;
  cover_image: null | string;
  social_image: string;
  canonical_url: string;
  created_at: string;
  edited_at: null | string;
  crossposted_at: null | string;
  published_at: string;
  last_comment_at: string;
  reading_time_minutes: number;
  tag_list: string[];
  tags: string;
  user: {
    name: string;
    username: string;
    twitter_username: null | string;
    github_username: string;
    user_id: number;
    website_url: null | string;
    profile_image: string;
    profile_image_90: string;
  };
}

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

&lt;/div&gt;



&lt;p&gt;This interface represents the structure of dev.to articles that we'll be fetching and displaying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Fetch dev.to Articles
&lt;/h2&gt;

&lt;p&gt;Next, we'll create a function to fetch dev.to articles based on a given username. In this tutorial, we'll use the username "azadshukor" as an example. Paste the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fetchDevToArticles = (username: string): Promise&amp;lt;IArticle[]&amp;gt; =&amp;gt;
  fetch(`https://dev.to/api/articles?username=${username}`).then((response) =&amp;gt;
    response.json()
  );

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

&lt;/div&gt;



&lt;p&gt;The fetchDevToArticles function takes a username parameter and returns a Promise that resolves to an array of IArticle objects. It fetches the articles using the dev.to API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Fetch Articles from the Client Side
&lt;/h2&gt;

&lt;p&gt;Inside the App component, we'll use the useEffect hook to fetch the dev.to articles from the client side. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  fetchDevToArticles("azadshukor")
    .then((articles) =&amp;gt; {
      setBlogs(articles);
    })
    .catch((error) =&amp;gt; {
      console.error("Error fetching articles:", error);
    });
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will fetch the articles from the dev.to API using the fetchDevToArticles function we defined earlier. The fetched articles will be stored in the blogs state using the setBlogs function. The useEffect hook ensures that the articles are fetched only once when the component mounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Finalize the App Component
&lt;/h2&gt;

&lt;p&gt;Now, let's update the App.tsx file with the final code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from "react";
import "./styles.css";

interface IArticle {
  type_of: string;
  id: number;
  title: string;
  description: string;
  readable_publish_date: string;
  slug: string;
  path: string;
  url: string;
  comments_count: number;
  public_reactions_count: number;
  collection_id: null | number;
  published_timestamp: string;
  positive_reactions_count: number;
  cover_image: null | string;
  social_image: string;
  canonical_url: string;
  created_at: string;
  edited_at: null | string;
  crossposted_at: null | string;
  published_at: string;
  last_comment_at: string;
  reading_time_minutes: number;
  tag_list: string[];
  tags: string;
  user: {
    name: string;
    username: string;
    twitter_username: null | string;
    github_username: string;
    user_id: number;
    website_url: null | string;
    profile_image: string;
    profile_image_90: string;
  };
}

const fetchDevToArticles = (username: string): Promise&amp;lt;IArticle[]&amp;gt; =&amp;gt;
  fetch(`https://dev.to/api/articles?username=${username}`).then((response) =&amp;gt;
    response.json()
  );

export default function App() {
  const [blogs, setBlogs] = useState&amp;lt;IArticle[]&amp;gt;([]);

  useEffect(() =&amp;gt; {
    fetchDevToArticles("azadshukor")
      .then((articles) =&amp;gt; {
        setBlogs(articles);
      })
      .catch((error) =&amp;gt; {
        console.error("Error fetching articles:", error);
      });
  }, []);

  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;h1&amp;gt;Hello CodeSandbox&amp;lt;/h1&amp;gt;
      &amp;lt;h2&amp;gt;Start editing to see some magic happen!&amp;lt;/h2&amp;gt;
      {blogs.map((blog) =&amp;gt; (
        &amp;lt;div key={blog.id}&amp;gt;
          &amp;lt;h3&amp;gt;{blog.title}&amp;lt;/h3&amp;gt;
          &amp;lt;p&amp;gt;{blog.description}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;p&gt;This code imports the necessary dependencies, including the useEffect and useState hooks. The App component sets up the state for storing the fetched articles in the blogs variable. The fetched articles are then mapped over and displayed in the component's JSX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Test and Customize
&lt;/h2&gt;

&lt;p&gt;You can now test your application and see the dev.to articles being displayed in your React project. Feel free to customize the code to suit your specific needs.&lt;/p&gt;

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

&lt;p&gt;Congratulations! You have successfully implemented the functionality to display dev.to articles in your React project. I hope this tutorial has been helpful to you. If you have any further questions, feel free to leave a comment. Happy coding!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
    </item>
    <item>
      <title>Setting up Next.js 13 with Vitest</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Thu, 08 Jun 2023 02:57:13 +0000</pubDate>
      <link>https://dev.to/azadshukor/setting-up-nextjs-13-with-vitest-51ol</link>
      <guid>https://dev.to/azadshukor/setting-up-nextjs-13-with-vitest-51ol</guid>
      <description>&lt;p&gt;In this tutorial, we will demonstrate how to set up a Next.js 13 application with Vitest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before getting started, make sure you have the following installed on your machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Creating a Next.js application
&lt;/h2&gt;

&lt;p&gt;First, let's create a new Next.js application using the create-next-app command. Open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app my-app --yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a new Next.js application in the my-app directory. When prompted, choose No for TypeScript and No for the experimental app/ directory. Next, navigate to the project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up Vitest
&lt;/h2&gt;

&lt;p&gt;Now, we need to install Vitest as a dev dependency for our Next.js application. Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev vitest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the installation is complete, open the package.json file in your project and add a new script called "test" under the "scripts" section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "next lint",
  "test": "vitest"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have now configured the test script to run Vitest for our application.&lt;/p&gt;

&lt;p&gt;Next, create a configuration file called &lt;code&gt;vitest.config.js&lt;/code&gt; in the root directory of your project and paste the following code into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {},
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Test the setup
&lt;/h2&gt;

&lt;p&gt;To test if everything is set up correctly, create a new file named index.test.js in the root directory of your project and paste the following code into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { describe, expect, test } from "vitest";

const add = (a, b) =&amp;gt; {
  return a + b;
};

describe("test add function", () =&amp;gt; {
  test("should return the sum of two numbers", () =&amp;gt; {
    const result = add(2, 3);
    expect(result).toBe(5);
  });

  test("should return zero when adding zero to a number", () =&amp;gt; {
    const result = add(10, 0);
    expect(result).toBe(10);
  });

  test("should return a negative number when adding a negative and a positive number", () =&amp;gt; {
    const result = add(-5, 8);
    expect(result).toBe(3);
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run the tests, open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the test results displayed in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ index.test.js (3)

 Test Files  1 passed (1)
      Tests  3 passed (3)
   Start at  10:43:04
   Duration  414ms (transform 29ms, setup 0ms, collect 18ms, tests 6ms, environment 0ms, prepare 91ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>test</category>
      <category>nextjs</category>
      <category>vitest</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Link Your Google Domain with Vercel: A Step-by-Step Guide (2023)</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Thu, 27 Apr 2023 03:35:05 +0000</pubDate>
      <link>https://dev.to/azadshukor/how-to-link-your-google-domain-with-vercel-a-step-by-step-guide-2023-5ac9</link>
      <guid>https://dev.to/azadshukor/how-to-link-your-google-domain-with-vercel-a-step-by-step-guide-2023-5ac9</guid>
      <description>&lt;p&gt;Log in to your Google Domains account and navigate to the My Domains page. If you have multiple domains, make sure you select the one you want to link with Vercel.&lt;/p&gt;

&lt;p&gt;Click on the &lt;strong&gt;"Manage"&lt;/strong&gt; button on the right side of the domain name. This will take you to the domain management page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fi8ot8w4kfrpelplzdmi3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fi8ot8w4kfrpelplzdmi3.png" alt="manage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left sidebar, select &lt;strong&gt;"DNS"&lt;/strong&gt;. This will bring up the DNS settings for your domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F85hcrlxxpsgd95gi5aro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F85hcrlxxpsgd95gi5aro.png" alt="DNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;"Custom name servers"&lt;/strong&gt;. This will allow you to add custom name servers for your domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2bjj3vrflw9awweaz4i3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2bjj3vrflw9awweaz4i3.png" alt="Custom name servers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;"Name Server"&lt;/strong&gt;, add the following two name servers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ns1.vercel-dns.com
ns2.vercel-dns.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the name servers provided by Vercel, and they will handle the DNS requests for your domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbeh7edclr5bm56sezn09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbeh7edclr5bm56sezn09.png" alt="name servers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;"Save"&lt;/strong&gt; to save the changes. Once you've added the custom name servers, your Google domain will be linked with Vercel, and you can start using it to host your website or web application.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Setting up Next.js 13 with TypeScript-ESLint</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Wed, 12 Apr 2023 03:10:20 +0000</pubDate>
      <link>https://dev.to/azadshukor/setting-up-nextjs-13-with-typescript-eslint-47an</link>
      <guid>https://dev.to/azadshukor/setting-up-nextjs-13-with-typescript-eslint-47an</guid>
      <description>&lt;h2&gt;
  
  
  Step 1: Create a new Next.js project with TypeScript
&lt;/h2&gt;

&lt;p&gt;To create a new Next.js project with TypeScript, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app@latest --ts my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;my-app&lt;/code&gt; is the name of the project folder, and you can replace it with any name you prefer.&lt;/p&gt;

&lt;p&gt;During the creation process, you will be asked several questions. Here are the recommended answers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Would you like to use ESLint with this project? -&amp;gt; Yes
Which ESLint configuration would you like to use? -&amp;gt; Next.js (uses eslint-config-next)
Would you like to use Tailwind CSS? -&amp;gt; No
Would you like to use the src directory? -&amp;gt; No
Would you like to use the experimental app directory? -&amp;gt; Yes
What would you like to name the import alias? -&amp;gt; @/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a new Next.js project with TypeScript and the recommended configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Install TypeScript-ESLint as a dev dependency
&lt;/h2&gt;

&lt;p&gt;TypeScript-ESLint is a tool that integrates ESLint with TypeScript. To install it as a dev dependency, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install two packages: &lt;code&gt;@typescript-eslint/parser&lt;/code&gt;, which allows ESLint to understand TypeScript syntax, and &lt;code&gt;@typescript-eslint/eslint-plugin&lt;/code&gt;, which provides additional TypeScript-specific ESLint rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Configure ESLint for TypeScript
&lt;/h2&gt;

&lt;p&gt;ESLint uses a configuration file &lt;code&gt;(.eslintrc.json)&lt;/code&gt; to define the rules and plugins that should be used. Open this file and add the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "extends": [
    "next/core-web-vitals",
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint"],
  "root": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Test the integration
&lt;/h2&gt;

&lt;p&gt;To test the integration, open &lt;code&gt;pages/index.tsx&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Test = {};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code defines a new type called Test. If you save the file, you should see an error message in your editor, indicating that the code is not valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `object` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
- If you want a type meaning "empty object", you probably want `Record&amp;lt;string, never&amp;gt;` instead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error message confirms that TypeScript-ESLint is working correctly and is providing helpful feedback on your code.&lt;/p&gt;

&lt;p&gt;Congratulations! You have successfully integrated TypeScript-ESLint in Next.js. From now on, ESLint will check your TypeScript code and provide suggestions to improve its quality&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Setting up Next.js 13 with Prisma and SQLite</title>
      <dc:creator>Azad Shukor</dc:creator>
      <pubDate>Fri, 10 Mar 2023 03:00:57 +0000</pubDate>
      <link>https://dev.to/azadshukor/setting-up-nextjs-13-with-prisma-and-sqlite-1lld</link>
      <guid>https://dev.to/azadshukor/setting-up-nextjs-13-with-prisma-and-sqlite-1lld</guid>
      <description>&lt;p&gt;In this tutorial, we will demonstrate how to set up a &lt;code&gt;Next.js 13&lt;/code&gt; application with &lt;code&gt;Prisma&lt;/code&gt; as the ORM and &lt;code&gt;SQLite&lt;/code&gt; as the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Creating a Next.js application
&lt;/h2&gt;

&lt;p&gt;First, let's create a new Next.js application using the create-next-app command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app my-app --yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a new Next.js application in the my-app directory. When prompted, choose &lt;code&gt;No&lt;/code&gt; for &lt;code&gt;TypeScript&lt;/code&gt; and &lt;code&gt;No&lt;/code&gt; for the &lt;code&gt;experimental app/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Next, change into the project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Setting up SQLite
&lt;/h2&gt;

&lt;p&gt;To set up a SQLite database for our Next.js application, we need to install the sqlite3 package and create a new dev.db file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install sqlite3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Setting up Prisma
&lt;/h2&gt;

&lt;p&gt;Next, we need to install the Prisma and initialize a new Prisma project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install prisma --save-dev &amp;amp;&amp;amp; prisma init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will initialize a new Prisma project in our application directory. Then, we can paste the following code into the schema.prisma file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id    Int    @id @default(autoincrement())
  email String @unique
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to create &lt;code&gt;dev.db&lt;/code&gt; file inside prisma folder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd prisma
touch dev.db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Pushing the Prisma schema and starting the Prisma Studio
&lt;/h2&gt;

&lt;p&gt;Finally, we need to push our schema to the database and start the Prisma Studio to view the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prisma db push &amp;amp;&amp;amp; prisma studio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Congratulations, you have successfully set up a Next.js 13 application with Prisma as the ORM and SQLite as the database. You can now use Prisma to query the SQLite database in your Next.js application.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
