<?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: Emmanuel (Emmo00)</title>
    <description>The latest articles on DEV Community by Emmanuel (Emmo00) (@emmo00).</description>
    <link>https://dev.to/emmo00</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1376028%2Fde7adeef-631e-480c-90c1-de950ac02fa6.jpg</url>
      <title>DEV Community: Emmanuel (Emmo00)</title>
      <link>https://dev.to/emmo00</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emmo00"/>
    <language>en</language>
    <item>
      <title>Building x402 Clients on Celo: A Getting-Started Guide</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Wed, 22 Jul 2026 02:26:44 +0000</pubDate>
      <link>https://dev.to/emmo00/building-x402-clients-on-celo-a-getting-started-guide-578i</link>
      <guid>https://dev.to/emmo00/building-x402-clients-on-celo-a-getting-started-guide-578i</guid>
      <description>&lt;p&gt;&lt;em&gt;How to make your code (or your agent) pay an HTTP endpoint automatically by signing a stablecoin micropayment on Celo and retrieving the resource in a single flow.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is x402, from the client's side?
&lt;/h2&gt;

&lt;p&gt;x402 allows a program to pay for an HTTP resource the moment it needs it with no accounts, API keys, or credit cards on file. When you request a protected URL, the server responds with &lt;code&gt;402 Payment Required&lt;/code&gt; and explains how to pay. Your client signs a payment and retries the request to receive the data. For an autonomous agent, this means discovering a priced endpoint and paying a fraction of a cent for it without requiring a human to configure billing beforehand.&lt;/p&gt;

&lt;p&gt;This guide covers the &lt;strong&gt;client&lt;/strong&gt; side on &lt;strong&gt;Celo&lt;/strong&gt;, which offers cheap gas fees, fast finality, and widely held stablecoins like USDT and USDC. If you are building the endpoint itself, check out my companion guide, &lt;em&gt;&lt;a href="https://dev.to/emmo00/building-x402-servers-on-celo-a-getting-started-guide-498f"&gt;Building x402 Servers on Celo&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You send a &lt;code&gt;GET&lt;/code&gt; request to the protected URL. The server replies with an &lt;strong&gt;HTTP 402&lt;/strong&gt; status and a base64-encoded &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt; response header (along with an empty &lt;code&gt;{}&lt;/code&gt; body). Decoding the header reveals &lt;code&gt;{ x402Version, error, resource, accepts: [...] }&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;accepts[]&lt;/code&gt; array lists the payment options accepted by the server. Each item specifies a &lt;code&gt;{ scheme, network, amount, asset, payTo, maxTimeoutSeconds, extra }&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Your client &lt;strong&gt;selects one option&lt;/strong&gt;, signs an EIP-3009 authorization (a signed off-chain message rather than an on-chain transaction from your wallet), and retries the request including an &lt;code&gt;X-PAYMENT&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;A facilitator submits the transfer on-chain and pays the gas fee. You receive an &lt;strong&gt;HTTP 200&lt;/strong&gt; status along with a base64-encoded &lt;code&gt;PAYMENT-RESPONSE&lt;/code&gt; header containing the settlement transaction hash.&lt;/li&gt;
&lt;/ol&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6an43o876pc6zu4o5iiu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6an43o876pc6zu4o5iiu.png" alt="x402 Flow - Sequence Diagram" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 20 or higher.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;funded wallet&lt;/strong&gt; on Celo containing the stablecoin you plan to spend (such as Celo USDT). You do &lt;strong&gt;not&lt;/strong&gt; need native CELO for gas.&lt;/li&gt;
&lt;li&gt;Your wallet's private key provided via an &lt;strong&gt;environment variable&lt;/strong&gt; (never hardcoded in source code).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @x402/core @x402/evm @x402/fetch viem

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@x402/core&lt;/code&gt;: Provides the &lt;code&gt;x402Client&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@x402/evm&lt;/code&gt;: Provides the exact EVM scheme (&lt;code&gt;registerExactEvmScheme&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@x402/fetch&lt;/code&gt;: Provides &lt;code&gt;wrapFetchWithPayment&lt;/code&gt;, which converts standard &lt;code&gt;fetch&lt;/code&gt; into a payment-aware request handler.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;viem&lt;/code&gt;: Utility for generating a signer from a private key.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Inspect Before You Code
&lt;/h2&gt;

&lt;p&gt;Before writing client code, you can inspect an endpoint's exact configuration (including its &lt;code&gt;accepts[]&lt;/code&gt; array, supported networks, assets, and prices) using the &lt;strong&gt;x402 Inspector&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[https://x402-inspector.vercel.app/?url=](https://x402-inspector.vercel.app/?url=)&amp;lt;x402endpoint&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can point the inspector at the live &lt;strong&gt;Chess Puzzles API&lt;/strong&gt; on Celo as a working example (each call costs a fraction of a cent):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[https://x402-inspector.vercel.app/?url=https://api.chesspuzzles.xyz/puzzles?count=1](https://x402-inspector.vercel.app/?url=https://api.chesspuzzles.xyz/puzzles?count=1)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The inspector decodes the &lt;code&gt;402&lt;/code&gt; challenge and lets you make real payments directly from a browser wallet, making it the fastest way to understand and debug endpoints.&lt;/p&gt;




&lt;h2&gt;
  
  
  Celo Token Constants
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CELO_NETWORK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eip155:42220&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                                &lt;span class="c1"&gt;// CAIP-2 chain id&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CELO_USDT&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 6 decimals, EIP-3009 (proxy)&lt;/span&gt;
&lt;span class="c1"&gt;// USDT's EIP-712 domain: name = "Tether USD", version = "1"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;An endpoint's &lt;code&gt;accepts[]&lt;/code&gt; array often lists several options across different blockchains. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[0]&lt;/code&gt; Base USDC (&lt;code&gt;eip155:8453&lt;/code&gt;): &lt;strong&gt;The wrong chain for a Celo-only wallet.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[1]&lt;/code&gt; Celo USDC (&lt;code&gt;eip155:42220&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[2]&lt;/code&gt; Celo USDT (&lt;code&gt;eip155:42220&lt;/code&gt;, asset &lt;code&gt;0x48065…&lt;/code&gt;): Target this option if your wallet holds USDT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The single most important habit: &lt;strong&gt;always select the option matching the network and asset your wallet is actually funded with.&lt;/strong&gt; Do not assume &lt;code&gt;accepts[0]&lt;/code&gt; is the correct choice. Selecting the wrong network option is the primary reason funded wallets fail to settle payments.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Complete Client (Node + viem)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;privateKeyToAccount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;viem/accounts&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;x402Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@x402/core/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registerExactEvmScheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@x402/evm/exact/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;wrapFetchWithPayment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decodePaymentResponseHeader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@x402/fetch&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;CELO_NETWORK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eip155:42220&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;CELO_USDT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e&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;TARGET_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.chesspuzzles.xyz/puzzles?count=1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Read the key from the environment: never hardcode a private key.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AGENT_WALLET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;privateKey&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AGENT_WALLET env is required (0x-prefixed private key).&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&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="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;privateKeyToAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x&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="nx"&gt;privateKey&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`0x&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;privateKey&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;// Selector signature: (version, requirements) =&amp;gt; requirement.&lt;/span&gt;
&lt;span class="c1"&gt;// Prefer Celo USDT; fall back to any Celo option; last resort accepts[0].&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;selectCeloUsdt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requirements&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;usdt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&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;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;CELO_NETWORK&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;CELO_USDT&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;usdt&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&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;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;CELO_NETWORK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Decode the real error from the base64 PAYMENT-REQUIRED response header.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decodePaymentRequiredError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;payment-required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&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;decoded&lt;/span&gt; &lt;span class="o"&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// e.g. "insufficient_funds"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// CRITICAL: the selector goes in the x402Client CONSTRUCTOR (see Pitfall #1).&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;x402Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectCeloUsdt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;registerExactEvmScheme&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CELO_NETWORK&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;fetchWithPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrapFetchWithPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&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="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="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;`Paying &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;TARGET_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (Celo USDT)…`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Wrap in new URL(): a bare string can throw "Failed to parse URL" on Node 20+.&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="nf"&gt;fetchWithPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TARGET_URL&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="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&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;serverError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decodePaymentRequiredError&lt;/span&gt;&lt;span class="p"&gt;(&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`FAILED status=&lt;/span&gt;&lt;span class="p"&gt;${&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;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; serverError=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;serverError&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(none)&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&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="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decodePaymentResponseHeader&lt;/span&gt;&lt;span class="p"&gt;(&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;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;payment-response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="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;`SETTLED tx=&lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;settle&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;settle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(none)&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response:&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;})().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;THREW:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Run the client:&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="nv"&gt;AGENT_WALLET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0x... node pay-x402-celo.js https://api.chesspuzzles.xyz/puzzles?count&lt;span class="o"&gt;=&lt;/span&gt;1

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

&lt;/div&gt;



&lt;p&gt;On success, the script logs the settlement transaction hash. On failure, it outputs the decoded server error. This gives you a complete, functional x402 client on Celo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two Pitfalls That Cost Me Hours
&lt;/h2&gt;

&lt;p&gt;When I first implemented x402 on Celo, I encountered two subtle issues. Both presented as a properly funded wallet failing to pay, and both had non-obvious causes. Understanding these pitfalls will save you time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pitfall #1: The selector MUST be passed to the &lt;code&gt;x402Client&lt;/code&gt; constructor
&lt;/h3&gt;

&lt;p&gt;This bug causes a funded wallet to fail with an &lt;code&gt;insufficient_funds&lt;/code&gt; error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ BROKEN: The option is IGNORED, and the client defaults to accepts[0] (Base USDC).&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;x402Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;wrapFetchWithPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;paymentRequirementsSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;selectCeloUsdt&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ CORRECT: The selector explicitly controls which asset and network are paid.&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;x402Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectCeloUsdt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;wrapFetchWithPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the selector is ignored, the client attempts to pay &lt;code&gt;accepts[0]&lt;/code&gt;, which defaults to &lt;strong&gt;Base USDC on `eip155:8453&lt;/strong&gt;&lt;code&gt;. A Celo-only wallet holds no balance on Base, causing the facilitator to return &lt;/code&gt;insufficient_funds` even if your wallet holds Celo USDT. Adding more funds to Celo will not fix this; the solution is passing your selector directly to the &lt;strong&gt;constructor&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Note the function signature difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constructor / &lt;code&gt;x402HTTPClient&lt;/code&gt; signature: &lt;code&gt;(version, requirements) =&amp;gt; requirement&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;wrapFetchWithPayment&lt;/code&gt; options argument expects &lt;code&gt;(requirements)&lt;/code&gt;, but using this path can cause selection issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pitfall #2: Read the actual error from the &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt; header
&lt;/h3&gt;

&lt;p&gt;When a payment retry fails, the HTTP response body is usually an empty object &lt;code&gt;{}&lt;/code&gt;. The actual error details are stored inside the base64-encoded &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt; &lt;strong&gt;response&lt;/strong&gt; header. Always decode this header when debugging failures (the &lt;code&gt;decodePaymentRequiredError&lt;/code&gt; helper function above handles this).&lt;/p&gt;

&lt;p&gt;If you receive an unresolved &lt;code&gt;402&lt;/code&gt; with &lt;code&gt;error: "insufficient_funds"&lt;/code&gt;, treat it as a &lt;strong&gt;temporary failure&lt;/strong&gt; rather than a fatal error. It indicates the payment did not settle (due to network mismatches, empty balances, or temporary facilitator issues), and retrying later may succeed. If you are unsure, paste your endpoint into the inspector to compare decoded requirements with what your client selected:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[https://x402-inspector.vercel.app/?url=](https://x402-inspector.vercel.app/?url=)&amp;lt;x402endpoint&amp;gt;&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Other Gotchas Worth Knowing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node 20+ fetch handling:&lt;/strong&gt; Passing a raw string URL to wrapped fetch can throw a &lt;code&gt;Failed to parse URL&lt;/code&gt; error. Wrap string URLs using &lt;code&gt;new URL(TARGET_URL)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomic token units:&lt;/strong&gt; Celo USDT uses 6 decimal places, so &lt;code&gt;amount: "10000"&lt;/code&gt; represents &lt;code&gt;0.01 USDT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No CELO required for gas:&lt;/strong&gt; The facilitator covers transaction gas fees. Your wallet only needs sufficient stablecoin balances. You can verify token balances with &lt;code&gt;viem&lt;/code&gt; by querying &lt;code&gt;balanceOf&lt;/code&gt; and &lt;code&gt;decimals&lt;/code&gt; on the token contract at &lt;code&gt;[https://forno.celo.org](https://forno.celo.org)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object-style &lt;code&gt;asset&lt;/code&gt; declarations:&lt;/strong&gt; Some servers define &lt;code&gt;asset&lt;/code&gt; as an object &lt;code&gt;{ address, decimals, eip712: { name, version } }&lt;/code&gt; with empty &lt;code&gt;extra&lt;/code&gt; fields. The client library expects &lt;code&gt;asset&lt;/code&gt; to be a string address with EIP-712 parameters inside &lt;code&gt;extra&lt;/code&gt;. If signature generation fails to locate the domain, normalize each &lt;code&gt;accepts[]&lt;/code&gt; entry so &lt;code&gt;asset&lt;/code&gt; contains the address string and &lt;code&gt;extra&lt;/code&gt; contains &lt;code&gt;{ name, version }&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Paying from a Browser Wallet (ethers)
&lt;/h2&gt;

&lt;p&gt;The same client libraries function in browser environments; you simply adapt the signer to use an injected EIP-1193 wallet provider. The selection function must still be passed to the &lt;code&gt;x402Client&lt;/code&gt; constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;signTypedData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="k"&gt;delete&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;EIP712Domain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ethers rejects EIP712Domain&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ethersSigner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signTypedData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domain&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;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;readContract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* provider.call */&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;x402Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectRequirements&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// (version, options) =&amp;gt; option&lt;/span&gt;
&lt;span class="nf"&gt;registerExactEvmScheme&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signer&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;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;x402HTTPClient&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentRequired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPaymentRequiredResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parsedBody&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;payload&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPaymentPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paymentRequired&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;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encodePaymentSignatureHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// retry the original request with `headers` merged in&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Skip the Trial and Error: Grab the Skills
&lt;/h2&gt;

&lt;p&gt;To simplify client integration, I packaged my Celo x402 learnings into reusable agent skills. If you build with an AI coding assistant (such as Claude Code), you can install them directly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/Emmo00/agent-skills" rel="noopener noreferrer"&gt;https://github.com/Emmo00/agent-skills&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add emmo00/agent-skills

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

&lt;/div&gt;



&lt;p&gt;This library provides pre-configured skills for building x402 clients and servers on Celo, ensuring your development workflow automatically handles constructor selector placement, EIP-712 domains, and header error decoding.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to Go Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build the server side:&lt;/strong&gt; Read my companion guide, &lt;em&gt;&lt;a href="https://dev.to/emmo00/building-x402-servers-on-celo-a-getting-started-guide-498f"&gt;Building x402 Servers on Celo&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect endpoints:&lt;/strong&gt; Test endpoints using the &lt;a href="https://x402-inspector.vercel.app/" rel="noopener noreferrer"&gt;x402 Inspector&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference implementation:&lt;/strong&gt; Test your client against the live Chess Puzzles API on Celo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;x402 streamlines API access by replacing user registration, API keys, and credit cards with a single signed HTTP request. On Celo, low gas fees, widespread stablecoin adoption, and gasless user transactions provide an ideal environment for building autonomous client applications.&lt;/p&gt;

</description>
      <category>x402</category>
      <category>celo</category>
      <category>agentskills</category>
    </item>
    <item>
      <title>Building x402 Servers on Celo: A Getting-Started Guide</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Wed, 22 Jul 2026 02:18:47 +0000</pubDate>
      <link>https://dev.to/emmo00/building-x402-servers-on-celo-a-getting-started-guide-498f</link>
      <guid>https://dev.to/emmo00/building-x402-servers-on-celo-a-getting-started-guide-498f</guid>
      <description>&lt;p&gt;&lt;em&gt;How to put an HTTP endpoint behind a stablecoin paywall so any agent can pay per request with no accounts, API keys, or invoices.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is x402?
&lt;/h2&gt;

&lt;p&gt;x402 revives the long-dormant HTTP &lt;code&gt;402 Payment Required&lt;/code&gt; status code and turns it into a real payment protocol. The concept is simple: a client requests a protected resource, the server replies that payment is required with instructions on how to pay, the client signs a payment and retries, and the server returns the requested resource.&lt;/p&gt;

&lt;p&gt;There are no signups, API keys, or monthly subscriptions. A single HTTP request becomes an instant paid transaction.&lt;/p&gt;

&lt;p&gt;An autonomous agent can discover a priced endpoint, pay a fraction of a cent, and retrieve its data, all without a human needing to create an account first.&lt;/p&gt;

&lt;p&gt;This guide walks you through building the &lt;strong&gt;server&lt;/strong&gt; side on &lt;strong&gt;Celo&lt;/strong&gt;, where transactions are fast, cheap, and stablecoins (such as USDT and USDC) are widely used. If you want to build the paying side, check out my companion guide, &lt;em&gt;&lt;a href="https://dev.to/emmo00/building-x402-clients-on-celo-a-getting-started-guide-578i"&gt;Building x402 Clients on Celo&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Mental Model
&lt;/h2&gt;

&lt;p&gt;An x402 server handles three main steps on any protected route:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Challenge:&lt;/strong&gt; If a request arrives without a valid payment, respond with a &lt;code&gt;402&lt;/code&gt; status code and a &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt; header. The decoded JSON header contains an &lt;code&gt;accepts[]&lt;/code&gt; array listing the payment options you accept, including the network, asset, price, and your receiving wallet address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify &amp;amp; Settle:&lt;/strong&gt; If the request includes a signed payment in the &lt;code&gt;X-PAYMENT&lt;/code&gt; header, verify it and settle it through a &lt;strong&gt;facilitator&lt;/strong&gt; (a service that submits the on-chain transfer and pays the network gas fee). On success, run your real route handler and return a &lt;code&gt;PAYMENT-RESPONSE&lt;/code&gt; header with the settlement transaction hash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run it through middleware:&lt;/strong&gt; You do not need to build this payment flow from scratch. The &lt;code&gt;@x402/express&lt;/code&gt; package provides &lt;code&gt;paymentMiddleware&lt;/code&gt; that handles challenge, verification, and settlement automatically. You simply provide a map of routes to &lt;code&gt;accepts[]&lt;/code&gt; options and a resource server that routes network requests to the correct facilitator.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Your server never holds the payer's private key and never pays gas fees. The facilitator handles all on-chain work, while your wallet simply acts as the &lt;code&gt;payTo&lt;/code&gt; recipient address.&lt;/p&gt;
&lt;/blockquote&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx71qcce2dfov1zibjirl.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx71qcce2dfov1zibjirl.png" alt="x402 Flow - Sequence Diagram" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 20 or higher running an Express app.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;receiving wallet address&lt;/strong&gt; on Celo (this is your &lt;code&gt;payTo&lt;/code&gt; address that collects payments; it does not sign transactions).&lt;/li&gt;
&lt;li&gt;Access to a &lt;strong&gt;Celo facilitator&lt;/strong&gt; (an HTTP facilitator URL and API key). Celo's ecosystem provides these, or you can self-host &lt;code&gt;x402-rs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @x402/express @x402/evm @x402/core @coinbase/cdp-sdk

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@x402/express&lt;/code&gt;: Handles &lt;code&gt;paymentMiddleware&lt;/code&gt; and &lt;code&gt;x402ResourceServer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@x402/evm&lt;/code&gt;: Provides &lt;code&gt;ExactEvmScheme&lt;/code&gt; for exact-amount payments on EVM-compatible chains.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@x402/core&lt;/code&gt;: Provides &lt;code&gt;HTTPFacilitatorClient&lt;/code&gt; for self-hosted or third-party facilitators.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@coinbase/cdp-sdk&lt;/code&gt;: (Optional) Required only if you also want to accept Base USDC via Coinbase's hosted facilitator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are using TypeScript and these packages lack built-in type definitions, add a small declaration file to keep your compiler happy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// x402-shims.d.ts&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@x402/express&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;const&lt;/span&gt; &lt;span class="nx"&gt;paymentMiddleware&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x402ResourceServer&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="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@x402/evm/exact/server&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;const&lt;/span&gt; &lt;span class="nx"&gt;ExactEvmScheme&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="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@x402/core/server&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;const&lt;/span&gt; &lt;span class="nx"&gt;HTTPFacilitatorClient&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="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@coinbase/cdp-sdk/x402&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;const&lt;/span&gt; &lt;span class="nx"&gt;createCdpFacilitatorClient&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="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 1: Connect Your Facilitators
&lt;/h2&gt;

&lt;p&gt;Each blockchain network requires a facilitator to verify and settle payments. Celo uses an HTTP facilitator configured via URL. If you also choose to accept USDC on Base, you can use Coinbase's hosted CDP facilitator.&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;HTTPFacilitatorClient&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;@x402/core/server&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;createCdpFacilitatorClient&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;@coinbase/cdp-sdk/x402&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Celo (eip155:42220): third-party or self-hosted HTTP facilitator using an API key&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;celoFacilitatorClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HTTPFacilitatorClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;X402_CELO_FACILITATOR_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createAuthHeaders&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;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-API-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CELO_FACILITATOR_API_KEY&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;settle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;supported&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Base (eip155:8453): optional Coinbase-hosted facilitator (reads CDP creds from env)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseFacilitatorClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCdpFacilitatorClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Keep all sensitive credentials (API keys, CDP credentials, and wallet addresses) inside environment variables rather than your codebase. Additionally, wrap your payment setup in a configuration check so a misconfigured server returns a helpful error instead of crashing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Go to &lt;a href="https://x402.celo.org/" rel="noopener noreferrer"&gt;x402.celo.org&lt;/a&gt; to get a Celo x402 facilitator URL and API key.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;X402_PAY_TO_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;payTo&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;X402_CELO_FACILITATOR_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CELO_FACILITATOR_API_KEY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x402 payment endpoint is not configured on this server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Declare What You Accept
&lt;/h2&gt;

&lt;p&gt;The core of your server setup is a mapping from route paths to an &lt;code&gt;accepts[]&lt;/code&gt; array, paired with a resource server that routes each network to its corresponding facilitator.&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;paymentMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x402ResourceServer&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;@x402/express&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;ExactEvmScheme&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;@x402/evm/exact/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Dynamic price: compute atomic units for this request.&lt;/span&gt;
&lt;span class="c1"&gt;// All these stablecoins use 6 decimals, so $0.10 = 100,000 atomic units.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;units&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRequestedUnits&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="c1"&gt;// your per-request quantity&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usd&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;units&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;PRICE_PER_UNIT_USD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// e.g., 0.10 * count&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;atomic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e6&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;     &lt;span class="c1"&gt;// "100000"&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;paymentMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET /&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;accepts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// Base USDC: human-readable price strings work fine for the CDP facilitator&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;formatUsd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usd&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eip155:8453&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payTo&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;

        &lt;span class="c1"&gt;// Celo USDC: MUST use the flat wire shape (see Pitfall #1)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&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="nx"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xcEBA9300f2b948710d2653dD7B07f33A8B32118C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USDC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&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;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eip155:42220&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;payTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;

        &lt;span class="c1"&gt;// Celo USDT: flat wire shape with the correct EIP-712 domain&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&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="nx"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tether USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&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&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;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eip155:42220&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;payTo&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="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your resource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;mimeType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;x402ResourceServer&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;baseFacilitatorClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;celoFacilitatorClient&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eip155:8453&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ExactEvmScheme&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eip155:42220&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ExactEvmScheme&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Offering multiple options in &lt;code&gt;accepts[]&lt;/code&gt; allows callers to pay using whichever stablecoin they hold. The client chooses one option, and your resource server delegates settlement to the registered facilitator for that network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Celo Token Constants
&lt;/h3&gt;

&lt;p&gt;Copy these exact contract addresses and EIP-712 domain parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Celo USDT:&lt;/strong&gt; &lt;code&gt;0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e&lt;/code&gt; | &lt;code&gt;extra: { name: "Tether USD", version: "1" }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Celo USDC:&lt;/strong&gt; &lt;code&gt;0xcEBA9300f2b948710d2653dD7B07f33A8B32118C&lt;/code&gt; | &lt;code&gt;extra: { name: "USDC", version: "2" }&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; The &lt;code&gt;extra.name&lt;/code&gt; and &lt;code&gt;extra.version&lt;/code&gt; fields must match the token's on-chain EIP-712 &lt;code&gt;DOMAIN_SEPARATOR&lt;/code&gt; exactly. If they differ, payment signatures will fail to recover, causing settlement errors. Note that Celo USDT is a proxy contract whose domain version is &lt;code&gt;"1"&lt;/code&gt;, not &lt;code&gt;"2"&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Two Pitfalls That Cost Me Hours
&lt;/h2&gt;

&lt;p&gt;When I first implemented x402 on Celo, two subtle issues caused unexpected errors. Reviewing them now will save you debugging time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pitfall #1: The Celo facilitator requires a flat wire shape
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;x402-rs&lt;/code&gt; facilitator expects the &lt;code&gt;asset&lt;/code&gt; field to be a plain string address, with EIP-712 domain details placed in &lt;code&gt;extra&lt;/code&gt;. Passing an object-style asset causes the facilitator to reject the transaction with an &lt;code&gt;invalid_format&lt;/code&gt; error, even if the 402 challenge looks correct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ REJECTED by the Celo facilitator (invalid_format)&lt;/span&gt;
&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x4806…&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eip712&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tether USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;version&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&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="c1"&gt;// ✅ ACCEPTED: flat string asset + domain in extra&lt;/span&gt;
&lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tether USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&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&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Declare the &lt;code&gt;AssetAmount&lt;/code&gt; explicitly with a string &lt;code&gt;amount&lt;/code&gt; in atomic units. Avoid passing raw price strings like &lt;code&gt;"$0.10"&lt;/code&gt; directly for Celo; calculate the atomic integer value beforehand to ensure clarity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pitfall #2: Calculating price per request in atomic units
&lt;/h3&gt;

&lt;p&gt;If your API charges by usage quantity (such as item counts or data size), calculate the price inside the request middleware rather than globally at startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unitPriceUsd&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;X402_PRICE_USD_PER_UNIT&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isFinite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// safe default&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Standard stablecoins like USDC and USDT on Celo use 6 decimals, meaning $1.00 equals 1,000,000 atomic units (&lt;code&gt;usd * 1e6&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Always configure prices via environment variables with a safe fallback value to prevent accidental zero-pricing.&lt;/li&gt;
&lt;li&gt;Pass the calculated atomic &lt;code&gt;amount&lt;/code&gt; into every entry in your &lt;code&gt;accepts[]&lt;/code&gt; array.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Mount this combined logic on your Express routes after standard parameter validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/resource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validateParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x402Middleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resourceRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Make Your Paywall Discoverable to AI Agents
&lt;/h2&gt;

&lt;p&gt;Autonomous agents read API documentation to determine how to pay. You can make your server agent-friendly by publishing a &lt;code&gt;GET /llms.txt&lt;/code&gt; file that outlines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The authentication flow (&lt;code&gt;402&lt;/code&gt; response -&amp;gt; decode &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt; header -&amp;gt; sign -&amp;gt; retry with &lt;code&gt;X-PAYMENT&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The header requirement structure (noting that the response body remains empty &lt;code&gt;{}&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Supported networks, stablecoin assets, and atomic unit calculations.&lt;/li&gt;
&lt;li&gt;Your expected request parameters and response schemas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Providing machine-readable documentation enables AI agents to pay and access your API automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test and Debug Your Endpoint
&lt;/h2&gt;

&lt;p&gt;Once your server is running, test it using the &lt;strong&gt;x402 Inspector&lt;/strong&gt;. This tool decodes your &lt;code&gt;402&lt;/code&gt; challenge, displays the &lt;code&gt;accepts[]&lt;/code&gt; array, and allows you to execute end-to-end test payments from a browser wallet:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[https://x402-inspector.vercel.app/?url=](https://x402-inspector.vercel.app/?url=)&amp;lt;your-endpoint-url&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For a working reference implementation, inspect and query the live &lt;strong&gt;Chess Puzzles API&lt;/strong&gt; on Celo:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[https://x402-inspector.vercel.app/?url=https://api.chesspuzzles.xyz/puzzles?count=1](https://x402-inspector.vercel.app/?url=https://api.chesspuzzles.xyz/puzzles?count=1)&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Skip the Trial and Error: Grab the Skills
&lt;/h2&gt;

&lt;p&gt;To simplify integration, I packaged my Celo x402 learnings into reusable agent skills. If you use an AI coding assistant (such as Claude Code), you can install them directly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/Emmo00/agent-skills" rel="noopener noreferrer"&gt;https://github.com/Emmo00/agent-skills&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add emmo00/agent-skills

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

&lt;/div&gt;



&lt;p&gt;This library provides pre-configured skills for building x402 servers and clients on Celo, ensuring your development environment automatically handles flat wire shapes, EIP-712 domains, and facilitator client setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to Go Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build the paying client:&lt;/strong&gt; Read my companion guide, &lt;em&gt;&lt;a href="https://dev.to/emmo00/building-x402-clients-on-celo-a-getting-started-guide-578i"&gt;Building x402 Clients on Celo&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect endpoints:&lt;/strong&gt; Test your setup using the &lt;a href="https://x402-inspector.vercel.app/" rel="noopener noreferrer"&gt;x402 Inspector&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference code:&lt;/strong&gt; Test against the live Chess Puzzles API on Celo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;x402 streamlines API monetization by replacing complex signup forms and key management with instant signed HTTP payments. Combined with Celo's fast block times and low transaction costs, it offers a seamless way to monetize services for human users and AI agents alike.&lt;/p&gt;

</description>
      <category>x402</category>
      <category>celo</category>
      <category>agentskills</category>
    </item>
    <item>
      <title>How to Use Claude Code and OpenAI Codex for Free with FreeModel.dev</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Sun, 28 Jun 2026 16:04:11 +0000</pubDate>
      <link>https://dev.to/emmo00/how-to-use-claude-code-and-openai-codex-for-free-with-freemodeldev-2e9b</link>
      <guid>https://dev.to/emmo00/how-to-use-claude-code-and-openai-codex-for-free-with-freemodeldev-2e9b</guid>
      <description>&lt;p&gt;If you've wanted to use &lt;strong&gt;Claude Code&lt;/strong&gt; or &lt;strong&gt;OpenAI Codex&lt;/strong&gt; without paying for expensive API usage, &lt;strong&gt;FreeModel.dev&lt;/strong&gt; provides an easy way to do it. You simply create an account, generate an API key, and point the official CLI tools to FreeModel's API endpoint.&lt;/p&gt;

&lt;p&gt;As a bonus, if you sign up using my referral link, &lt;strong&gt;both of us receive $10 in API credits&lt;/strong&gt; after you verify your account.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Sign up here:&lt;/strong&gt; &lt;a href="https://freemodel.dev/invite/FRE-0b7baf97" rel="noopener noreferrer"&gt;https://freemodel.dev/invite/FRE-0b7baf97&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use FreeModel.dev?
&lt;/h2&gt;

&lt;p&gt;FreeModel.dev acts as an API provider compatible with official AI developer tools, allowing you to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code&lt;/li&gt;
&lt;li&gt;OpenAI Codex CLI&lt;/li&gt;
&lt;li&gt;VS Code extensions&lt;/li&gt;
&lt;li&gt;Your own applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of paying immediately for API usage, new users can receive free credits through referrals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Referral Bonus
&lt;/h3&gt;

&lt;p&gt;When you create an account through my referral link and verify your account via &lt;strong&gt;phone or Telegram&lt;/strong&gt;, both of us receive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎁 &lt;strong&gt;$10 in API credits&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ No expiration&lt;/li&gt;
&lt;li&gt;✅ No limit on referrals&lt;/li&gt;
&lt;li&gt;✅ Works with any email provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Referral link:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://freemodel.dev/invite/FRE-0b7baf97" rel="noopener noreferrer"&gt;https://freemodel.dev/invite/FRE-0b7baf97&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Credits are usually added within about a minute after verification.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installing Claude Code
&lt;/h2&gt;

&lt;p&gt;The setup uses the &lt;strong&gt;official Anthropic Claude Code CLI&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Git Bash (Windows)
&lt;/h3&gt;

&lt;p&gt;Git Bash is recommended because it handles paths and shell commands more reliably than Command Prompt.&lt;/p&gt;

&lt;p&gt;Download Git for Windows and install it using the default options.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2: Install Node.js
&lt;/h3&gt;

&lt;p&gt;Claude Code requires &lt;strong&gt;Node.js 18 or newer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Verify your version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your version is below 18, install the latest LTS release from Node.js.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Create a FreeModel API Key
&lt;/h3&gt;

&lt;p&gt;After signing into FreeModel:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;API Keys&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Give it a name&lt;/li&gt;
&lt;li&gt;Copy the key somewhere safe&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Treat this key like a password.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Install Claude Code
&lt;/h3&gt;

&lt;p&gt;Install the official CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart your terminal afterwards.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 5: Configure Claude
&lt;/h3&gt;

&lt;p&gt;Create the file:&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="err"&gt;C:\Users\&amp;lt;your-user&amp;gt;\.claude\settings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;.claude&lt;/code&gt; folder doesn't exist, simply run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;once, then close it.&lt;/p&gt;

&lt;p&gt;Now create &lt;code&gt;settings.json&lt;/code&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;"env"&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;"ANTHROPIC_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cc.freemodel.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;"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC"&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"&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;"permissions"&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;"allow"&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;"deny"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"apiKeyHelper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo 'YOUR_API_KEY'"&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;p&gt;Replace both instances of:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;with your actual FreeModel API key.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 6: Launch Claude
&lt;/h3&gt;

&lt;p&gt;Restart your terminal and run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If everything is configured correctly, you'll see the Claude Code welcome screen and can start chatting with Claude immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installing OpenAI Codex
&lt;/h2&gt;

&lt;p&gt;FreeModel also supports the &lt;strong&gt;official OpenAI Codex CLI&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 1: Install Codex
&lt;/h3&gt;

&lt;p&gt;Install using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @openai/codex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;codex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 2: Create the Configuration Directory
&lt;/h3&gt;

&lt;p&gt;Delete any previous configuration and recreate it.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Remove-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Recurse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;~\.codex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ErrorAction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SilentlyContinue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;~\.codex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 3: Create an API Key
&lt;/h3&gt;

&lt;p&gt;Generate an API key inside your FreeModel dashboard.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Create auth.json
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\Users\&amp;lt;your-user&amp;gt;\.codex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create:&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;"OPENAI_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_API_KEY"&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;p&gt;Replace &lt;code&gt;YOUR_API_KEY&lt;/code&gt; with your key.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 5: Create config.toml
&lt;/h3&gt;

&lt;p&gt;In the same folder, create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;model_provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"freemodel"&lt;/span&gt;
&lt;span class="py"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"gpt-5.5"&lt;/span&gt;
&lt;span class="py"&gt;model_reasoning_effort&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"xhigh"&lt;/span&gt;
&lt;span class="py"&gt;disable_response_storage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;preferred_auth_method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"apikey"&lt;/span&gt;

&lt;span class="nn"&gt;[model_providers.freemodel]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"freemodel"&lt;/span&gt;
&lt;span class="py"&gt;base_url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://api.freemodel.dev"&lt;/span&gt;
&lt;span class="py"&gt;wire_api&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"responses"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 6: Verify Installation
&lt;/h3&gt;

&lt;p&gt;Restart your terminal.&lt;/p&gt;

&lt;p&gt;Check that Codex is installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex &lt;span class="nt"&gt;-V&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see a version number, you're ready.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 7: Start Coding
&lt;/h3&gt;

&lt;p&gt;Navigate into your project:&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="nb"&gt;cd &lt;/span&gt;your-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch Codex:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;You can also use the official VS Code extension.&lt;/p&gt;




&lt;h2&gt;
  
  
  Updating Claude Code
&lt;/h2&gt;

&lt;p&gt;To update to the latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Uninstalling Claude Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm uninstall &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/.claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nv"&gt;%USERPROFILE%&lt;/span&gt;\.claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to remove your configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude won't start
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ensure Node.js is version 18+&lt;/li&gt;
&lt;li&gt;Confirm your API key is correct&lt;/li&gt;
&lt;li&gt;Make sure &lt;code&gt;settings.json&lt;/code&gt; is inside the &lt;code&gt;.claude&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;Restart your terminal after editing configuration files&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Codex isn't using FreeModel
&lt;/h3&gt;

&lt;p&gt;Double-check that &lt;code&gt;config.toml&lt;/code&gt; contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;base_url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://api.freemodel.dev"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that &lt;code&gt;auth.json&lt;/code&gt; contains your API key.&lt;/p&gt;




&lt;h2&gt;
  
  
  Earn More Free Credits
&lt;/h2&gt;

&lt;p&gt;FreeModel's referral program has &lt;strong&gt;no referral limit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every verified friend earns both of you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;$10 API credits&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Credits never expire&lt;/li&gt;
&lt;li&gt;Works with any email provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use my referral link to get started:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://freemodel.dev/invite/FRE-0b7baf97" rel="noopener noreferrer"&gt;https://freemodel.dev/invite/FRE-0b7baf97&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you've verified your account, you'll receive your credits and can begin using Claude Code or Codex without paying upfront.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>codex</category>
      <category>free</category>
    </item>
    <item>
      <title>🚀 From Student to Web3 Builder: My Journey, My Project, and Why It Matters</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Fri, 25 Apr 2025 04:22:05 +0000</pubDate>
      <link>https://dev.to/emmo00/from-student-to-web3-builder-my-journey-my-project-and-why-it-matters-18b2</link>
      <guid>https://dev.to/emmo00/from-student-to-web3-builder-my-journey-my-project-and-why-it-matters-18b2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Hi, I’m Emmanuel Nwafor&lt;/strong&gt;, a computer science student at the University of Nigeria, Nsukka — and a curious mind who fell in love with software development. Like &lt;em&gt;not&lt;/em&gt; many others, I started with the basics of back-end development — arguably the best way to begin a software engineering journey — and eventually dabbled in other areas of tech.&lt;br&gt;&lt;br&gt;
&lt;em&gt;[I also wanted to be a writer, so I hope you enjoy this piece].&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I remember when I built my first API server with Node.js — that was when I realized I’d actually found something I liked doing. For once, I wasn’t overthinking my crush at the time. Turns out, &lt;em&gt;I wasn’t sad, or lonely, or ugly😐 — I just needed to build.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well, enough of the self-glazing 😅. Let’s talk about something else.&lt;/p&gt;




&lt;h3&gt;
  
  
  🌐 Why I Chose Web3
&lt;/h3&gt;

&lt;p&gt;What pulled me into Web3 wasn’t just the buzz or the promise of pay that overwhelmingly surpassed what I was already making as a back-end web developer 👀.&lt;/p&gt;

&lt;p&gt;I wanted to build cool stuff &lt;em&gt;while creating ✨impact✨&lt;/em&gt;, and I feel Web3 provides a certain liberty for that. &lt;strong&gt;Impact&lt;/strong&gt; is the keyword — and in my opinion, that’s what all of us ultimately want to make. Web3 enables individuals to create things that &lt;em&gt;don’t need approval to exist&lt;/em&gt; and &lt;em&gt;can’t be switched off by gatekeepers&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;[we might still be cooked in Web3 if one of these gatekeepers decides to switch off their servers, but we move &lt;a href="https://www.reddit.com/r/CryptoCurrency/comments/vziazb/more_than_50_of_ethereum_is_hosted_on_amazons_aws" rel="noopener noreferrer"&gt;#ReditIsTheOnlySourceOfTruth&lt;/a&gt;]&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So far, so good. It’s been an interesting ride — full of learning, for sure.&lt;br&gt;&lt;br&gt;
&lt;em&gt;[The amount of new vocabulary I had to learn just to grasp beginner-level blockchain concepts is alarming 🫠].&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 Learning from the Cipher Session
&lt;/h3&gt;

&lt;p&gt;This journey accelerated when I joined the &lt;strong&gt;B&amp;lt;&amp;gt;rder/ess &amp;lt;&amp;gt; Metis Cipher Session&lt;/strong&gt;, a mind-stretching experience hosted by &lt;em&gt;[you guessed it]&lt;/em&gt; the B&amp;lt;&amp;gt;rder/ess team in collaboration with Metis and KarlaGod.&lt;/p&gt;

&lt;p&gt;Here are some highlights of what I picked up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Full-stack Solidity development skills&lt;/strong&gt; — &lt;em&gt;[Imagine if this wasn’t on the list 🙂]&lt;/em&gt;&lt;br&gt;&lt;br&gt;
We covered everything from smart contracts to front-end interactions. &lt;em&gt;[Safe to say, I can add Solidity to my LinkedIn profile]&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to actually make money as a developer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Our tutor didn’t just focus on the tech — we also got real-world advice on how to monetize our skills, navigate the ecosystem, and think like builders, not just coders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clarity on the Web3 landscape, from KarlaGod herself🫡&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Karla gave us the &lt;em&gt;real&lt;/em&gt; sauce — how the space works, why community matters, and how to market your project and get funded. Step-by-step clarity. &lt;em&gt;[I can't make this stuff up]&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔨 What I’m Building: [Blockchain-powered verification system that ensures transparent, tamper-proof records of land ownership (BPVSTETTPROLO)]
&lt;/h3&gt;

&lt;p&gt;My project is called ✨&lt;strong&gt;LandRegistry&lt;/strong&gt;✨ — a decentralized app that leverages blockchain technology to provide secure, transparent, and efficient land ownership verification.&lt;br&gt;&lt;br&gt;
👉 &lt;a href="https://land-registry-dapp-tau.vercel.app" rel="noopener noreferrer"&gt;Check it out&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The problem:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Land ownership disputes are &lt;em&gt;way too common&lt;/em&gt; — especially in regions where records are handwritten, scattered across multiple offices, or worse, mysteriously “missing.”&lt;br&gt;&lt;br&gt;
People lose properties, get scammed, or spend years in court because a piece of paper said one thing, and some government staff or “land agent” said another.&lt;br&gt;&lt;br&gt;
The lack of a reliable, tamper-proof record system means trust is low, fraud is high, and verification is expensive, slow, and largely opaque.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The solution:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;LandRegistry&lt;/strong&gt; stores land ownership records directly on the blockchain — publicly verifiable, immutable, and timestamped.&lt;br&gt;&lt;br&gt;
Here’s what it offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tamper-proof verification:&lt;/strong&gt; Once a record is written, not even I can alter it. And that’s the whole point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open ownership:&lt;/strong&gt; Every change in ownership is logged and visible. No shady backdoor deals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decentralized access:&lt;/strong&gt; You don’t need to know someone in the ministry to verify or register land — you just need a wallet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost-effective and secure:&lt;/strong&gt; Cuts out intermediaries and reduces paperwork. No more photocopying a "C of O" ten times.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At its core, the project isn’t just about digitizing land ownership — it’s about &lt;strong&gt;restoring trust&lt;/strong&gt; where it’s been broken for decades.&lt;/p&gt;




&lt;h3&gt;
  
  
  🗓️ Join Me for Demo Day!
&lt;/h3&gt;

&lt;p&gt;I’ll be demoing &lt;strong&gt;LandRegistry&lt;/strong&gt; on &lt;strong&gt;Friday, 4PM WAT&lt;/strong&gt;, alongside other brilliant minds from the Cipher cohort.&lt;/p&gt;

&lt;p&gt;Let’s shape the future of on-chain land ownership — one block at a time.&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>web3</category>
    </item>
    <item>
      <title>Self Guide for Deploying Laravel and React Applications on a VPS</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Wed, 26 Feb 2025 20:48:34 +0000</pubDate>
      <link>https://dev.to/emmo00/self-guide-for-deploying-laravel-and-react-applications-on-a-vps-1o57</link>
      <guid>https://dev.to/emmo00/self-guide-for-deploying-laravel-and-react-applications-on-a-vps-1o57</guid>
      <description>&lt;p&gt;This is a documentation of the steps I took in deploying my Laravel and React application to a VPS. &lt;/p&gt;

&lt;p&gt;If you're reading along, I'm sure it'd be useful irrespective of the application stack. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Initial VPS Setup
&lt;/h2&gt;

&lt;p&gt;Before deploying your applications, you need to prepare your server environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Your System
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Essential Dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;apache2 unzip curl git &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Laravel Backend Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add ondrej/php PPA as a software repository.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository ppa:ondrej/php &lt;span class="c"&gt;# Press enter when prompted.&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install PHP and Required Extensions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;php php-cli php-mbstring php-xml php-bcmath php-tokenizer php-curl php-zip php-mysql &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Composer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://getcomposer.org/installer | php
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;composer.phar /usr/local/bin/composer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Up MySQL Database
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;mysql-server &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql_secure_installation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a database and user for your Laravel application:&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="nb"&gt;sudo &lt;/span&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within the MySQL prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;laravel_db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="s1"&gt;'laravel_user'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'your_strong_password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;laravel_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'laravel_user'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;EXIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy Your Laravel Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www
git clone https://github.com/your-username/your-laravel-project.git laravel
&lt;span class="nb"&gt;cd &lt;/span&gt;laravel
composer &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the .env file with your database credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=your_strong_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate the application key and run migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan key:generate
php artisan migrate &lt;span class="nt"&gt;--seed&lt;/span&gt;
php artisan config:cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Apache for Laravel
&lt;/h3&gt;

&lt;p&gt;Create a new Apache configuration file:&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="nb"&gt;sudo &lt;/span&gt;nano /etc/apache2/sites-available/laravel.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following configuration:&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; *:80&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="nc"&gt;ServerAdmin&lt;/span&gt; webmaster@yourdomain.com
    &lt;span class="nc"&gt;DocumentRoot&lt;/span&gt; /var/www/laravel/public
    &lt;span class="nc"&gt;ServerName&lt;/span&gt; api.yourdomain.com

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="sr"&gt; /var/www/laravel/public&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="nc"&gt;AllowOverride&lt;/span&gt; &lt;span class="ss"&gt;All&lt;/span&gt;
        &lt;span class="nc"&gt;Require&lt;/span&gt; &lt;span class="ss"&gt;all&lt;/span&gt; granted
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="nc"&gt;ErrorLog&lt;/span&gt; ${APACHE_LOG_DIR}/laravel_error.log
    &lt;span class="nc"&gt;CustomLog&lt;/span&gt; ${APACHE_LOG_DIR}/laravel_access.log combined
&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;p&gt;Enable the site and required modules:&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="nb"&gt;sudo &lt;/span&gt;a2ensite laravel.conf
&lt;span class="nb"&gt;sudo &lt;/span&gt;a2enmod rewrite
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Proper File Permissions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; www-data:www-data /var/www/laravel
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 775 /var/www/laravel/storage /var/www/laravel/bootstrap/cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. React Frontend Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Build Your React Application
&lt;/h3&gt;

&lt;p&gt;On your local development machine:&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 build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Transfer the Build to Your VPS
&lt;/h3&gt;

&lt;p&gt;Using SCP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-r&lt;/span&gt; build/ username@your-vps-ip:/var/www/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you could clone your repository and build directly on the server (I'd recommend the former especially if deploying with a CICD pipeline):&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="nb"&gt;cd&lt;/span&gt; /var/www
git clone https://github.com/your-username/your-react-project.git react
&lt;span class="nb"&gt;cd &lt;/span&gt;react
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Configure Apache for React
&lt;/h3&gt;

&lt;p&gt;Create a new Apache configuration:&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="nb"&gt;sudo &lt;/span&gt;nano /etc/apache2/sites-available/react.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following:&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; *:80&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="nc"&gt;ServerAdmin&lt;/span&gt; webmaster@yourdomain.com
    &lt;span class="nc"&gt;DocumentRoot&lt;/span&gt; /var/www/react/build
    &lt;span class="nc"&gt;ServerName&lt;/span&gt; yourdomain.com

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="sr"&gt; /var/www/react/build&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="nc"&gt;Options&lt;/span&gt; &lt;span class="ss"&gt;Indexes&lt;/span&gt; &lt;span class="ss"&gt;FollowSymLinks&lt;/span&gt;
        &lt;span class="nc"&gt;AllowOverride&lt;/span&gt; &lt;span class="ss"&gt;All&lt;/span&gt;
        &lt;span class="nc"&gt;Require&lt;/span&gt; &lt;span class="ss"&gt;all&lt;/span&gt; granted

        &lt;span class="c"&gt;# This configuration ensures that React Router works correctly&lt;/span&gt;
        &lt;span class="nc"&gt;RewriteEngine&lt;/span&gt; &lt;span class="ss"&gt;on&lt;/span&gt;
        &lt;span class="nc"&gt;RewriteCond&lt;/span&gt; %{REQUEST_FILENAME} !-f
        &lt;span class="nc"&gt;RewriteCond&lt;/span&gt; %{REQUEST_FILENAME} !-d
        &lt;span class="nc"&gt;RewriteRule&lt;/span&gt; ^ index.html [L]
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nl"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="nc"&gt;ErrorLog&lt;/span&gt; ${APACHE_LOG_DIR}/react_error.log
    &lt;span class="nc"&gt;CustomLog&lt;/span&gt; ${APACHE_LOG_DIR}/react_access.log combined
&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;p&gt;Enable the site:&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="nb"&gt;sudo &lt;/span&gt;a2ensite react.conf
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Secure Your Applications with SSL
&lt;/h2&gt;

&lt;p&gt;For production applications, SSL is essential. Let's Encrypt provides free SSL certificates:&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="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-apache &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--apache&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; yourdomain.com &lt;span class="nt"&gt;-d&lt;/span&gt; api.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the prompts to complete the SSL setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Set Up Process Management for Laravel
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Configure Supervisor for Queue Workers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;supervisor &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/supervisor/conf.d/laravel-worker.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[program:laravel-worker]&lt;/span&gt;
&lt;span class="py"&gt;process_name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;%(program_name)s_%(process_num)02d&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;php /var/www/laravel/artisan queue:work --tries=3 --sleep=3&lt;/span&gt;
&lt;span class="py"&gt;autostart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;autorestart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;www-data&lt;/span&gt;
&lt;span class="py"&gt;numprocs&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;
&lt;span class="py"&gt;redirect_stderr&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;stdout_logfile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/log/laravel-worker.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate the configuration:&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="nb"&gt;sudo &lt;/span&gt;supervisorctl reread
&lt;span class="nb"&gt;sudo &lt;/span&gt;supervisorctl update
&lt;span class="nb"&gt;sudo &lt;/span&gt;supervisorctl start laravel-worker:&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Up Laravel Scheduler
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * * cd /var/www/laravel &amp;amp;&amp;amp; php artisan schedule:run &amp;gt;&amp;gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Advanced Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set Up a Load Balancer (Optional)
&lt;/h3&gt;

&lt;p&gt;For high-traffic applications, consider setting up Nginx as a load balancer in front of Apache:&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="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a configuration file:&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="nb"&gt;sudo &lt;/span&gt;nano /etc/nginx/sites-available/loadbalancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&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;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# Add more servers if you have multiple instances&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&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;80&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;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&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;h3&gt;
  
  
  Configure Redis for Caching (Optional)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;redis-server &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your Laravel .env file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CACHE_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Maintenance and Updates
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Automating Laravel Updates
&lt;/h3&gt;

&lt;p&gt;Create a simple script:&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="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/update-laravel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&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;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/laravel
git pull
composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt;
php artisan migrate &lt;span class="nt"&gt;--force&lt;/span&gt;
php artisan config:cache
php artisan route:cache
php artisan view:cache
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; www-data:www-data /var/www/laravel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable:&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="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/update-laravel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Monitoring Your Application
&lt;/h3&gt;

&lt;p&gt;Install monitoring tools:&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="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;htop net-tools &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common Laravel Issues
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;500 Internal Server Error&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check Laravel logs: &lt;code&gt;tail -f /var/www/laravel/storage/logs/laravel.log&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check Apache logs: &lt;code&gt;tail -f /var/log/apache2/laravel_error.log&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Permission Issues&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run: &lt;code&gt;sudo chown -R www-data:www-data /var/www/laravel&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Common React Issues
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;White Screen / Not Loading&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check browser console for errors&lt;/li&gt;
&lt;li&gt;Verify .htaccess file in build directory&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;API Connection Issues&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure your .env file in React has the correct API URL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;You've now successfully deployed both your Laravel backend and React frontend on a single VPS.&lt;/p&gt;

&lt;p&gt;Remember to regularly back up your database and application files, keep your server updated with security patches, and monitor your application's performance as your user base grows.&lt;/p&gt;

&lt;p&gt;Up until now we have done the deployment manually, but you should definitely consider setting up a CICD pipeline for easy, automated deployment. GitHub Actions is a good recommendation.&lt;/p&gt;

&lt;p&gt;Happy coding!👍🏻&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>react</category>
      <category>vps</category>
      <category>linux</category>
    </item>
    <item>
      <title>Learning a new language/framework</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Sun, 30 Jun 2024 19:43:26 +0000</pubDate>
      <link>https://dev.to/emmo00/learning-a-new-languageframework-1ef7</link>
      <guid>https://dev.to/emmo00/learning-a-new-languageframework-1ef7</guid>
      <description>&lt;p&gt;I recently took up an internship role where I had to use a programming language and framework I was unfamiliar with. The role involved using Laravel as the backend framework and I had to learn it. &lt;a href="https://laravel.com" rel="noopener noreferrer"&gt;Laravel&lt;/a&gt; is a PHP framework for building web applications.&lt;br&gt;
In this post, I'd like to outline some steps I took from being clueless to contributing to the codebase within 2 months.&lt;br&gt;
Don't be alarmed if this timeframe seems too short, this is probably, as I'll talk about in a minute, because I have had a little experience in programming and backend development before then. If you don't fall into this category or you are a total beginner in your field, these tips should still be helpful to you as a developer. Hang tight, let's explore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Having a good programming background
&lt;/h2&gt;

&lt;p&gt;A really smart guy once said, "People need to start learning programming instead of programming languages". I agree with this saying. Programming languages are just tools software developers use to implement their solutions. The underlying way of thinking and problem-solving are still required no matter the number of languages you know.&lt;br&gt;
Knowing a lot of programming languages, although impressive, doesn't mean the person can apply these concepts to build cool and helpful software, especially in this age of rising use of AI tools and companions.&lt;/p&gt;

&lt;p&gt;Understanding concepts like Variables, Data types, control flow, data structures, algorithms, programming paradigms like Object Oriented Programming (OOP) and Functional programming, Design patterns, Testing, concurrency and parallelism, and error handling is a good start. In the real world, or even now, we apply and implement most of these without consciously/intentionally thinking about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn the language first
&lt;/h2&gt;

&lt;p&gt;I've heard people say "I'm good with React, but I have issues with JavaScript". This shouldn't be the case. One should be very familiar with a language and how it works before learning any of its frameworks.&lt;br&gt;
Some key questions to ask when learning a new language may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does the general &lt;strong&gt;Syntax&lt;/strong&gt; look?&lt;/li&gt;
&lt;li&gt;What are the provided/built-in &lt;strong&gt;Data Types&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How do I declare &lt;strong&gt;Variables&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Provided &lt;strong&gt;Operators&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;How to implement &lt;strong&gt;Control Flows&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;How to declare &lt;strong&gt;Function&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Manual &lt;strong&gt;Memory Management&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How to run my programs? &lt;strong&gt;Compiled&lt;/strong&gt; or &lt;strong&gt;Interpreted&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Is it a &lt;strong&gt;Static or Dynamic Type&lt;/strong&gt; language?&lt;/li&gt;
&lt;li&gt;What &lt;strong&gt;Paradigm&lt;/strong&gt; does it belong?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, You'll notice answers to these questions for any programming language you choose are not the same. You might also get a "Not Quite" or "It depends" answer from some of these in some languages, and understanding these "It depends" scenarios is key.&lt;/p&gt;

&lt;p&gt;For example, answering the question "How do I run my Java Program". You can run your Java program by first compiling it to bytecode with the java compiler: &lt;code&gt;javac MyCode.java&lt;/code&gt;, then running the generated &lt;code&gt;.class&lt;/code&gt; file with &lt;code&gt;java MyCode&lt;/code&gt;. Despite the compilation step, java is "Not Quite" a compiled language. Java is considered both compiled and interpreted. It compiles to bytecode, then the bytecode is interpreted with the Java Virtual Machine (JVM).&lt;/p&gt;

&lt;p&gt;Most of the knowledge you gain in this stage is transferable to other programming languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Projects
&lt;/h2&gt;

&lt;p&gt;This is a very important step in the process. Building projects is a way for you to exercise the knowledge you've acquired. It also allows you to experiment with the language or framework, which gives you a more in-depth knowledge of the language.&lt;br&gt;
It is okay to start small as no one expects you to build anything too complex as you start, you are only advised to take up challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Frameworks/Libraries
&lt;/h2&gt;

&lt;p&gt;After getting a grasp of the language through the docs/tutorials and building projects, it's time to choose a framework.&lt;br&gt;
Frameworks are pre-written blocks of code that programmers can incorporate into their projects to save time and effort. Frameworks and libraries make implementation of common tasks very easy because of the provided &lt;em&gt;abstraction&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Choosing a framework to learn can be hard and confusing as you're new to the space, so here are some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with a Popular one: Learning a popular framework with a vast community and resources makes it easier to find help and learning materials.&lt;/li&gt;
&lt;li&gt;Experiment: Once you're comfortable with one framework, consider exploring others in different domains to broaden your skillset and knowledge.&lt;/li&gt;
&lt;li&gt;Focus on Core Programming Concepts: Regardless of the framework, a solid understanding of programming fundamentals is crucial. The ability to learn new frameworks becomes easier as your programming foundation strengthens.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Start learning the framework
&lt;/h2&gt;

&lt;p&gt;Before diving into the framework, ensure you have a good grasp of the programming language it's built on. This will make understanding the framework's syntax and concepts much smoother.&lt;/p&gt;

&lt;p&gt;Finding the right resources to learn the chosen framework is not always easy, but I always recommend the Official framework documentation. Most frameworks have comprehensive documentation that covers everything from basic concepts to advanced features. Start here to get a solid understanding of the framework's core principles and functionalities.&lt;br&gt;
Other sources for learning about a framework include Tutorials (e.g. YouTube Videos, Blogs, and Articles), Video Courses (like Udemy or Coursera), and Forums.&lt;/p&gt;

&lt;p&gt;Do not waste time in this stage before moving to the next step so you don't get stuck in "Tutorial Hell".&lt;/p&gt;

&lt;h2&gt;
  
  
  Notice the Key concepts
&lt;/h2&gt;

&lt;p&gt;Don't try to learn everything at once. Prioritize understanding of the framework's core functionalities, architecture, and design patterns. This foundational knowledge will be essential as you build more complex projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Projects
&lt;/h2&gt;

&lt;p&gt;Yet again, Build projects. Don't wait until you're an expert to start building. Look for small project ideas that allow you to practice the framework's concepts. This will solidify your learning and boost your confidence.&lt;/p&gt;

&lt;p&gt;Speaking of taking challenges, allow me to introduce the &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;HNG internship program&lt;/a&gt;. HNG is a company with a mission — we work with the very best techies to help them enhance their skills through our HNG internship program and build their network. HNG Internship is a fast-paced boot camp for learning digital skills. It's focused on advanced learners and those with some pre-knowledge, and it gets people into shape for job offers. To register for this program, click &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope these tips were helpful. Remember, growth takes time and dedication so set realistic goals, take breaks and you can also find a study buddy to help you in your journey. Stay consistent friends🙋‍♂️.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>learning</category>
      <category>laravel</category>
    </item>
    <item>
      <title>The difference between '||' and '??' in JavaScript.</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Fri, 12 Apr 2024 16:20:23 +0000</pubDate>
      <link>https://dev.to/emmo00/the-difference-between-and-in-javascript-3em3</link>
      <guid>https://dev.to/emmo00/the-difference-between-and-in-javascript-3em3</guid>
      <description>&lt;p&gt;Today, we are going to look at the behavior of two operators in JavaScript - the Logical OR Operator (&lt;code&gt;||&lt;/code&gt;) and the Nullish Coalescing Operator (&lt;code&gt;??&lt;/code&gt;). These operators are usually confused or misunderstood, so let's get right to it.&lt;/p&gt;

&lt;p&gt;They are usually used in writing one-liner "hotwires" (providing default values or fallbacks) and while they might seem similar, they serve different purposes and behave differently, especially in the context of handling &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; values in JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logical OR Operator &lt;code&gt;||&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The logical OR operator &lt;code&gt;||&lt;/code&gt; is a binary operator that returns the first truthy value it encounters or the last value if none are truthy. &lt;br&gt;
JavaScript considers a value that is not among the following truthy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;''&lt;/code&gt; (empty string)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NaN&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is used to test whether at least one of the operands is truthy. if the left-hand operand is truthy, it is returned. If it is falsy, the right-hand operand is evaluated and returned.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Emmanuel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;defaultName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;defaultName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Emmanuel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;the &lt;code&gt;name&lt;/code&gt; variable is not falsy, so the &lt;code&gt;displayName&lt;/code&gt; is evaluated to &lt;code&gt;"Emmanuel"&lt;/code&gt;. Now consider this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;defaultName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;defaultName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Guest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, since &lt;code&gt;name&lt;/code&gt; is an empty string (which is falsy), the || operator evaluates &lt;code&gt;defaultName&lt;/code&gt; and assigns it to &lt;code&gt;displayName&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nullish Coalescing Operator (??)
&lt;/h2&gt;

&lt;p&gt;The nullish coalescing operator (??) is also a logical operator that returns its right-hand side operand when its left-hand side operand is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;, and otherwise returns its left-hand side operand. Unlike the &lt;code&gt;||&lt;/code&gt; operator, it does not consider other falsy values (&lt;code&gt;false&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;''&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;) as triggering the fallback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;defaultAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;defaultAge&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, even though age is &lt;code&gt;0&lt;/code&gt; (which is considered falsy), the &lt;code&gt;??&lt;/code&gt; operator does not consider it as a trigger for the fallback because &lt;code&gt;0&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. Therefore, &lt;code&gt;userAge&lt;/code&gt; is assigned the value of age, which is &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In summary, the &lt;code&gt;||&lt;/code&gt; operator is used to test whether at least one of the operands is truthy, while the ?? operator is used to provide a default value for a variable, but only considers &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; as falsy.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>node</category>
      <category>coding</category>
    </item>
    <item>
      <title>What is the point of using recursive functions when writing code?</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Fri, 05 Apr 2024 14:29:43 +0000</pubDate>
      <link>https://dev.to/emmo00/what-is-the-point-of-using-recursive-functions-when-writing-code-2k4f</link>
      <guid>https://dev.to/emmo00/what-is-the-point-of-using-recursive-functions-when-writing-code-2k4f</guid>
      <description>&lt;p&gt;Have you ever heard of recursion in programming? It's a cool technique where a function can call itself! It might sound a bit mind-bending at first, but once you understand how it works, it can be an incredibly helpful and interesting to implement in your programs.&lt;/p&gt;

&lt;p&gt;Recursive functions are divided into 3 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Base case&lt;/li&gt;
&lt;li&gt;logic&lt;/li&gt;
&lt;li&gt;Calling itself&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Consider this implementation of the factorial(!) function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&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="c1"&gt;// base case.&lt;/span&gt;
        &lt;span class="k"&gt;return&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// call itself. (combined with the logic)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A base case is a crucial component of a recursive function. It is responsible for preventing the function from calling itself repeatedly, which could result in a stack overflow error. Without a base case, the function would keep calling itself infinitely.&lt;/p&gt;

&lt;p&gt;The logic is the part of the function that solves the most basic unit of the bigger problem you are trying to solve with recursion.&lt;/p&gt;

&lt;p&gt;Finally, the recursive function has to call itself. That's what recursion is all about.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now the advantages: ?!?!?!?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Readability: Recursive functions can often be more readable and easier to understand than iterative(loop) functions, especially for problems that have a natural recursive structure.&lt;/p&gt;

&lt;p&gt;Conciseness: Recursive functions can be more concise than iterative ones, as they don't require explicit loop variables and increment operations&lt;/p&gt;

&lt;p&gt;Modularity: Recursive functions can be more modular than iterative ones, as they can often be divided into smaller subproblems that can be solved recursively.&lt;/p&gt;

&lt;p&gt;Tail-recursion optimization: Some programming languages can optimize tail-recursive functions, which can lead to better performance than iterative functions.&lt;/p&gt;

&lt;p&gt;Tree-like data structures: Recursive functions are particularly well-suited to tree-like data structures, as they can easily traverse the structure using recursive calls.&lt;/p&gt;

&lt;p&gt;However, recursion is not always the best way to implement a solution, here's why:&lt;/p&gt;

&lt;p&gt;Space complexity: Recursive functions can sometimes have higher space complexity than iterative functions, as each recursive call adds a new stack frame to the call stack.&lt;/p&gt;

&lt;p&gt;Stack overflow: Recursive functions can lead to stack overflow errors if the recursion depth becomes too large. This can be mitigated by using tail recursion or by using an iterative solution.&lt;/p&gt;

&lt;p&gt;In conclusion, recursion in programming is a fascinating technique that opens up new avenues for solving problems. By allowing functions to call themselves, recursion offers a powerful approach to tackling complex tasks with elegance and simplicity.&lt;br&gt;
However, it's crucial to recognize that recursion isn't always the optimal solution. &lt;/p&gt;

</description>
      <category>code</category>
      <category>programming</category>
      <category>design</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to use Black and pre-commit for auto text-formatting on commit [setup] [python]</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Fri, 29 Mar 2024 00:36:07 +0000</pubDate>
      <link>https://dev.to/emmo00/how-to-setup-black-and-pre-commit-in-python-for-auto-text-formatting-on-commit-4kka</link>
      <guid>https://dev.to/emmo00/how-to-setup-black-and-pre-commit-in-python-for-auto-text-formatting-on-commit-4kka</guid>
      <description>&lt;p&gt;Hello👋.&lt;/p&gt;

&lt;p&gt;Today we are going to look at how to setup &lt;a href="https://github.com/pre-commit/pre-commit" rel="noopener noreferrer"&gt;Black&lt;/a&gt; (a python code formatter) and &lt;a href="https://github.com/pre-commit/pre-commit" rel="noopener noreferrer"&gt;pre-commit&lt;/a&gt; (a package for handling git hooks in python) to automatically format you code on commit.&lt;/p&gt;

&lt;p&gt;All the Code used in this article can be found on this GitHub repo &lt;a href="https://github.com/Emmo00/black-pre-commit-example-setup" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;Setting up your project with this (automatic code formatting on every commit) can be very useful and helpful especially when setting up a GitHub repository you expect other contributors. This enforces coding formatting and fosters consistency in coding style.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let's get right to it&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing Black and pre-commit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First of all, we need to install these packages to our projects. You can use the following command to install them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;black pre-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might also need to add these packages to your &lt;code&gt;requirements.txt&lt;/code&gt; file so other contributors can install the need packages by running &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;. You can do this by running &lt;code&gt;pip freeze&lt;/code&gt;, and the coping the output to your &lt;code&gt;requirements.txt&lt;/code&gt; file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure pre-commit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next step is configuring &lt;code&gt;pre-commit&lt;/code&gt;. To do this, create a file called &lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .pre-commit-config.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then copy the following configurations to this file.&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;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/psf/black&lt;/span&gt;
    &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;22.3.0&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;black&lt;/span&gt;
        &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;--line-length=88&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;language_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3.11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Pre-Commit to use Black version 22.3.0 and format all Python files with a line length of 88 characters (you can adjust this to your preference).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run pre-commit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have our configurations ready, make sure that the current folder you are in is a git/github project (With the &lt;code&gt;.git&lt;/code&gt; folder)&lt;br&gt;
Now, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pre-commit &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs pre-commit hooks to &lt;code&gt;.git\hooks\pre-commit&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you need an internet commit for the first commit you make. This is to enable pre-commit initialize the environment for black, but once the environment is setup, it'd be reused.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git commit -m "add pre-commit configuration"
[INFO] Initializing environment for https://github.com/psf/black.      
[INFO] Installing environment for https://github.com/psf/black.        
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
black................................................(no files to check)Skipped
[main 6e21eab] add pre-commit configuration
 1 file changed, 7 insertions(+)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, you are ready to use the automatic code formatter. Just create a python file, run &lt;code&gt;git add .&lt;/code&gt;, and then run &lt;code&gt;git commit -m "Commit message"&lt;/code&gt;. You'd notice that black attempts to format the file you just created. If you get the following message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;black....................................................................Failed
- hook id: black
- files were modified by this hook

reformatted test.py

All done! \u2728 \U0001f370 \u2728
1 file reformatted.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just run &lt;code&gt;git add&lt;/code&gt; and &lt;code&gt;git commit&lt;/code&gt; again.&lt;/p&gt;



&lt;p&gt;Enjoy autoformatted code from now on😅. Bye👋&lt;/p&gt;

</description>
      <category>python</category>
      <category>git</category>
      <category>howto</category>
      <category>code</category>
    </item>
    <item>
      <title>Closures 🫂 Memoisation</title>
      <dc:creator>Emmanuel (Emmo00)</dc:creator>
      <pubDate>Fri, 22 Mar 2024 21:34:13 +0000</pubDate>
      <link>https://dev.to/emmo00/closures-memoisation-3gpp</link>
      <guid>https://dev.to/emmo00/closures-memoisation-3gpp</guid>
      <description>&lt;p&gt;In functional programming, closure refers to the ability of a function to access and utilize variables from its lexical scope, even after that scope has finished executing. Now, Lexical scope basically refers to the environment/location a variable is defined/declared within the source code.&lt;/p&gt;

&lt;p&gt;Closures (forever) remember the scope they were declared in for as long as they exist.&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%2F819iwehth5q4sd82et1k.jpg" 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%2F819iwehth5q4sd82et1k.jpg" alt="Example of closures" width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above example, the code uses a closure to create a function object that provides controlled access to a private variable. The &lt;code&gt;get&lt;/code&gt; method allows you to retrieve the value, and the &lt;code&gt;set&lt;/code&gt; method allows you to update it.&lt;/p&gt;

&lt;p&gt;This may sound obvious, but it can be very useful in implementing a technique called "memoisation"&lt;/p&gt;

&lt;p&gt;Memoization is an optimization technique used in computer science to improve the performance of programs. It's especially useful for improving the performance of functions that are computationally expensive and called multiple times with the same inputs.&lt;/p&gt;

&lt;p&gt;Memoisation can basically be described as when expensive operations are run early, and their results cached for later use in the program.&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%2Fdaoso2oyy75ukh3swyog.jpg" 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%2Fdaoso2oyy75ukh3swyog.jpg" alt="Example implementation of Memoisation" width="800" height="860"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above example, the function  &lt;code&gt;square_memoise&lt;/code&gt; uses memoization by avoiding unnecessary computations for repeated function calls with the same arguments, potentially improving performance.&lt;/p&gt;

&lt;p&gt;In conclusion, closures and memoization are powerful tools that enhance the capabilities of functional programming. Closures provide a way to create private variables within functions, leading to better data encapsulation and code organization. Memoization, on the other hand, optimizes program performance by caching the results of expensive calculations, preventing redundant work. By understanding and utilizing these techniques, you can write cleaner, more efficient, and maintainable code.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>algorithms</category>
      <category>design</category>
      <category>functional</category>
    </item>
  </channel>
</rss>
