<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ifeanyi Chima</title>
    <description>The latest articles on Forem by Ifeanyi Chima (@ifeanyichima).</description>
    <link>https://forem.com/ifeanyichima</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F763463%2F9fc4d7f3-908c-400a-b330-7db284158422.jpg</url>
      <title>Forem: Ifeanyi Chima</title>
      <link>https://forem.com/ifeanyichima</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ifeanyichima"/>
    <language>en</language>
    <item>
      <title>How to use Google Gemma 4 model</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Thu, 14 May 2026 08:58:30 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/how-to-use-google-gemma-4-model-2o3l</link>
      <guid>https://forem.com/ifeanyichima/how-to-use-google-gemma-4-model-2o3l</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Write About Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I Built a Celebrity AI Chat App with Google Gemma 4 26B-A4B, Here's Everything You Need to Know&lt;/p&gt;

&lt;p&gt;I've always been fascinated by the idea of talking to your Elon Musk, but for now we would have to settle down for a &lt;strong&gt;chatbot&lt;/strong&gt; that actually &lt;em&gt;feels&lt;/em&gt; like them. So when Google dropped Gemma 4 in April 2026, I saw my chance. I built a web app with a chat UI where you pick a celebrity, and Gemma 4 slips into their persona and holds a full conversation with you. The results were genuinely impressive and sometimes hilarious.&lt;/p&gt;

&lt;p&gt;But before I walk you through how I built it, let me give you a proper introduction to the models that made it possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understanding the Google Gemma 4 Model Family
&lt;/h2&gt;

&lt;p&gt;Gemma 4 is Google DeepMind's latest generation of open models, released on April 2, 2026. It comes in &lt;strong&gt;four distinct sizes&lt;/strong&gt;, each targeting a different use case, from running on your phone to powering a server-grade workstation. All four models are multimodal (they can process text and images), licensed under Apache 2.0, and support over 140 languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Comparison Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Architecture&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Audio&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;E2B&lt;/td&gt;
&lt;td&gt;Efficient Dense&lt;/td&gt;
&lt;td&gt;128K&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Mobile / Edge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E4B&lt;/td&gt;
&lt;td&gt;Efficient Dense&lt;/td&gt;
&lt;td&gt;128K&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;On-device assistants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26B A4B&lt;/td&gt;
&lt;td&gt;Mixture of Experts&lt;/td&gt;
&lt;td&gt;256K&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;High-throughput APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;31B&lt;/td&gt;
&lt;td&gt;Dense&lt;/td&gt;
&lt;td&gt;256K&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Maximum quality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. How to Get an API Key
&lt;/h2&gt;

&lt;p&gt;Before you can start building anything with Gemma 4, you need API access. The good news? You have a couple of options and one of them is completely free to start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Google AI Studio (Direct from Google)
&lt;/h3&gt;

&lt;p&gt;Google provides direct API access to Gemma 4 through &lt;strong&gt;Google AI Studio&lt;/strong&gt;. Here's how to get your key:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://aistudio.google.com" rel="noopener noreferrer"&gt;aistudio.google.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sign in with your Google account&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Get API key"&lt;/strong&gt; in the left sidebar&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Create API key"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Copy your key and store it somewhere safe (you won't be able to see it again)&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.amazonaws.com%2Fuploads%2Farticles%2Fmip5p7ed8ne4dzfj82v1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmip5p7ed8ne4dzfj82v1.png" alt="Google AI Studio" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it. Google AI Studio gives you a generous free tier to experiment with before you need to think about billing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Never hardcode your API key in your frontend code. Always store it in an environment variable (&lt;code&gt;.env&lt;/code&gt; file) and access it from your backend.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;.env&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; before your first commit, not after.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Option B: OpenRouter
&lt;/h3&gt;

&lt;p&gt;OpenRouter is a unified API gateway that gives you access to hundreds of models including all Gemma 4 variants through a single, OpenAI-compatible endpoint. That means you can switch models with one line of code change, get automatic fallbacks if a provider goes down, and even access the &lt;strong&gt;free tier&lt;/strong&gt; of Gemma 4 31B without spending a cent to start.&lt;/p&gt;

&lt;p&gt;To get your OpenRouter API key:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://openrouter.ai" rel="noopener noreferrer"&gt;openrouter.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Sign In"&lt;/strong&gt; and create an account&lt;/li&gt;
&lt;li&gt;Once logged in, click &lt;strong&gt;"Get API Key"&lt;/strong&gt; button from your dashboard&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"New Key"&lt;/strong&gt;, give it a name (e.g. &lt;code&gt;celeb-chat-dev&lt;/code&gt;), and hit create&lt;/li&gt;
&lt;li&gt;Copy and save your key it starts with &lt;code&gt;sk-or-...&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can optionally add credits to your account for paid usage, but to start experimenting, the free-tier models (including &lt;code&gt;google/gemma-4-26b-a4b-it:free&lt;/code&gt;) are more than enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. How to Use Google Gemma 4 Through OpenRouter
&lt;/h2&gt;

&lt;p&gt;Alright, this is where the fun begins. Let me walk you through exactly how I wired up Gemma 4 via OpenRouter to power my celebrity chat app, from the first API call all the way to a working chat UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Base URL and Model IDs
&lt;/h3&gt;

&lt;p&gt;OpenRouter exposes Gemma 4 through a single endpoint that's fully compatible with the OpenAI Chat API format. If you've ever called GPT-4 or any other model via OpenAI's SDK, this will feel immediately familiar, you're literally changing one URL and one model string.&lt;/p&gt;

&lt;p&gt;The base URL is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;https://openrouter.ai/api/v1/chat/completions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the Gemma 4 model IDs on OpenRouter are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Model ID&lt;/th&gt;
&lt;th&gt;Free Tier?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 E2B&lt;/td&gt;
&lt;td&gt;&lt;code&gt;google/gemma-4-e2b-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 E4B&lt;/td&gt;
&lt;td&gt;&lt;code&gt;google/gemma-4-e4b-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 26B A4B&lt;/td&gt;
&lt;td&gt;&lt;code&gt;google/gemma-4-26b-a4b-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ (&lt;code&gt;:free&lt;/code&gt; suffix)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 31B&lt;/td&gt;
&lt;td&gt;&lt;code&gt;google/gemma-4-31b-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ (&lt;code&gt;:free&lt;/code&gt; suffix)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To use the free tier of the 26B model for example, use &lt;code&gt;google/gemma-4-26b-a4b-it:free&lt;/code&gt; as the model string.&lt;/p&gt;




&lt;h3&gt;
  
  
  Switching Models Without Rewriting Your Code
&lt;/h3&gt;

&lt;p&gt;This is the quiet superpower of going through OpenRouter. Because the API schema is identical across all models, switching from the free 31B to the 26B MoE (which is faster and cheaper in production) is literally one line:&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;// During development&lt;/span&gt;
&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google/gemma-4-31b-it:free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// In production (faster, cheaper MoE)&lt;/span&gt;
&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google/gemma-4-26b-a4b-it:free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No refactoring. No new SDK. Just change the string. This is why I recommend OpenRouter for any serious project, you can prototype on free-tier models and graduate to the right production model without touching your integration code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Your First API Call
&lt;/h3&gt;

&lt;p&gt;Let's start simple with a raw &lt;code&gt;fetch&lt;/code&gt; call in JavaScript, no SDKs needed:&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;response&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://openrouter.ai/api/v1/chat/completions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &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;OPENROUTER_API_KEY&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google/gemma-4-26b-a4b-it:free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What's the capital of Nigeria?&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="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;response&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Three things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your API key goes in the &lt;code&gt;Authorization&lt;/code&gt; header as a Bearer token&lt;/li&gt;
&lt;li&gt;The response shape mirrors OpenAI, your answer lives at &lt;code&gt;data.choices[0].message.content&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You're billed (or rate-limited on free tier) per token, so &lt;code&gt;max_tokens&lt;/code&gt; is worth setting explicitly&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I was getting this error&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;google/gemma-4-26b-a4b-it:free is temporarily rate-limited upstream.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The free tier of Gemma 4 on OpenRouter is being hammered by too many users right now and Google AI Studio is throttling it. When you use the free tier on OpenRouter &lt;code&gt;(google/gemma-4-26b-a4b-it:free)&lt;/code&gt;, you are sharing a pool of rate limits with every other developer in the world using that same free model. So when too many people hit it at once, Google throttles it and you get that &lt;code&gt;429&lt;/code&gt; error. But you already have a Google AI Studio API key sitting in your &lt;code&gt;.env.local&lt;/code&gt; doing nothing right now. OpenRouter lets you connect your own Google AI Studio key so that your requests go through your personal quota instead of the shared free pool.&lt;/p&gt;

&lt;p&gt;You have two options:&lt;/p&gt;

&lt;p&gt;Option 1 — Add your Google AI Studio key to OpenRouter&lt;/p&gt;

&lt;p&gt;Option 2 — Add retry logic to your API route&lt;/p&gt;

&lt;p&gt;I went with Option 1 which is adding my Google AI Studio key to OpenRouter integrations&lt;/p&gt;

&lt;p&gt;Go to: &lt;code&gt;openrouter.ai/settings/integrations&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find Google AI Studio&lt;/li&gt;
&lt;li&gt;Paste your Google AI Studio API key there&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you your own dedicated rate limit instead of sharing the free pool with everyone&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%2Fm8ghwn94mnwxihpsmxkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8ghwn94mnwxihpsmxkw.png" alt="OpenRouter integration" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  The System Prompt; The Secret Weapon for My Project
&lt;/h3&gt;

&lt;p&gt;Here's where Gemma 4 genuinely impressed me. Gemma 4 officially supports the &lt;code&gt;system&lt;/code&gt; role natively; a big deal for an open model, since earlier generations required hacky workarounds. However, in my actual project I used a slightly different pattern that I found worked even better for persona-heavy apps: the &lt;strong&gt;user/assistant injection pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of passing the persona as a &lt;code&gt;system&lt;/code&gt; message, I injected it as the first &lt;code&gt;user&lt;/code&gt; message and followed it with a primed &lt;code&gt;assistant&lt;/code&gt; response where the model explicitly "agrees" to become the character before the real conversation even starts:&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;formattedMessages&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="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// persona instructions injected here&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// the model "confirms" the persona before the conversation begins&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Understood. I am &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. I will only speak about my own life, work, and experiences. Ask me anything about who I am.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// then the real conversation history follows&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subtle advantage of this approach over a plain &lt;code&gt;system&lt;/code&gt; message: the model has explicitly &lt;em&gt;agreed&lt;/em&gt; to the role as part of the conversation context. That in-context confirmation produces noticeably stronger character lock-in across long conversations. The model is far less likely to slip out of persona when it has already "committed" to it in an early assistant turn.&lt;/p&gt;

&lt;p&gt;The results were honestly uncanny. The model held the persona across multiple turns, matched the celebrity's tone and vocabulary, and even pushed back on out-of-character questions in a way that felt natural. The 256K context window meant I could carry a long conversation without the model ever "forgetting" who it was supposed to be.&lt;/p&gt;




&lt;h3&gt;
  
  
  Enabling Reasoning Mode
&lt;/h3&gt;

&lt;p&gt;One of Gemma 4's standout features is its configurable thinking mode, you can ask the model to reason through a problem before giving its final answer. OpenRouter exposes this through a &lt;code&gt;reasoning&lt;/code&gt; parameter:&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="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google/gemma-4-26b-a4b-it&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;reasoning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// turn on chain-of-thought&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When enabled, the response includes a &lt;code&gt;reasoning_details&lt;/code&gt; array showing the model's internal thought process before the final answer. I didn't use this for the celebrity chat (you don't want Morgan Freeman visibly deliberating), but it's incredibly useful for any app where you want to show &lt;em&gt;why&lt;/em&gt; the model said something for example; tutoring apps, code explainers, or decision-support tools.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One tip from the OpenRouter docs: if you're building an agentic tool or integrating with something like Claude Code or Cline, &lt;strong&gt;turn reasoning off&lt;/strong&gt;. It adds latency and those tools are optimized for fast back-and-forth, not deep deliberation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Thanks for Reading !
&lt;/h3&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
    </item>
    <item>
      <title>My Buddy and I</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Wed, 13 May 2026 16:33:04 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/my-buddy-and-i-5i5</link>
      <guid>https://forem.com/ifeanyichima/my-buddy-and-i-5i5</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I chose this project because as a kid (since age: 17) I have always had this vivid dreams of speaking with Elon Musk, he is kind of like my Idol and I would cherish the opportunity to have a conversation with him, until that day comes, this is what we would manage. When I came across this hackathon to test the lates model built by Google (Gemma 4) it was a no-brainer for me. I want the opportunity to understand the memory and context management of this model. I decided not to limit it to Elon Musk and included as much celebrities as possible. I want to give my friends the opportunity to test and use it. &lt;/p&gt;

&lt;p&gt;Buddy is a web application that lets you have real, in-character conversations with iconic public figures such as athletes, billionaires, historical leaders, artists, and innovators. You pick a person, and the AI steps into their shoes completely. It speaks the way they speak, stays grounded in their real life and career, and refuses to break character.&lt;/p&gt;

&lt;p&gt;Although, with this project I am not solving a problem like climate change or malaria cure, The problem Buddy solves is simple. Most AI chatbots are general-purpose. You can ask them anything, and they will answer as a neutral assistant. That is useful, but it is not immersive. Buddy flips that entirely. The AI is not an assistant anymore, it is a person. Ask Lionel Messi about his childhood in Rosario. Ask Steve Jobs why he believed design was everything. You get answers that feel like a real conversation, not a Wikipedia summary read back to you.&lt;/p&gt;

&lt;p&gt;The experience Buddy creates is curiosity without friction. It is the feeling of sitting across from someone remarkable and just... asking them things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Link: &lt;a href="https://ifeanyi-buddy.netlify.app" rel="noopener noreferrer"&gt;https://ifeanyi-buddy.netlify.app&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/MasterIfeanyi/google-gemma4-hackathon" rel="noopener noreferrer"&gt;https://github.com/MasterIfeanyi/google-gemma4-hackathon&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Gemma 4
&lt;/h2&gt;

&lt;p&gt;Buddy runs on Gemma 4 26B, accessed via OpenRouter using the &lt;code&gt;google/gemma-4-26b-a4b-it:free model&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The choice of Gemma 4 over the smaller variants came down to one core requirement; persona consistency. Keeping an AI locked inside a specific person's personality across a full multi-turn conversation is genuinely hard. The model needs to remember who it is, match the person's tone and vocabulary, deflect off-topic questions naturally without sounding robotic, and stay grounded in real publicly known facts all at the same time. The smaller E2B and E4B variants are impressive for their size, but they tend to drift out of character more easily under pressure, especially when a user deliberately tries to break the persona with trick questions or unrelated topics.&lt;/p&gt;

&lt;p&gt;The 26B model holds the character much more firmly. When you ask Messi a question in Spanish, it does not just translate, it responds with the rhythm and warmth of how Messi actually speaks. When you push Steve Jobs on a topic he would find irrelevant, it redirects with the kind of sharp confidence Jobs was known for. That level of nuance needs a bigger model.&lt;/p&gt;

&lt;p&gt;One specific technical challenge worth mentioning is Gemma 4 does not support a native system role in its message format. To get around this, Buddy injects the personality prompt as a user / assistant turn pair at the very start of every request, effectively tricking the model into treating the persona as established context before the real conversation begins. The 26B model responds to this pattern reliably and stays locked in. Smaller models were noticeably less consistent with the same approach.&lt;/p&gt;

&lt;p&gt;What &lt;strong&gt;Gemma 4&lt;/strong&gt; ultimately unlocked for Buddy was believability. Because the model is large enough to hold complex persona context across many turns, we never had to simplify the experience to make it work. We did not have to limit conversation length, restrict the types of questions users could ask, or hardcode fallback responses. The model handled edge cases we never explicitly planned for. When a user asked Messi to speak Spanish, &lt;strong&gt;Gemma 4&lt;/strong&gt; switched languages naturally and stayed in character at the same time, responding with the warmth and rhythm of how Messi actually communicates, without any instruction from us to do so. When users tried to break the persona with off-topic questions, the model deflected in the voice of the person, not with a generic AI refusal. That level of emergent, in-character behaviour is what a smaller model cannot reliably give you and it is what makes Buddy feel like a conversation rather than a demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank you.
&lt;/h2&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
    </item>
    <item>
      <title>Google Next '26 - My thoughts</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Tue, 28 Apr 2026 08:01:47 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/google-next-26-my-thoughts-5dj3</link>
      <guid>https://forem.com/ifeanyichima/google-next-26-my-thoughts-5dj3</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-cloud-next-2026-04-22"&gt;Google Cloud NEXT Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I have been eyeing to participate in a DEV.TO hackathon for a while now and when I saw this come across my timeline, I jumped up excitedly. I want the badge of honor. The big focus for the Google Cloud NEXT event is on what Google is debuting in the A.I. race especially agents. The future of developing on the cloud is exciting !! &lt;/p&gt;

&lt;h2&gt;
  
  
  Keynote &amp;amp; Demos
&lt;/h2&gt;

&lt;p&gt;In this article, I’ll break down the Developer Keynote because that stood out most to me and why.&lt;/p&gt;

&lt;p&gt;I tuned in for the &lt;a href="https://www.youtube.com/watch?v=A01DQ8_xy7Q" rel="noopener noreferrer"&gt;Developer Keynote (April, 23)&lt;/a&gt; which discussed building a marathon planning agent. A Gemini Enterprise Agent planned an entire Las Vegas marathon experience, coordinating hotels, routes, schedules, and logistics using multiple connected agents. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo 1 (Mofi Rahman) - Building agents with Agent Platform&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can design an agent in agent designer. When building an agent you need three things: Instructions; to help the agent understand its role as the marathon planner. Skills; help the agent progressively understand what is available to the agent to complete the work. such as using Google maps, handling Geo-spatial data. Map skills can make your agent an expert at using Google maps. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recap&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give the agent a prompt&lt;/li&gt;
&lt;li&gt;Agent loads the skills&lt;/li&gt;
&lt;li&gt;Agent executes the tools to find viable routes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What this means for developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For developers, this means they can build specialized AI agents by composing three core components: instructions, skills, and tools, rather than writing complex logic from scratch. The agent designer platform handles how the agent loads skills, processes prompts, and decides which tools to call, so developers can focus on defining what the agent should do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo 2 (Ivan Nardini &amp;amp; Casey West) - Creating multi-agent systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have a planner agent that needs to talk to 2 other agents: the simulator agent and the evaluator agent. The planner agent creates potential routes for the race. Evaluator sub-agent will judge routes based on specific criteria that we pick. Simulator agent works with the planner to get approved routes, run them and show results. How can we facilitate communication between all agents, we need two components; A2A protocol and agent registry. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A2A Protocol:&lt;/strong&gt; Google introduced an open-source protocol called A2A protocol. This protocol eliminates API code to connect agents. Agents can just share a card that represents the capabilities of that agent. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Registry:&lt;/strong&gt; This is a directory where agents get registered and it resolves every agent identity and maps their specific skillset across the agent network.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What this means for developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For developers, this means they can build multi-agent systems where agents communicate and collaborate without writing custom API integration code. The A2A protocol lets agents share capability cards with each other, while the agent registry acts as a directory that tracks every agent's identity and skillset across the network, so the planner, simulator, and evaluator agents can find and talk to each other automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo 3 (Lucia Subatin &amp;amp; Jack Wotherspoon) - Enhancing agents with memory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When using gemini to do my job in the office, I usually copy all the files one-by-one and shove it into one prompt, in a bid to give gemini as much context as possible. For our planner agent we improve the context by giving it the ability to manage sessions, add memory and access other data sources. In this demo, we saw how we can use a skill to make the agent an expert at using alloyDB and vector functions. Basically what this Demo was showing is that by managing context efficiently and adding memory to our agent you can see the simulator agent adjust its route based on the memory and data it now had. The memory aspect comes from how the agent uses alloyDB together with vector functions to store and recall context from previous sessions, so it (alloyDB) behaves like a memory bank. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For developers, this means they can replace the manual process of dumping files into a prompt by giving agents structured memory and database access instead. By connecting the agent to tools like AlloyDB and vector functions, the agent automatically manages its own context across sessions, so it can make smarter, more informed decisions without the developer having to feed it everything upfront.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo 4 (Megan O'keefe) - Debugging agents at scale&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We all use &lt;code&gt;console.log("here")&lt;/code&gt; to debug a point in our codebase, well in artificial intelligence, we can not do that but, Google provides tools for us to debug; Agent observability and Cloud assist investigation agent. Using these tools we will find and investigate the root cause of the error and then we will deploy a proactive fix. In this demo, we had an error and we were suggested a fix by the agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt; The simulator agent is failing to call the gemini model API due to a request error. Something is wrong that the payloads were sending to the model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud assist prompt:&lt;/strong&gt; Resume the Gemini cloud assist investigation about the simulator agent. What is wrong with agent.py&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; The agent is suggesting a fix that we add a token threshold parameter to our event compaction config so that we are periodically compressing context more often with each invocation. This is because we have a 1 million context token limit.&lt;/p&gt;

&lt;p&gt;From this demo, I learned that Google cloud provides a full observability suite for agents - cloud assist, coding agent. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For developers, this means they have a proper debugging suite for AI agents rather than guessing what went wrong. Google Cloud's observability tools let developers investigate agent failures, understand why an agent misbehaved, and get suggested fixes, so in this case the tool spotted that the simulator agent was hitting Gemini's 1 million token context limit and recommended compressing context more frequently to stay within that boundary.&lt;/p&gt;

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

&lt;p&gt;Google Cloud NEXT made one thing clear: building AI agents is becoming a first class developer experience. You no longer have to stitch together APIs, manually manage context, or guess why your agent broke. Google is giving developers a full stack for agent development, from designing and connecting agents, to giving them memory, to debugging them when things go wrong. The A2A protocol, agent registry, AlloyDB memory, and Cloud observability tools all point in the same direction: agents are becoming software components that developers can build, scale, and maintain just like any other part of their stack. The marathon planner was just a demo but the underlying tools are real and they are ready to be used.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cloudnextchallenge</category>
      <category>googlecloud</category>
      <category>ai</category>
    </item>
    <item>
      <title>Outreachy May, 2026</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Thu, 16 Apr 2026 00:20:49 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/outreachy-may-2026-2b7l</link>
      <guid>https://forem.com/ifeanyichima/outreachy-may-2026-2b7l</guid>
      <description>&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;I have been singing about open-source to my friends for about some time now. I write articles about it. I have done hacktoberfest (twice in 2022 &amp;amp; 2023). It has always been on my mind to take on the big 3 - &lt;strong&gt;MLH, Outreachy and G-Soc&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Outreachy - initial applications
&lt;/h2&gt;

&lt;p&gt;Alright, let me start by saying: "Thank you universe for the reminder at the eleventh hour". This is because I literally forgot that the initial applications for contribution phase for May-August, 2026 Outreachy internship had already started. It opened Feb 6 - Feb 13, 2026. I was only reminded by a random tweet from a stranger on the 11th hour (Feb 13, 2 pm). Applications closed by (Feb 13, 5 pm).&lt;/p&gt;

&lt;h3&gt;
  
  
  Interlude
&lt;/h3&gt;

&lt;p&gt;Once you get selected after the initial applications, you would see different organisations, select the one that suits you best. I chose Mozilla firefox because it required knowledge of HTML, CSS, and JavaScript. &lt;/p&gt;

&lt;h2&gt;
  
  
  Outreachy - Contribution phase
&lt;/h2&gt;

&lt;p&gt;Before you get selected as an intern with Outreachy, you need to take part in the contribution phase which lasts for about three (3) weeks. It actually ends today (March 20 - April 15, 2026). &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%2Fgqmkkgkzixt6pj8hgsdh.gif" 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%2Fgqmkkgkzixt6pj8hgsdh.gif" alt="Wizard meme" width="250" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I learned quickly how to use bugzilla to find issues on my own (I made sure to look out for bugs with the label &lt;code&gt;good-first-issue&lt;/code&gt;) and how to create patches using phabricator. &lt;strong&gt;Bugzilla&lt;/strong&gt; and &lt;strong&gt;Phabricator&lt;/strong&gt; those words sound big and fancy but phrabicator is just a single line of code - &lt;code&gt;moz-phab submit --single&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;here is a sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; bug-2022414-array-profiles

git add &lt;span class="s2"&gt;"file name"&lt;/span&gt;

git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix: migrations for profiles with backup enabled"&lt;/span&gt;

moz-phab submit &lt;span class="nt"&gt;--single&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You submit a patch for a bug, you get feedback or review from a mentor and then you push again.&lt;/p&gt;

&lt;p&gt;One thing I learned, always make sure that you &lt;code&gt;checkout -b&lt;/code&gt; into a new branch from &lt;code&gt;main&lt;/code&gt; so that the branch does not have unrealated histroy from other bugs or commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outreachy - Final Application
&lt;/h2&gt;

&lt;p&gt;In your final application, you would be asked a few questions, you are to write essays answering them, they ask about your experience with the organisation. Also, You need submit a timeline of the work you propose to do during the thirteen week internship. You look at the goal of the organisation and you outline how you intend to approach the task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&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%2Fpe5o7x3k2lwc34hf2n6n.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%2Fpe5o7x3k2lwc34hf2n6n.jpg" alt="Job and Experience meme" width="800" height="809"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My life is literally this meme and the best way to get a job is to have some experience under your belt, which the Outreachy internship will provide. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you, please follow me.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This blog is only a single part, in a multi-series blog that I will write about my experience !!!&lt;/p&gt;

&lt;p&gt;Stay tuned !!!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Useless project.</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Mon, 06 Apr 2026 13:42:06 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/useless-project-371a</link>
      <guid>https://forem.com/ifeanyichima/useless-project-371a</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;A button. Just a button.&lt;/p&gt;

&lt;p&gt;You click it, and lines start crawling across your screen. 50 vertical lines and 50 horizontal lines slowly forming a grid of boxes like graph paper possessed by a ghost. That's it. That's the whole app. No data. No purpose. No redemption arc.&lt;/p&gt;

&lt;p&gt;You can control how many lines appear, how fast they draw, and what color they are. You can also clear the grid and do it all over again, because apparently that's how you want to spend your time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&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%2Fkvb0ol88puo6snf14gp3.gif" 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%2Fkvb0ol88puo6snf14gp3.gif" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/MasterIfeanyi" rel="noopener noreferrer"&gt;
        MasterIfeanyi
      &lt;/a&gt; / &lt;a href="https://github.com/MasterIfeanyi/grid-lines" rel="noopener noreferrer"&gt;
        grid-lines
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Built with pure HTML5 Canvas, vanilla JavaScript, and zero regrets.&lt;/p&gt;

&lt;p&gt;The core idea is simple, the canvas is just a blank piece of paper. I grab a "pencil" using &lt;code&gt;getContext('2d')&lt;/code&gt;, pre-calculate all the x and y positions for each line by dividing the canvas width and height by the number of lines, store them in two arrays (&lt;code&gt;verticals[]&lt;/code&gt; and &lt;code&gt;horizontals[]&lt;/code&gt;), then draw them one by one using &lt;code&gt;setTimeout&lt;/code&gt; so you can actually watch the chaos unfold in real time.&lt;/p&gt;

&lt;p&gt;No frameworks. No libraries. No npm install. Just a canvas, a loop, and a questionable life decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Category
&lt;/h2&gt;

&lt;p&gt;Community Favorite.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Two worlds of mine colliding !</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Wed, 18 Feb 2026 17:30:37 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/two-worlds-of-mine-colliding--24h3</link>
      <guid>https://forem.com/ifeanyichima/two-worlds-of-mine-colliding--24h3</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/devteam/a-new-chapter-dev-is-joining-forces-with-major-league-hacking-mlh-3kfd" class="crayons-story__hidden-navigation-link"&gt;A New Chapter: DEV is Joining Forces with Major League Hacking (MLH)&lt;/a&gt;
    &lt;div class="crayons-article__cover crayons-article__cover__image__feed"&gt;
      &lt;iframe src="https://www.youtube.com/embed/gGUkTiiCqxE" title="A New Chapter: DEV is Joining Forces with Major League Hacking (MLH)"&gt;&lt;/iframe&gt;
    &lt;/div&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/devteam"&gt;
            &lt;img alt="The DEV Team logo" 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%2Forganization%2Fprofile_image%2F1%2Fd908a186-5651-4a5a-9f76-15200bc6801f.jpg" class="crayons-logo__image" width="800" height="800"&gt;
          &lt;/a&gt;

          &lt;a href="/ben" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&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%2Fuser%2Fprofile_image%2F1%2Fbabb96d0-9cd2-49bc-a412-2dc4caf94c2a.png" alt="ben profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ben" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ben Halpern
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ben Halpern
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3265532" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ben" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F1%2Fbabb96d0-9cd2-49bc-a412-2dc4caf94c2a.png" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ben Halpern&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/devteam" class="crayons-story__secondary fw-medium"&gt;The DEV Team&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/devteam/a-new-chapter-dev-is-joining-forces-with-major-league-hacking-mlh-3kfd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/devteam/a-new-chapter-dev-is-joining-forces-with-major-league-hacking-mlh-3kfd" id="article-link-3265532"&gt;
          A New Chapter: DEV is Joining Forces with Major League Hacking (MLH)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/news"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;news&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devto"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devto&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hackathon"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hackathon&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/devteam/a-new-chapter-dev-is-joining-forces-with-major-league-hacking-mlh-3kfd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;389&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/devteam/a-new-chapter-dev-is-joining-forces-with-major-league-hacking-mlh-3kfd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              106&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>news</category>
      <category>devto</category>
      <category>hackathon</category>
      <category>discuss</category>
    </item>
    <item>
      <title>A must read on how to implement GitHub actions.</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Sun, 18 Jan 2026 10:55:01 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/a-must-read-on-how-to-implement-github-actions-2gkk</link>
      <guid>https://forem.com/ifeanyichima/a-must-read-on-how-to-implement-github-actions-2gkk</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ifeanyichima/github-actions-example-29pj" class="crayons-story__hidden-navigation-link"&gt;GitHub actions example&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/ifeanyichima" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F763463%2F9fc4d7f3-908c-400a-b330-7db284158422.jpg" alt="ifeanyichima profile" class="crayons-avatar__image" width="800" height="1067"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ifeanyichima" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ifeanyi Chima
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ifeanyi Chima
                
              
              &lt;div id="story-author-preview-content-1793929" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ifeanyichima" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F763463%2F9fc4d7f3-908c-400a-b330-7db284158422.jpg" class="crayons-avatar__image" alt="" width="800" height="1067"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ifeanyi Chima&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ifeanyichima/github-actions-example-29pj" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 18 '24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ifeanyichima/github-actions-example-29pj" id="article-link-1793929"&gt;
          GitHub actions example
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubactions"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubactions&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ifeanyichima/github-actions-example-29pj" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ifeanyichima/github-actions-example-29pj#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>devops</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Demistifying Nextjs</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Sun, 18 Jan 2026 09:17:22 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/demistifying-nextjs-4ha6</link>
      <guid>https://forem.com/ifeanyichima/demistifying-nextjs-4ha6</guid>
      <description>&lt;p&gt;&lt;em&gt;2026, Happy new year&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's been a while, my dear. I have been learning Nextjs by building an open-source project that is available for everyone to contribute at &lt;a href="https://github.com/MasterIfeanyi/THOR" rel="noopener noreferrer"&gt;THOR&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In this article, I will try to demystify Nextjs&lt;/p&gt;

&lt;p&gt;first, let's lay some ground work or establish some fundamentals. &lt;/p&gt;

&lt;h2&gt;
  
  
  Client vs Server
&lt;/h2&gt;

&lt;p&gt;In Nextjs, you can have 2 types of components, namely (server) and (client) components. The server components will never run in the browser and they can be used to make calls to the backend or even directly to a DB. The client components can and will run in the browser, where you have access to &lt;code&gt;localStorage&lt;/code&gt; and &lt;code&gt;browser window&lt;/code&gt;, it is advisable to not have things such as API keys and secrets in the client components. To make a page a client component, you do this "use client". &lt;/p&gt;



&lt;h2&gt;
  
  
  File based routing
&lt;/h2&gt;

&lt;p&gt;In Nextjs, you have "file-based routing" which means once a folder or file is created in &lt;code&gt;/src/app&lt;/code&gt; directory it becomes a route that can be reached. example if I wanted a "community" route, I would create this &lt;code&gt;/src/app/community/page.js&lt;/code&gt;. This will become a route that you can navigate to. Remember to add "use client", if you want the component to be a client component.&lt;/p&gt;



&lt;h2&gt;
  
  
  _components
&lt;/h2&gt;

&lt;p&gt;In Nextjs, if you do not want certain components / pages that you create to become routes that can be accessed i.e You want to create components such as &lt;code&gt;ToggleButton.jsx&lt;/code&gt;, &lt;code&gt;Sidebar.jsx&lt;/code&gt;, &lt;code&gt;NavbarLayout.jsx&lt;/code&gt;, &lt;code&gt;Avatar.jsx&lt;/code&gt; etc. all of these are components that can be reused but I don't want them to become "routes", you can create a folder like this &lt;code&gt;_components&lt;/code&gt; and every component you create inside that folder will never be route.&lt;/p&gt;



&lt;h2&gt;
  
  
  Fetch API
&lt;/h2&gt;

&lt;p&gt;In Nextjs, if you want to make requests that involves API_KEYS or SECRETS to the backend or database, it is advisable to do that from a server component, and gone are the days of &lt;code&gt;getServerSideProps&lt;/code&gt;, &lt;code&gt;getStaticParams&lt;/code&gt;, and &lt;code&gt;getStaticProps&lt;/code&gt;. now you can just use the native &lt;code&gt;fetch&lt;/code&gt; API in Javascript to make those requests and you can mimic those behaviours using&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;data&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&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;options&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;





&lt;p&gt;Here are some options.&lt;/p&gt;

&lt;p&gt;Want fresh data every time? → &lt;code&gt;cache: 'no-store'&lt;/code&gt; - this used to be &lt;code&gt;getServerSideProps&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Want cached data? → &lt;code&gt;cache: "force-cache"&lt;/code&gt; - default behavior, similar to &lt;code&gt;getStaticProps&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Want periodic revalidation? → &lt;code&gt;next: { revalidate: seconds }&lt;/code&gt; - this used to be &lt;code&gt;getStaticProps&lt;/code&gt; with revalidate (ISR)&lt;/p&gt;

&lt;p&gt;These 3 used to scare me so much, gosh !!!&lt;/p&gt;



&lt;h2&gt;
  
  
  route group
&lt;/h2&gt;

&lt;p&gt;In Nextjs, if you have a bunch of files or folders and you want to group them for organization and readability, you can create a folder like this &lt;code&gt;(docs)&lt;/code&gt;  which will contain all of them to keep your workspace neat. e.g &lt;code&gt;src/app/(docs)/content/page.js&lt;/code&gt;. This way you have many files in one place.&lt;/p&gt;



&lt;h2&gt;
  
  
  Thank you, Please follow me
&lt;/h2&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Navbar scroll event</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Sat, 19 Jul 2025 10:09:31 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/navbar-scroll-event-11do</link>
      <guid>https://forem.com/ifeanyichima/navbar-scroll-event-11do</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92fb8tdk1yh09nfmvg6w.gif" 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%2F92fb8tdk1yh09nfmvg6w.gif" alt=" " width="600" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, I want to show you how I darken the navbar when a user scrolls on the website. &lt;/p&gt;

&lt;h3&gt;
  
  
  THE SECRET
&lt;/h3&gt;

&lt;p&gt;I am using an event listener &lt;code&gt;scroll&lt;/code&gt; which I attached to the navbar to listen for when the user scrolls beyond a certain screen size. This will allow the text on the navbar to be readable.&lt;/p&gt;

&lt;p&gt;Using JavaScript, we add two classes to the navbar &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;bg-dark&lt;/code&gt;: this will give the navbar a dark background. I believe this is an in-built bootstrap class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;slow&lt;/code&gt;: this will add animation to make the navbar slowly darken. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;HTML&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!--NavBar--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar navbar-dark py-3 navbar-expand-lg fixed-top"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-brand"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./img/halo-logo.jpg"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-fluid logo"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-toggler"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-bs-toggle=&lt;/span&gt;&lt;span class="s"&gt;"collapse"&lt;/span&gt; &lt;span class="na"&gt;data-bs-target=&lt;/span&gt;&lt;span class="s"&gt;"#navmenu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-toggler-icon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"collapse navbar-collapse"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"navmenu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-nav me-auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#home"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link active"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;GAMES&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#news"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;NEWS&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#about"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;ESPORTS&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#occupation"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;COMMUNITY&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#occupation"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link linkarrow"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;SUPPORT&lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ri-arrow-right-up-line"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#occupation"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav-link linkarrow"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;GEAR&lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ri-arrow-right-up-line"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#footer"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-brand"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;GET HALO&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CSS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;
&lt;span class="nc"&gt;.slow&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@include&lt;/span&gt; &lt;span class="err"&gt;transition-ease;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@mixin&lt;/span&gt; &lt;span class="n"&gt;transition-ease&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="m"&gt;1.4s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt;&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;nav&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nav&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&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="o"&gt;=&amp;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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slow&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explaination&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;we capture the navbar using DOM manipulation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we add an event listener to the browser window to listen for when a user scrolls beyond 100 vh. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;we add the classes "bg-dark" and "slow" to the navbar.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Thank You, Please Follow me.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Firebase: My negative Experience</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Sat, 05 Jul 2025 21:56:43 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/firebase-my-negative-experience-4ij9</link>
      <guid>https://forem.com/ifeanyichima/firebase-my-negative-experience-4ij9</guid>
      <description>&lt;p&gt;I am working on a website that will allow a user to login and upload images to his website through a dashboard. &lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1
&lt;/h2&gt;

&lt;p&gt;The first issue that I ran into was firebase SDK. I could not use npm packages directly in HTML/CSS. I had to use firebase SDK like 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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initializeApp&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;https://www.gstatic.com/firebasejs/11.8.1/firebase-app.js&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;getAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onAuthStateChanged&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;https://www.gstatic.com/firebasejs/11.8.1/firebase-auth.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Here is a Fix:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Upgrade Firebase SDK - Make sure you're using the latest versions:&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problem 2
&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;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// authDomain: "oleru-young.firebaseapp.com",&lt;/span&gt;
    &lt;span class="c1"&gt;// storageBucket: "oleru-young.firebasestorage.app",&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;After enabling Storage, you'll see the bucket name in the Firebase Console. It will look like one of these:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;oleru-young.appspot.com&lt;/code&gt; (older format)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;oleru-young.firebasestorage.app&lt;/code&gt; (newer format)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This caused a lot of confusion, if you were wondering the &lt;strong&gt;newer format&lt;/strong&gt; is the correct thing to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 3
&lt;/h2&gt;

&lt;p&gt;CORS - I had to battle with this 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="nx"&gt;Access&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;XMLHttpRequest&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://firebasestorage.googleapis.com/v0/b/oleru-young.appspot.com/o?name=uploads%2F11f20756a8694b63b7ee0645cde15e2e.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:5500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;has&lt;/span&gt; &lt;span class="nx"&gt;been&lt;/span&gt; &lt;span class="nx"&gt;blocked&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;CORS&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;preflight&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;doesn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t pass access control check: It does not have HTTP ok status.

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

&lt;/div&gt;



&lt;p&gt;means your browser is blocking the request to Firebase Storage due to a CORS (Cross-Origin Resource Sharing) issue. Here’s how to fix it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Here is a fix
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;cors.json&lt;/code&gt; file in your VScode project and add the following syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "origin": ["*"],
    "method": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    "maxAgeSeconds": 3600,
    "responseHeader": ["Content-Type", "Authorization"]
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using your terminal in VScode, you need to login to google cloud by using the terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're working on a project and want to set the active project after logging in, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud config &lt;span class="nb"&gt;set &lt;/span&gt;project &lt;span class="o"&gt;[&lt;/span&gt;PROJECT_ID]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace [PROJECT_ID] with your actual Google Cloud project ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CORS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set the CORS policy for your project by running this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
gcloud storage buckets update gs://[PROJECT_ID].firebasestorage.app &lt;span class="nt"&gt;--cors-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;cors.json

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problem 4
&lt;/h2&gt;

&lt;p&gt;Firebase Storage Rules&lt;/p&gt;

&lt;p&gt;You need to set the rules for the bucket. When you are creating the bucket for the first time. You need to choose &lt;code&gt;test mode&lt;/code&gt;. This will allow read and write access to the bucket for up to 30 days. &lt;/p&gt;

&lt;p&gt;A firebase bucket looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rules_version = '2';


service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if true;
    }
  }
}

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Use something permissive for testing (not production-safe):&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Google Cloud Auth Issue</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Sun, 01 Jun 2025 12:10:16 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/google-cloud-auth-issue-2eo1</link>
      <guid>https://forem.com/ifeanyichima/google-cloud-auth-issue-2eo1</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Copying file://kitten.png [Content-Type=image/png]... ServiceException: 401 Anonymous caller does not have storage.objects.create access to the Google Cloud Storage object. Permission 'storage.objects.create' denied on resource (or it may not exist).

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Steps to recreate it.
&lt;/h2&gt;

&lt;p&gt;Having this issue while trying to copy a file to a new cloud storage bucket. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download a cat image 
This will download the image for us.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget https://cloud.google.com/storage/images/kitten.png

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Try to copy the image to my cloud storage bucket
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gsutil cp kitten.png gs://gcp-ifeanyi-tutorial

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

&lt;/div&gt;



&lt;p&gt;Now, we run into the issue stated above. &lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to Resolve
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth login

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Open your terminal and login to google cloud&lt;/li&gt;
&lt;li&gt;Follow the prompt (Type Y for yes)&lt;/li&gt;
&lt;li&gt;Copy the link provided in your browser&lt;/li&gt;
&lt;li&gt;Select your google account and grant permission&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;After following the prompt you will be provided with a key that looks like this&lt;br&gt;
&lt;em&gt;4/9ANIR-c9k6BnlT ..........&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Copy the key and paste it in your google cloud console&lt;/li&gt;
&lt;li&gt;Try to run the previous command again
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gsutil cp kitten.png gs://gcp-ifeanyi-tutorial

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

&lt;/div&gt;



</description>
      <category>cloud</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Load-balancing using docker and nginx</title>
      <dc:creator>Ifeanyi Chima</dc:creator>
      <pubDate>Mon, 17 Mar 2025 16:07:07 +0000</pubDate>
      <link>https://forem.com/ifeanyichima/load-balancing-using-docker-and-nginx-16p7</link>
      <guid>https://forem.com/ifeanyichima/load-balancing-using-docker-and-nginx-16p7</guid>
      <description>&lt;p&gt;Let me be clear this article is not a tutorial on NGINX or Docker. Just how to setup Load-balancing using both (Nginx and Docker). I will be assuming pre-requiste knowledge of both subjects.&lt;/p&gt;

&lt;p&gt;In this article, we will be looking at how to achieve load-balancing using nginx and docker. well, what exactly is &lt;strong&gt;nginx&lt;/strong&gt; and what is &lt;strong&gt;docker&lt;/strong&gt; ? &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%2F8eupukop7v97kxk611yp.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%2F8eupukop7v97kxk611yp.jpg" alt=" " width="176" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding Load-balancing&lt;/strong&gt; - A website can have millions of requests, which can cause a bottleneck and make the latency (response time) slow. We need a way to handle the millions of request, to do this we need to increase the number of servers. &lt;/p&gt;

&lt;h3&gt;
  
  
  NGINX
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nginx&lt;/strong&gt; - is a web server that serves us web content.&lt;/p&gt;

&lt;p&gt;Nginx can forward a user request to an available server. This is called (load balancing). Nginx chooses which server will handle user request at each time.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nginx.conf&lt;/code&gt; - the file to setup nginx&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;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backendserver&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# here, we can specify all the backend url, that we have.&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;9000&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;9001&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;9002&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kn"&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;8080&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://backendserver/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;cd nginx - nginx&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To start the nginx server&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt; - is a way to package your application, as a developer. This way another developer can quickly setup same application on their system without running into a lot of issues and errors along the way. A dockerfile comes with all of the necessary instructions needed to setup said application.&lt;/p&gt;

&lt;p&gt;Now, Docker can host a nodejs web-server inside of a container for you, this way we can run multiple servers at once, just by spinning up multiple instances of docker containers.&lt;/p&gt;

&lt;p&gt;I ran into a major problem when using dockerfile to spin up my containers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Problem 1
&lt;/h1&gt;

&lt;p&gt;The index.js file has changed, do I need to rebuild the dockerfile and if I do that, would I need to re-create new containers based off on the new docker image&lt;/p&gt;

&lt;h3&gt;
  
  
  Answer
&lt;/h3&gt;

&lt;p&gt;The answer to that question was &lt;strong&gt;Yes&lt;/strong&gt;, if the index.js file has changed, you need to rebuild the Docker image to include the updated code. After rebuilding the Docker image, you will need to recreate the containers based on the new image to run the updated code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Doing this everytime feels repetitive and tiring.&lt;/strong&gt; &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%2Foqy2ssa28zuxcnfdl9oa.gif" 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%2Foqy2ssa28zuxcnfdl9oa.gif" alt=" " width="220" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Problem 2
&lt;/h1&gt;

&lt;p&gt;Is there a way to automatically restarting your container every time a file has changed without the need to rebuild your image each time ?&lt;/p&gt;

&lt;h3&gt;
  
  
  Answer
&lt;/h3&gt;

&lt;p&gt;The answer to that question was &lt;strong&gt;Yes&lt;/strong&gt;, we have two ways or options to do that &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Docker Compose&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mount Volumes&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would be looking into the second option for today, you can use Docker volumes to mount your local directory into the container. This way, any changes you make to your local files will be reflected in the running container without needing to rebuild the image.&lt;/p&gt;

&lt;p&gt;So, we need a dockerfile that would contain information about the web-server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Uses node version 16 as our base image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:16&lt;/span&gt;

&lt;span class="c"&gt;# Create app directory inside the docker image&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;

&lt;span class="c"&gt;# Copy package.json into the app directory of the docker image&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Copy our entire code into the app directory of the docker image&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;


&lt;span class="c"&gt;# Install nodemon globally&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; nodemon

&lt;span class="c"&gt;# expose port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# Run app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nodemon", "--legacy-watch", "index.js"]&lt;/span&gt;

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

&lt;/div&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%2Fb1mumjhniwd4gvdb0blx.gif" 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%2Fb1mumjhniwd4gvdb0blx.gif" alt=" " width="220" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I need to explain the dockerfile a bit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nodemon", "--legacy-watch", "index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will ensure that nodemon automatically restarts the container when we make changes to our nodejs code locally.&lt;/p&gt;

&lt;p&gt;Now, we can carry on.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the Docker image:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt; docker build -t node-application .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the container with a volume mount:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We would have two docker containers running, so we would run this command twice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(-e CONTAINER_NAME=web1):&lt;/strong&gt; This is the environment variable to help us distinguish between each container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(--name web1):&lt;/strong&gt; This is the name of the container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(-p 9001:3000):&lt;/strong&gt; This is port-mapping, we expose the container's port (3000) to our local computer port (9000).&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;docker run -d -p 9001:3000 --name web1 -v C:\Users\PC\Documents\Documents\2025\nginx_tuts\server:/usr/src/app -e CONTAINER_NAME=web1 node-application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Nodejs
&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;const&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;/&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;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="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;`This endpoint &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;CONTAINER_NAME&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was hit`&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello World from &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;CONTAINER_NAME&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;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;Server is running on port 3000&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;This is how my &lt;strong&gt;basic&lt;/strong&gt; nodejs-express server was setup&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%2Fz2xa5tfn4umxwfgylqf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2xa5tfn4umxwfgylqf4.png" alt=" " width="252" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Thank you, please follow me
&lt;/h3&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
