<?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: Ikegbo Ogochukwu</title>
    <description>The latest articles on Forem by Ikegbo Ogochukwu (@kenryikegbo).</description>
    <link>https://forem.com/kenryikegbo</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%2F419033%2Faae23086-d49c-46ab-9295-3d17f2c343b4.png</url>
      <title>Forem: Ikegbo Ogochukwu</title>
      <link>https://forem.com/kenryikegbo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kenryikegbo"/>
    <language>en</language>
    <item>
      <title>How to Change Wi-Fi Details on a Headless Raspberry Pi When You Don’t Know the Current Network</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Fri, 08 May 2026 12:05:34 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/-how-to-change-wi-fi-details-on-a-headless-raspberry-pi-when-you-dont-know-the-current-network-375l</link>
      <guid>https://forem.com/kenryikegbo/-how-to-change-wi-fi-details-on-a-headless-raspberry-pi-when-you-dont-know-the-current-network-375l</guid>
      <description>&lt;p&gt;If you’ve ever worked with a headless Raspberry Pi, you’ve probably faced this problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Raspberry Pi was previously connected to a Wi-Fi network&lt;/li&gt;
&lt;li&gt;You do not know which network it is connected to&lt;/li&gt;
&lt;li&gt;You cannot connect a monitor, keyboard, or mouse&lt;/li&gt;
&lt;li&gt;SSH is your only option&lt;/li&gt;
&lt;li&gt;The Pi is no longer appearing on your current network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This usually happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You move to a new location&lt;/li&gt;
&lt;li&gt;Your Wi-Fi name/password changes&lt;/li&gt;
&lt;li&gt;Someone else configured the Pi&lt;/li&gt;
&lt;li&gt;You forgot the old network credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this guide, I’ll show you how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Diagnose the problem&lt;/li&gt;
&lt;li&gt;Reconfigure Wi-Fi without a monitor&lt;/li&gt;
&lt;li&gt;Force the Pi onto a new network&lt;/li&gt;
&lt;li&gt;Recover SSH access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The methods below work for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi 3&lt;/li&gt;
&lt;li&gt;Raspberry Pi 4&lt;/li&gt;
&lt;li&gt;Raspberry Pi 5&lt;/li&gt;
&lt;li&gt;Raspberry Pi Zero W/2W&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Understanding the Problem
&lt;/h1&gt;

&lt;p&gt;A Raspberry Pi configured for headless access boots and automatically tries to connect to the Wi-Fi credentials saved inside:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the saved Wi-Fi no longer exists&lt;/li&gt;
&lt;li&gt;the password changed&lt;/li&gt;
&lt;li&gt;or the Pi is too far from the router&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then the Pi never joins the network.&lt;/p&gt;

&lt;p&gt;Since SSH depends on network access, you lose remote control completely.&lt;/p&gt;




&lt;h1&gt;
  
  
  Method 1 — Edit Wi-Fi Credentials Directly from the SD Card (Best Method)
&lt;/h1&gt;

&lt;p&gt;This is the fastest recovery method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Remove the SD Card
&lt;/h2&gt;

&lt;p&gt;Power off the Raspberry Pi safely.&lt;/p&gt;

&lt;p&gt;Remove the microSD card and insert it into your computer using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SD card reader&lt;/li&gt;
&lt;li&gt;USB adapter&lt;/li&gt;
&lt;li&gt;laptop SD slot&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Step 2 — Open the Boot Partition
&lt;/h1&gt;

&lt;p&gt;After inserting the SD card, you’ll see a small partition called:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boot&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bootfs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open it.&lt;/p&gt;

&lt;p&gt;This partition is readable on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;li&gt;Linux&lt;/li&gt;
&lt;li&gt;macOS&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Step 3 — Create or Edit &lt;code&gt;wpa_supplicant.conf&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Inside the boot partition, create a file named:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If it already exists, edit it.&lt;/p&gt;

&lt;p&gt;Paste this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NG
&lt;span class="nv"&gt;ctrl_interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/run/wpa_supplicant &lt;span class="nv"&gt;GROUP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;netdev
&lt;span class="nv"&gt;update_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

&lt;span class="nv"&gt;network&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;
    &lt;span class="nv"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_WIFI_NAME"&lt;/span&gt;
    &lt;span class="nv"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_WIFI_PASSWORD"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NG
&lt;span class="nv"&gt;ctrl_interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/run/wpa_supplicant &lt;span class="nv"&gt;GROUP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;netdev
&lt;span class="nv"&gt;update_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

&lt;span class="nv"&gt;network&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;
    &lt;span class="nv"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"MTN_Home"&lt;/span&gt;
    &lt;span class="nv"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mysecurepassword"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Why &lt;code&gt;country=NG&lt;/code&gt; Matters
&lt;/h1&gt;

&lt;p&gt;A lot of people ignore this.&lt;/p&gt;

&lt;p&gt;The country code controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wi-Fi regulatory channels&lt;/li&gt;
&lt;li&gt;allowed radio frequencies&lt;/li&gt;
&lt;li&gt;transmission compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your country code is wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wi-Fi may fail silently&lt;/li&gt;
&lt;li&gt;some channels become inaccessible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Nigeria, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;country&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;unless you are actually in the US.&lt;/p&gt;




&lt;p&gt;Do You Need to Remove Old Wi-Fi Networks?&lt;/p&gt;

&lt;p&gt;Usually, no.&lt;/p&gt;

&lt;p&gt;The Raspberry Pi can store multiple Wi-Fi networks and automatically connect to whichever known network is available.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;network&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;
    &lt;span class="nv"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Old_Wifi"&lt;/span&gt;
    &lt;span class="nv"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"oldpassword"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;network&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;
    &lt;span class="nv"&gt;ssid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"New_Wifi"&lt;/span&gt;
    &lt;span class="nv"&gt;psk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"newpassword"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Old_Wifi is unavailable, the Pi will try New_Wifi.&lt;/p&gt;

&lt;p&gt;When Should You Remove Old Networks?&lt;/p&gt;

&lt;p&gt;You may want to remove old saved networks if:&lt;/p&gt;

&lt;p&gt;The Pi keeps reconnecting to the wrong network&lt;br&gt;
Multiple nearby networks are available&lt;br&gt;
The old Wi-Fi has poor internet access&lt;br&gt;
You want cleaner configuration management&lt;br&gt;
You are deploying the Pi to a new environment permanently&lt;/p&gt;

&lt;p&gt;In that case, simply delete the old network={} block from:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;and leave only the new network.&lt;/p&gt;

&lt;p&gt;Best Practice&lt;/p&gt;

&lt;p&gt;For classroom projects, IoT deployments, and Raspberry Pi labs, it is usually better to:&lt;/p&gt;

&lt;p&gt;remove outdated Wi-Fi networks&lt;br&gt;
keep only the active network&lt;br&gt;
avoid connection conflicts&lt;/p&gt;

&lt;p&gt;This makes troubleshooting much easier later.&lt;/p&gt;
&lt;h1&gt;
  
  
  Step 4 — Enable SSH
&lt;/h1&gt;

&lt;p&gt;Still inside the boot partition:&lt;/p&gt;

&lt;p&gt;Create an empty file named:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;No extension.&lt;/p&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ssh.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssh.conf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This enables the SSH server during boot.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 5 — Reinsert SD Card and Boot
&lt;/h1&gt;

&lt;p&gt;Insert the SD card back into the Raspberry Pi.&lt;/p&gt;

&lt;p&gt;Power it on.&lt;/p&gt;

&lt;p&gt;Wait about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1–3 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for the Pi to boot and connect.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 6 — Find the Raspberry Pi on the Network
&lt;/h1&gt;

&lt;p&gt;Now you need the Pi’s IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option A — Use Fing (Recommended)
&lt;/h2&gt;

&lt;p&gt;Install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fing (Android/iPhone)&lt;/li&gt;
&lt;li&gt;Fing Desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scan your network.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;raspberrypi&lt;/li&gt;
&lt;li&gt;Raspberry Pi Foundation&lt;/li&gt;
&lt;li&gt;hostname you configured&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Option B — Use Router Admin Page
&lt;/h2&gt;

&lt;p&gt;Login to your router.&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connected Devices&lt;/li&gt;
&lt;li&gt;DHCP Clients&lt;/li&gt;
&lt;li&gt;LAN Devices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may see:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;or an IP like:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Option C — Use &lt;code&gt;ping&lt;/code&gt;
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping raspberrypi.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping yourhostname.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Step 7 — SSH Into the Pi
&lt;/h1&gt;

&lt;p&gt;Once you have the IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh pi@192.168.1.12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh username@hostname.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh stanley@raspberrypi.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  What If You Don’t Know the Username?
&lt;/h1&gt;

&lt;p&gt;Modern Raspberry Pi OS no longer uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;raspberry&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;by default.&lt;/p&gt;

&lt;p&gt;The username is whatever was set during OS imaging.&lt;/p&gt;

&lt;p&gt;If you forgot it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reflash the OS&lt;/li&gt;
&lt;li&gt;or inspect old documentation&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Method 2 — Reflash Using Raspberry Pi Imager (Cleanest Option)
&lt;/h1&gt;

&lt;p&gt;If recovery fails completely, just rewrite the OS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Raspberry Pi Imager
&lt;/h2&gt;

&lt;p&gt;Download from:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.raspberrypi.com/software/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Raspberry Pi Imager&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Configure Headless Setup Properly
&lt;/h1&gt;

&lt;p&gt;Inside Raspberry Pi Imager:&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEXT → EDIT SETTINGS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure:&lt;/p&gt;

&lt;h2&gt;
  
  
  General
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hostname&lt;/li&gt;
&lt;li&gt;Username&lt;/li&gt;
&lt;li&gt;Password&lt;/li&gt;
&lt;li&gt;Wi-Fi SSID&lt;/li&gt;
&lt;li&gt;Wi-Fi Password&lt;/li&gt;
&lt;li&gt;Country&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Services
&lt;/h2&gt;

&lt;p&gt;Enable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Password authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then write the OS.&lt;/p&gt;

&lt;p&gt;This is the most reliable method.&lt;/p&gt;




&lt;h1&gt;
  
  
  Troubleshooting Tips
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Pi Not Appearing on Network
&lt;/h2&gt;

&lt;p&gt;Possible causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wrong Wi-Fi password&lt;/li&gt;
&lt;li&gt;Wrong country code&lt;/li&gt;
&lt;li&gt;Weak Wi-Fi signal&lt;/li&gt;
&lt;li&gt;5GHz unsupported network&lt;/li&gt;
&lt;li&gt;Hidden SSID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mobile hotspot&lt;/li&gt;
&lt;li&gt;2.4GHz Wi-Fi&lt;/li&gt;
&lt;li&gt;moving Pi closer&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  2. SSH “Hostname Could Not Be Resolved”
&lt;/h1&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the Pi is not on the network&lt;/li&gt;
&lt;li&gt;or mDNS isn’t working&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use direct IP instead.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. SSH Connection Refused
&lt;/h1&gt;

&lt;p&gt;Usually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSH disabled&lt;/li&gt;
&lt;li&gt;Pi still booting&lt;/li&gt;
&lt;li&gt;firewall issue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recreate the empty &lt;code&gt;ssh&lt;/code&gt; file.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Raspberry Pi Only Supports 2.4GHz
&lt;/h1&gt;

&lt;p&gt;Some older Pis cannot use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5GHz&lt;/li&gt;
&lt;li&gt;Wi-Fi 6 only networks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mixed mode&lt;/li&gt;
&lt;li&gt;2.4GHz compatibility&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Bonus Tip — Use Your Phone Hotspot
&lt;/h1&gt;

&lt;p&gt;If you don’t know the old network:&lt;/p&gt;

&lt;p&gt;Create a hotspot using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;same Wi-Fi name&lt;/li&gt;
&lt;li&gt;same password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as the old network.&lt;/p&gt;

&lt;p&gt;The Pi may reconnect automatically.&lt;/p&gt;

&lt;p&gt;This is one of the fastest recovery tricks.&lt;/p&gt;




&lt;h1&gt;
  
  
  Recommended Headless Workflow
&lt;/h1&gt;

&lt;p&gt;Here’s the workflow I now use for every Raspberry Pi deployment:&lt;/p&gt;

&lt;h2&gt;
  
  
  During OS Imaging
&lt;/h2&gt;

&lt;p&gt;Always configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hostname&lt;/li&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;li&gt;Wi-Fi&lt;/li&gt;
&lt;li&gt;username/password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;inside Raspberry Pi Imager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep Backup Notes
&lt;/h2&gt;

&lt;p&gt;Save:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hostname&lt;/li&gt;
&lt;li&gt;username&lt;/li&gt;
&lt;li&gt;password&lt;/li&gt;
&lt;li&gt;Wi-Fi used&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;inside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notion&lt;/li&gt;
&lt;li&gt;Google Docs&lt;/li&gt;
&lt;li&gt;password manager&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use Static Hostnames
&lt;/h2&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cv-group1
iot-node2
weather-station
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes network discovery easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Headless Raspberry Pi setups are incredibly powerful, but Wi-Fi issues can lock you out completely if you don’t plan ahead.&lt;/p&gt;

&lt;p&gt;The good news is:&lt;br&gt;
you usually do NOT need a monitor.&lt;/p&gt;

&lt;p&gt;As long as you can access the SD card, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;change Wi-Fi&lt;/li&gt;
&lt;li&gt;enable SSH&lt;/li&gt;
&lt;li&gt;recover the device&lt;/li&gt;
&lt;li&gt;regain remote access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you master this workflow, managing remote Raspberry Pis becomes much easier — especially in classrooms, IoT deployments, robotics projects, and AI edge systems.&lt;/p&gt;

&lt;p&gt;Happy building 🚀&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>ai</category>
      <category>iot</category>
      <category>micropython</category>
    </item>
    <item>
      <title>API Keys vs. Access Tokens: What's the Real Difference?</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Wed, 06 May 2026 13:39:41 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/api-keys-vs-access-tokens-whats-the-real-difference-1fbd</link>
      <guid>https://forem.com/kenryikegbo/api-keys-vs-access-tokens-whats-the-real-difference-1fbd</guid>
      <description>&lt;p&gt;As a developer, you’ve definitely seen them: &lt;code&gt;x-api-key&lt;/code&gt;, &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;, and &lt;code&gt;Personal Access Tokens&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you've ever wondered if they are just different names for the same thing—&lt;strong&gt;they aren't.&lt;/strong&gt; Using the wrong one can leave your app wide open to security risks.&lt;/p&gt;

&lt;p&gt;Here is the "explain like I'm five" breakdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 The API Key: The "Project ID Card"
&lt;/h2&gt;

&lt;p&gt;Think of an &lt;strong&gt;API Key&lt;/strong&gt; as a static ID card for an entire project or application. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Who is it?&lt;/strong&gt; It identifies the &lt;em&gt;application&lt;/em&gt; (e.g., "This request is coming from the WeatherDashboard app").&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Life Span:&lt;/strong&gt; Long-lived. It usually doesn't expire unless you manually rotate it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Best for:&lt;/strong&gt; Accessing public data (maps, weather) or simple server-to-server tasks where no specific user login is required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Usage:&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="c1"&gt;// Simple but less secure - anyone with the key can use it.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://weather.com{YOUR_API_KEY}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎟️ The Access Token: The "Visitor Badge"
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;Access Token&lt;/strong&gt; (like a &lt;a href="https://dev.to/authress/api-authentication-creating-service-client-api-keys-25i6"&gt;JWT&lt;/a&gt;) is more like a temporary visitor badge. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Who is it?&lt;/strong&gt; It identifies the &lt;em&gt;specific user&lt;/em&gt; and what they are allowed to do.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Life Span:&lt;/strong&gt; Short-lived. It expires quickly (often in 1 hour) and needs a "refresh" to stay active.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Best for:&lt;/strong&gt; Private user data (Gmail, Spotify, Banking). It ensures that even if a token is stolen, the damage is limited by time and scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📊 Side-by-Side Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;API Key&lt;/th&gt;
&lt;th&gt;Access Token&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Identifies&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The Application&lt;/td&gt;
&lt;td&gt;The User&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Expiration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Usually Permanent&lt;/td&gt;
&lt;td&gt;Short-lived (Expires)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low (Static)&lt;/td&gt;
&lt;td&gt;High (Dynamic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Common Flow&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generated in a Portal&lt;/td&gt;
&lt;td&gt;Generated via Login (OAuth)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  💡 When to use which?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use an &lt;a href="https://dev.to/codeparrot/api-keys-vs-tokens-theyre-not-the-same-thing-41fi"&gt;API Key&lt;/a&gt; when:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You are calling a public service (like Google Maps).&lt;/li&gt;
&lt;li&gt;You need to track usage for billing (e.g., "App X used 1,000 requests").&lt;/li&gt;
&lt;li&gt;You are doing internal server-to-server communication in a trusted environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Use an &lt;a href="https://dev.to/saif_shines/migrating-from-api-keys-to-oauth-2h40"&gt;Access Token&lt;/a&gt; when:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You are dealing with user-specific data (e.g., reading &lt;em&gt;my&lt;/em&gt; emails).&lt;/li&gt;
&lt;li&gt;Security is a priority (you want the credential to expire).&lt;/li&gt;
&lt;li&gt;You need "granular permissions" (e.g., "This app can read my profile but NOT post for me").&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🛡️ Pro-tip: Never Hardcode!
&lt;/h2&gt;

&lt;p&gt;Whether you use a key or a token, &lt;strong&gt;never&lt;/strong&gt; commit them to GitHub. Always use &lt;a href="https://dev.to/kylejb/how-should-you-secure-your-api-token-2odl"&gt;environment variables&lt;/a&gt; and a &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are you currently using in your latest project? Drop a comment below! 👇&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>🚀 Setting Up Raspberry Pi &amp; Camera for AI Projects (Complete Command Guide)</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Mon, 04 May 2026 18:34:12 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/setting-up-raspberry-pi-camera-for-ai-projects-complete-command-guide-340g</link>
      <guid>https://forem.com/kenryikegbo/setting-up-raspberry-pi-camera-for-ai-projects-complete-command-guide-340g</guid>
      <description>&lt;p&gt;If you're working with a Raspberry Pi for computer vision or AI projects, getting everything set up can be confusing—especially with newer devices like the Raspberry Pi 5.&lt;/p&gt;

&lt;p&gt;This guide compiles &lt;strong&gt;all essential commands&lt;/strong&gt; used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up your Raspberry Pi&lt;/li&gt;
&lt;li&gt;Configuring network access&lt;/li&gt;
&lt;li&gt;Enabling remote control&lt;/li&gt;
&lt;li&gt;Troubleshooting camera issues&lt;/li&gt;
&lt;li&gt;Capturing images&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🧠 1. System Setup &amp;amp; Updates
&lt;/h1&gt;

&lt;p&gt;Before doing anything, your system should be updated:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h1&gt;
  
  
  🌐 2. Network &amp;amp; IP Configuration
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Check IP address
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 This is needed for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSH connection&lt;/li&gt;
&lt;li&gt;VNC connection&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔐 3. Remote Access Setup
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Enable SSH and VNC
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;raspi-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then navigate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Interface Options → Enable SSH
Interface Options → Enable VNC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Connect via SSH
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh pi@&amp;lt;IP_ADDRESS&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh pi@192.168.43.25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🖥️ 4. VNC (Remote Desktop Access)
&lt;/h1&gt;

&lt;p&gt;Used when you want full GUI access from your laptop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Enable VNC (see above)&lt;/li&gt;
&lt;li&gt;Install VNC Viewer on your laptop&lt;/li&gt;
&lt;li&gt;Connect using:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;






&lt;h1&gt;
  
  
  📸 5. Camera System (Important Update)
&lt;/h1&gt;

&lt;p&gt;On modern Raspberry Pi OS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Camera is enabled by default (libcamera system)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 You will NOT see "Camera" in raspi-config anymore.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧪 6. Test Camera
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Preview camera
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;👉 Works only on GUI (monitor or VNC)&lt;/p&gt;




&lt;h2&gt;
  
  
  Capture image
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rpicam-still &lt;span class="nt"&gt;-o&lt;/span&gt; test.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Record video
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rpicam-vid &lt;span class="nt"&gt;-t&lt;/span&gt; 5000 &lt;span class="nt"&gt;-o&lt;/span&gt; video.h264
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  📂 7. File Management Commands
&lt;/h1&gt;

&lt;h2&gt;
  
  
  List files
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create folder
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;dataset
&lt;span class="nb"&gt;cd &lt;/span&gt;dataset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🔁 8. Capture Multiple Images
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;1..10&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;rpicam-still &lt;span class="nt"&gt;-o&lt;/span&gt; img_&lt;span class="nv"&gt;$i&lt;/span&gt;.jpg&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;sleep &lt;/span&gt;2&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🖼️ 9. Open Image (on Raspberry Pi GUI)
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xdg-open test.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🧪 10. Python + OpenCV Setup
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Start Python
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Import OpenCV
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Load image
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Resize image
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;resized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resized.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Convert to grayscale
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;gray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cvtColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COLOR_BGR2GRAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gray.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Convert to HSV
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;hsv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cvtColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COLOR_BGR2HSV&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hsv.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hsv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Exit Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ⚠️ 11. Common Troubleshooting
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Camera not working?
&lt;/h2&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cable orientation&lt;/li&gt;
&lt;li&gt;Proper connection&lt;/li&gt;
&lt;li&gt;Correct port (Pi 5 has 2 ports)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  No preview?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSH = No preview
VNC/Monitor = Preview works
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Restart system
&lt;/h2&gt;



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

&lt;/div&gt;






&lt;h1&gt;
  
  
  🧠 Key Takeaways
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✔ Raspberry Pi OS now uses libcamera
✔ No manual camera enable needed
✔ rpicam-* commands replace raspistill
✔ SSH is for control, not display
✔ VNC gives full desktop access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🎯 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Once your Raspberry Pi and camera are set up:&lt;/p&gt;

&lt;p&gt;👉 You are ready to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collect image datasets&lt;/li&gt;
&lt;li&gt;Train AI models&lt;/li&gt;
&lt;li&gt;Deploy computer vision applications&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔥 If you found this useful
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Drop a ❤️&lt;/li&gt;
&lt;li&gt;Share with someone learning Raspberry Pi&lt;/li&gt;
&lt;li&gt;Follow for more AI + Embedded Systems content&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>ai</category>
      <category>computervision</category>
      <category>raspberrypi</category>
      <category>iot</category>
    </item>
    <item>
      <title>COMPLETE COURSE: Git &amp; GitHub (From Zero to Advanced)</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Thu, 30 Apr 2026 17:59:55 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/complete-course-git-github-from-zero-to-advanced-14e4</link>
      <guid>https://forem.com/kenryikegbo/complete-course-git-github-from-zero-to-advanced-14e4</guid>
      <description>&lt;h2&gt;
  
  
  📘 COURSE OVERVIEW
&lt;/h2&gt;

&lt;p&gt;This course gives you a &lt;strong&gt;rock-solid foundation&lt;/strong&gt; in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git (local version control)&lt;/li&gt;
&lt;li&gt;GitHub (remote collaboration)&lt;/li&gt;
&lt;li&gt;Real-world workflows (branching, merging, collaboration)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Git = tracks changes locally&lt;br&gt;
GitHub = cloud platform for collaboration&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  🧩 MODULE 1: WHAT IS GIT?
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Definition
&lt;/h2&gt;

&lt;p&gt;Git is a &lt;strong&gt;Version Control System (VCS)&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracks every change in your files&lt;/li&gt;
&lt;li&gt;Stores history (who, when, what changed)&lt;/li&gt;
&lt;li&gt;Allows rollback to previous versions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tracks &lt;strong&gt;any file type&lt;/strong&gt; (code, text, images, videos)&lt;/li&gt;
&lt;li&gt;Maintains &lt;strong&gt;multiple versions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enables &lt;strong&gt;safe experimentation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 Real-world Problem Git Solves
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;Build a project → client likes it&lt;/li&gt;
&lt;li&gt;Update it → client wants old version&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Without Git → you're stuck&lt;br&gt;
👉 With Git → you restore instantly&lt;/p&gt;




&lt;h1&gt;
  
  
  🔗 MODULE 2: GIT vs GITHUB
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Git
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Local tool&lt;/li&gt;
&lt;li&gt;Runs on your computer&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 GitHub
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cloud platform&lt;/li&gt;
&lt;li&gt;Stores repositories online&lt;/li&gt;
&lt;li&gt;Enables collaboration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 Analogy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Git = coffee ☕&lt;/li&gt;
&lt;li&gt;GitHub = coffee shop 🏪&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 Alternatives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitLab&lt;/li&gt;
&lt;li&gt;Bitbucket&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🏗️ MODULE 3: GIT ARCHITECTURE
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Two Parts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Local&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote (GitHub)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔹 Workflow Stages
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Working Directory&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Where you edit files&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Staging Area&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Temporary holding area&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Repository&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Permanent storage (commit history)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔁 Workflow Summary
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Working Directory → Staging Area → Local Repo → Remote Repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ⚙️ MODULE 4: INSTALLING GIT
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to official Git website&lt;/li&gt;
&lt;li&gt;Download for:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Windows (32/64-bit)&lt;/li&gt;
&lt;li&gt;Mac (Homebrew)&lt;/li&gt;
&lt;li&gt;Linux&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 Verify Installation
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;✔ If installed → shows version&lt;br&gt;
❌ Else → error&lt;/p&gt;




&lt;h1&gt;
  
  
  💻 MODULE 5: TERMINAL BASICS
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Important Commands (NOT Git commands)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;       &lt;span class="c"&gt;# change directory&lt;/span&gt;
&lt;span class="nb"&gt;pwd&lt;/span&gt;      &lt;span class="c"&gt;# show current path&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt;    &lt;span class="c"&gt;# create folder&lt;/span&gt;
&lt;span class="nb"&gt;touch&lt;/span&gt;    &lt;span class="c"&gt;# create file&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt;       &lt;span class="c"&gt;# list files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  📁 MODULE 6: CREATING A PROJECT
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Steps
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Desktop
&lt;span class="nb"&gt;mkdir &lt;/span&gt;git-1
&lt;span class="nb"&gt;cd &lt;/span&gt;git-1

&lt;span class="nb"&gt;touch &lt;/span&gt;1.txt
&lt;span class="nb"&gt;touch &lt;/span&gt;2.txt

&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-folder
&lt;span class="nb"&gt;cd &lt;/span&gt;my-folder
&lt;span class="nb"&gt;touch &lt;/span&gt;3.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 MODULE 7: INITIALIZING GIT
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Command
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 What Happens
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Creates hidden &lt;code&gt;.git&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;Git starts tracking project
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Shows &lt;code&gt;.git&lt;/code&gt; folder&lt;/p&gt;




&lt;h1&gt;
  
  
  🌐 MODULE 8: GITHUB REPOSITORY
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to GitHub&lt;/li&gt;
&lt;li&gt;Create new repo&lt;/li&gt;
&lt;li&gt;Add files online&lt;/li&gt;
&lt;li&gt;Commit changes&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  📥 MODULE 9: CLONING A REPO
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Command
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repo-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Result
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Downloads remote repo&lt;/li&gt;
&lt;li&gt;Creates local copy&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔍 MODULE 10: TRACKING CHANGES
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Command
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Shows:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Modified files&lt;/li&gt;
&lt;li&gt;New files&lt;/li&gt;
&lt;li&gt;Deleted files&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  📦 MODULE 11: STAGING (git add)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Purpose
&lt;/h2&gt;

&lt;p&gt;Move changes → staging area&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 Variations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Add everything
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;--all&lt;/span&gt;
git add &lt;span class="nt"&gt;-A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Add current directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Add specific file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Add by extension
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="k"&gt;*&lt;/span&gt;.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Add using wildcard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Does NOT include deleted files&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 MODULE 12: UNSTAGING
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Command
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;👉 Moves files back to working directory&lt;/p&gt;




&lt;h1&gt;
  
  
  💾 MODULE 13: COMMITTING
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Command
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"message"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Meaning
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Permanently saves changes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ First-time Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"you@email.com"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Your Name"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ⏪ MODULE 14: UNDO COMMITS
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset HEAD~
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Undo last commit&lt;/p&gt;




&lt;h1&gt;
  
  
  ❌ MODULE 15: DELETING FILES
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Delete + stage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;rm &lt;/span&gt;file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Force delete
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Remove from Git only
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt; file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  📜 MODULE 16: VIEW HISTORY
&lt;/h1&gt;



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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Short version:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🌿 MODULE 17: BRANCHING
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Create branch
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 View branches
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Switch branch
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔹 Concept
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Main = stable code&lt;/li&gt;
&lt;li&gt;Branch = experimentation&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔀 MODULE 18: MERGING
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Merge branch
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git merge development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ⚠️ MODULE 19: MERGE CONFLICTS
&lt;/h1&gt;

&lt;p&gt;Occurs when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same file edited in different branches&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 Resolution Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open file&lt;/li&gt;
&lt;li&gt;Choose correct version&lt;/li&gt;
&lt;li&gt;Remove conflict markers&lt;/li&gt;
&lt;li&gt;Commit&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  ⏳ MODULE 20: TIME TRAVEL
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Go to old commit
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &amp;lt;commit-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Return to latest
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🔍 MODULE 21: COMPARE CHANGES
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &amp;lt;commit1&amp;gt; &amp;lt;commit2&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Red → removed&lt;/li&gt;
&lt;li&gt;Green → added&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ☁️ MODULE 22: REMOTE OPERATIONS
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Push
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Fetch
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Pull
&lt;/h2&gt;



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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔁 Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;push → local → remote&lt;/li&gt;
&lt;li&gt;fetch → remote → local (no merge)&lt;/li&gt;
&lt;li&gt;pull → fetch + merge&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔄 MODULE 23: RESTORE
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Undo changes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git restore file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Restore all
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git restore &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Unstage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git restore &lt;span class="nt"&gt;--staged&lt;/span&gt; file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  📦 MODULE 24: STASH
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔹 Save unfinished work
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔹 Retrieve later
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🧠 FINAL SUMMARY
&lt;/h1&gt;

&lt;p&gt;You now understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git fundamentals&lt;/li&gt;
&lt;li&gt;Local vs remote workflow&lt;/li&gt;
&lt;li&gt;Full command lifecycle&lt;/li&gt;
&lt;li&gt;Branching &amp;amp; collaboration&lt;/li&gt;
&lt;li&gt;Conflict resolution&lt;/li&gt;
&lt;li&gt;Undoing mistakes safely&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>linux</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Git and GitHub tutorials for Beginners</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Thu, 30 Apr 2026 11:03:44 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/git-and-github-tutorials-for-beginners-41nm</link>
      <guid>https://forem.com/kenryikegbo/git-and-github-tutorials-for-beginners-41nm</guid>
      <description>&lt;h1&gt;
  
  
  🔰 1. What is Git?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Git = Version Control System&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 It helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Track changes in your code&lt;/li&gt;
&lt;li&gt;Go back to previous versions&lt;/li&gt;
&lt;li&gt;Collaborate with others safely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Google Docs version history… but for code”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Git records every change as a &lt;strong&gt;snapshot (commit)&lt;/strong&gt; ([FreeCodeCamp][1])&lt;/p&gt;




&lt;h1&gt;
  
  
  🌐 2. What is GitHub?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;GitHub is a &lt;strong&gt;cloud platform&lt;/strong&gt; that hosts Git repositories&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collaboration&lt;/li&gt;
&lt;li&gt;Sharing code&lt;/li&gt;
&lt;li&gt;Team development&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;👉 Key idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Git = tool&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub = online platform using Git&lt;/strong&gt; ([product.hubspot.com][2])&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🏗️ 3. Core Git Concepts (VERY IMPORTANT)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  📁 Repository (Repo)
&lt;/h2&gt;

&lt;p&gt;A project folder tracked by Git&lt;/p&gt;

&lt;h2&gt;
  
  
  🧾 Commit
&lt;/h2&gt;

&lt;p&gt;A saved snapshot of your work&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Staging Area
&lt;/h2&gt;

&lt;p&gt;Where you prepare changes before saving&lt;/p&gt;

&lt;h2&gt;
  
  
  🌿 Branch
&lt;/h2&gt;

&lt;p&gt;A separate version of your project (for new features)&lt;/p&gt;

&lt;h2&gt;
  
  
  🔀 Merge
&lt;/h2&gt;

&lt;p&gt;Combining branches together&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ 4. Basic Git Workflow (The Heart of Everything)
&lt;/h1&gt;

&lt;p&gt;This is the &lt;strong&gt;main flow taught in the video&lt;/strong&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Initialize Git
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;👉 Turns your folder into a Git repository&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2: Add Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Moves files to the &lt;strong&gt;staging area&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Commit Changes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Your message"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Saves a snapshot of your work&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Connect to GitHub
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin &amp;lt;repo-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 5: Push to GitHub
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Uploads your code online&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 5. Everyday Git Commands
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Check status
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  See history
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Download updates
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Upload changes
&lt;/h2&gt;



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

&lt;/div&gt;






&lt;h1&gt;
  
  
  🌿 6. Working with Branches (Key Skill)
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Create a branch
&lt;/h3&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; feature-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Switch branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Merge branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git merge feature-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Why branches matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work on features without breaking main code ([product.hubspot.com][2])&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🤝 7. Collaboration Workflow (GitHub Flow)
&lt;/h1&gt;

&lt;p&gt;This is how teams work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create branch&lt;/li&gt;
&lt;li&gt;Make changes&lt;/li&gt;
&lt;li&gt;Push branch&lt;/li&gt;
&lt;li&gt;Open Pull Request (PR)&lt;/li&gt;
&lt;li&gt;Review&lt;/li&gt;
&lt;li&gt;Merge&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 Pull Request = “Please review my changes”&lt;/p&gt;




&lt;h1&gt;
  
  
  🧠 8. Mental Model (Very Important)
&lt;/h1&gt;

&lt;p&gt;Think of Git 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;Working Directory → Staging → Commit → GitHub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Working → you edit files&lt;/li&gt;
&lt;li&gt;Staging → you prepare changes&lt;/li&gt;
&lt;li&gt;Commit → you save version&lt;/li&gt;
&lt;li&gt;GitHub → you share it&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚡ 9. Common Beginner Mistakes (From the Video)
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;❌ Forgetting to &lt;code&gt;git add&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;❌ Bad commit messages&lt;/li&gt;
&lt;li&gt;❌ Working directly on main branch&lt;/li&gt;
&lt;li&gt;❌ Not pulling before pushing&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🚀 10. Your First Practice Exercise
&lt;/h1&gt;

&lt;p&gt;Try this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-project
&lt;span class="nb"&gt;cd &lt;/span&gt;my-project
git init

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello Git"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; file.txt
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"First commit"&lt;/span&gt;

&lt;span class="c"&gt;# connect to GitHub repo&lt;/span&gt;
git remote add origin &amp;lt;your-repo-url&amp;gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






</description>
      <category>git</category>
      <category>github</category>
      <category>versioncontrol</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>🔐 Android App Signing: Why the "Keystore" is Your Most Important File</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Tue, 28 Apr 2026 22:35:07 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/android-app-signing-why-the-keystore-is-your-most-important-file-38ee</link>
      <guid>https://forem.com/kenryikegbo/android-app-signing-why-the-keystore-is-your-most-important-file-38ee</guid>
      <description>&lt;p&gt;If you are a new Android developer, there is one file that can literally make or break your entire career: the Keystore.&lt;br&gt;
In this post, let’s break down what Android App Signing actually is, why it matters for security, and how Google Play App Signing saved us all from potential disaster.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧱 The Basics: What is an App Signature?
&lt;/h2&gt;

&lt;p&gt;Think of an app signature as a digital wax seal.&lt;br&gt;
When you build an APK or AAB, you sign it with a private key. This signature tells the Android OS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identity: This app was created by Developer X.&lt;/li&gt;
&lt;li&gt;Integrity: This app hasn't been modified or tampered with since it was signed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🛡️ The "Secure Update" Model
&lt;/h2&gt;

&lt;p&gt;The most important thing to understand is how Android handles updates.&lt;br&gt;
When you try to install an update over an existing app, Android checks if the new signature matches the old signature.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Matches? The update proceeds and your user data is safe.&lt;/li&gt;
&lt;li&gt;Doesn't match? Android throws an error and blocks the install.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This prevents a hacker from creating a "fake" update to your app to steal user passwords or data.&lt;/p&gt;

&lt;h2&gt;
  
  
  😱 The "Lost Key" Nightmare (The Old Way)
&lt;/h2&gt;

&lt;p&gt;Before 2017, if you lost your .jks (Java Keystore) file or forgot the password, you were finished.&lt;br&gt;
Because the signature is the only way Android identifies the developer, losing the key meant you could never update your app again. You would have to upload a completely new app with a new package name, losing all your installs and reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 How "Google Play App Signing" Fixed It
&lt;/h2&gt;

&lt;p&gt;Google introduced Play App Signing to solve this exact problem. It splits the signing into two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Upload Key: This is the key you keep. You sign your app with it and upload it to Google.&lt;/li&gt;
&lt;li&gt;The App Signing Key: Google keeps this master key in their secure "Vault."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The big win: If you lose your Upload Key, you just message Google Support. They verify your ID, reset the key, and you're back in business. The App Signing Key (the one the users see) never changes, so the update chain is never broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Quick Pro-Tips for Devs:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Never commit your .jks file to GitHub (even in a private repo). Use Environment Variables or Secrets.&lt;/li&gt;
&lt;li&gt;Always opt-in to Google Play App Signing for new apps.&lt;/li&gt;
&lt;li&gt;Backup your keystore in a secure password manager like Bitwarden or 1Password.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;App signing isn't just a technical hurdle; it’s the foundation of trust between you and your users. Treat your keys like your house keys—don't lose them, and don't give them to anyone else!&lt;br&gt;
Have you ever had a "Lost Keystore" horror story? Let’s talk in the comments! 👇&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>flutter</category>
      <category>androiddev</category>
    </item>
    <item>
      <title>Stop Losing Progress: Setting Up a Pro Jupyter Workflow in VS Code (No More Colab Timeouts!)</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Tue, 21 Apr 2026 08:46:18 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/stop-losing-progress-setting-up-a-pro-jupyter-workflow-in-vs-code-no-more-colab-timeouts-10b</link>
      <guid>https://forem.com/kenryikegbo/stop-losing-progress-setting-up-a-pro-jupyter-workflow-in-vs-code-no-more-colab-timeouts-10b</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: The "Colab Heartbreak"
&lt;/h2&gt;

&lt;p&gt;We’ve all been there: You’re 40 epochs into a multimodal model for crop disease detection, and suddenly—Session Terminated. Your variables are gone, your local drive isn't synced, and you have to start over.&lt;br&gt;
While Google Colab is great for quick scripts, serious AI projects (like my current multimodal yield prediction system) need persistence and the power of a local IDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why VS Code for Jupyter?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;IntelliSense: Better code completion than any browser-based notebook.&lt;/li&gt;
&lt;li&gt;Local Environment Control: No more !pip install every time you open the file.&lt;/li&gt;
&lt;li&gt;Git Integration: Version control your experiments easily.&lt;/li&gt;
&lt;li&gt;The Best of Both Worlds: Use your local UI while connecting to powerful cloud GPUs (like Paperspace or Saturn Cloud).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1: The Essentials
&lt;/h2&gt;

&lt;p&gt;First, grab the Jupyter Extension from the VS Code Marketplace. This transforms VS Code into a full-featured notebook editor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Virtual Environment (The Secret to Stability)
&lt;/h2&gt;

&lt;p&gt;Don't install your ML libraries globally! Create a dedicated environment for your project:&lt;/p&gt;

&lt;h1&gt;
  
  
  Create the env
&lt;/h1&gt;

&lt;p&gt;python -m venv crop_ai_env&lt;/p&gt;

&lt;h1&gt;
  
  
  Activate it
&lt;/h1&gt;

&lt;p&gt;source crop_ai_env/bin/activate  # Mac/Linux# .\crop_ai_env\Scripts\activate # Windows&lt;/p&gt;

&lt;h1&gt;
  
  
  Install the kernel connector
&lt;/h1&gt;

&lt;p&gt;pip install ipykernel tensorflow-gpu pillow pandas&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Launching the Notebook
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a file named experiment.ipynb.&lt;/li&gt;
&lt;li&gt;Look at the top right corner of the editor. Click Select Kernel.&lt;/li&gt;
&lt;li&gt;Choose your crop_ai_env.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tip: If you don't see it, press Ctrl+Shift+P and run "Python: Select Interpreter" first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Pro-Tip for Long Training Runs
&lt;/h2&gt;

&lt;p&gt;If you are doing heavy transfer learning (like MobileNetV3), use a Checkpoint Callback. This ensures that even if your computer restarts, your model weights are safe on your drive:&lt;/p&gt;

&lt;p&gt;checkpoint_path = "checkpoints/crop_model_v1.ckpt"cp_callback = tf.keras.callbacks.ModelCheckpoint(&lt;br&gt;
    filepath=checkpoint_path,&lt;br&gt;
    save_weights_only=True,&lt;br&gt;
    verbose=1&lt;br&gt;
)&lt;/p&gt;

&lt;h1&gt;
  
  
  Your model.fit() now has a safety net
&lt;/h1&gt;

&lt;p&gt;model.fit(train_data, epochs=50, callbacks=[cp_callback])&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Switching from Colab to VS Code + a local virtual environment (synced via GitHub or a Cloud Drive) has saved me hours of re-training time. If you're building lightweight TFLite models for offline use, this local-first workflow is a game-changer.
&lt;/h2&gt;

&lt;p&gt;What’s your biggest frustration with browser-based notebooks? Let’s discuss in the comments!&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>ai</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Fixing a Flutter Release APK Build That Failed on Windows</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Thu, 16 Apr 2026 13:27:12 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/-fixing-a-flutter-release-apk-build-that-failed-on-windows-41ip</link>
      <guid>https://forem.com/kenryikegbo/-fixing-a-flutter-release-apk-build-that-failed-on-windows-41ip</guid>
      <description>&lt;p&gt;&lt;strong&gt;How I diagnosed a misleading Gradle failure, separated a temporary Maven network issue from the real Android packaging problem, and fixed the release APK build with a small Gradle change&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;I was building a Flutter release APK on Windows for tester distribution and ran into a confusing sequence of build failures.&lt;/p&gt;

&lt;p&gt;The first error looked like a dependency-resolution problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not GET 'https://repo.maven.apache.org/...'
No such host is known (repo.maven.apache.org)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That made it look like the project or Firebase setup was broken.&lt;/p&gt;

&lt;p&gt;After retrying once the network recovered, the real build blocker appeared:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Execution failed for task ':app:extractReleaseNativeSymbolTables'.
Failed to create MD5 hash for file ... libflutter.so.sym.temp-stream ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the kind of issue that wastes time because the first failure distracts you from the second one. The Maven error was temporary. The actual release-build problem was native symbol extraction during Android packaging on Windows.&lt;/p&gt;

&lt;p&gt;This post explains how I diagnosed it and the small fix that got the APK building successfully.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;produce a signed release APK&lt;/li&gt;
&lt;li&gt;share it directly with testers&lt;/li&gt;
&lt;li&gt;avoid changing unrelated parts of the Android build&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project already had release signing configured, so this was not a keystore or package-name problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Separate the temporary network error from the real build issue
&lt;/h2&gt;

&lt;p&gt;The first failure was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not resolve all files for configuration ':firebase_core:releaseRuntimeClasspath'
Could not download error_prone_annotations-2.26.0.jar
No such host is known (repo.maven.apache.org)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is not a Flutter code issue.&lt;/p&gt;

&lt;p&gt;It means Gradle could not reach Maven Central at that moment. Before changing any project files, I verified whether the host was reachable from the machine.&lt;/p&gt;

&lt;p&gt;Useful checks on Windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;nslookup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;repo.maven.apache.org&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Test-NetConnection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;repo.maven.apache.org&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;443&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once Maven Central was reachable again, the dependency download issue disappeared.&lt;/p&gt;

&lt;p&gt;That was important, because fixing the wrong problem would have been wasted effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Retry the build and read the next failure carefully
&lt;/h2&gt;

&lt;p&gt;After the network issue cleared, the build failed again, but with a different error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Execution failed for task ':app:extractReleaseNativeSymbolTables'.
Cannot access output property 'outputDir' of task ':app:extractReleaseNativeSymbolTables'.
Failed to create MD5 hash for file ... libflutter.so.sym.temp-stream ... as it does not exist.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pointed to Android native symbol extraction, not Firebase, not signing, and not dependency resolution.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;p&gt;By this point, the release APK build was already far enough along to show that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flutter dependencies were resolving&lt;/li&gt;
&lt;li&gt;Firebase packages were not the main blocker&lt;/li&gt;
&lt;li&gt;the Android project structure was basically valid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The failure was happening in the release packaging phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Identify what was actually safe to disable
&lt;/h2&gt;

&lt;p&gt;For a tester APK, I did not need packaged native debug symbols.&lt;/p&gt;

&lt;p&gt;That made the fix straightforward: disable native debug symbol packaging for the release build.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;android/app/build.gradle.kts&lt;/code&gt;, I updated the &lt;code&gt;release&lt;/code&gt; build type to set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;ndk&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;debugSymbolLevel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"none"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The relevant release block became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;buildTypes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;release&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;isMinifyEnabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
        &lt;span class="n"&gt;isShrinkResources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
        &lt;span class="nf"&gt;ndk&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;debugSymbolLevel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"none"&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="n"&gt;hasKeystoreConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;signingConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signingConfigs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"release"&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="n"&gt;signingConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signingConfigs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"debug"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was a targeted fix. It did not relax signing. It did not remove shrinking. It only stopped the build from trying to package native debug symbols that were triggering the failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Rebuild the APK
&lt;/h2&gt;

&lt;p&gt;From the Flutter project root, I reran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;flutter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;flutter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--release&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the &lt;code&gt;debugSymbolLevel = "none"&lt;/code&gt; change, the build completed successfully and produced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build\app\outputs\flutter-apk\app-release.apk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, the resulting APK was about &lt;code&gt;64.5 MB&lt;/code&gt;, which was fine for direct tester distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Warnings that looked scary but were not the blocker
&lt;/h2&gt;

&lt;p&gt;During the build, there were also warnings like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source value 8 is obsolete
target value 8 is obsolete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Font asset "MaterialIcons-Regular.otf" was tree-shaken
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those warnings were not what caused the release build to fail.&lt;/p&gt;

&lt;p&gt;It is worth calling that out because large build logs often mix harmless warnings with the real failure, and it is easy to chase the wrong thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this fix made sense
&lt;/h2&gt;

&lt;p&gt;This was a pragmatic release-build decision.&lt;/p&gt;

&lt;p&gt;For a tester APK, the priority was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;get a stable release artifact&lt;/li&gt;
&lt;li&gt;keep minification and shrinking enabled&lt;/li&gt;
&lt;li&gt;avoid unnecessary Gradle/NDK packaging work that was failing on this environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I were setting up a more advanced crash-symbol workflow later, I could revisit symbol generation in a more controlled release pipeline. But for immediate tester distribution, disabling native debug symbol packaging was the right tradeoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final takeaway
&lt;/h2&gt;

&lt;p&gt;The key lesson was not just the Gradle fix. It was the debugging sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;verify whether the first error is actually environmental&lt;/li&gt;
&lt;li&gt;retry once the environment is healthy&lt;/li&gt;
&lt;li&gt;fix the first reproducible project-level failure, not the first scary message in the log&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the Maven Central error was temporary network/DNS trouble&lt;/li&gt;
&lt;li&gt;the actual reproducible blocker was &lt;code&gt;extractReleaseNativeSymbolTables&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the successful fix was setting &lt;code&gt;debugSymbolLevel = "none"&lt;/code&gt; in the release build&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your Flutter release APK build fails on Windows during native symbol extraction, and you do not need packaged native symbols for that build, this is a clean fix worth trying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build command recap
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;flutter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;flutter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--release&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Gradle fix recap
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;ndk&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;debugSymbolLevel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"none"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>flutter</category>
      <category>android</category>
      <category>gradle</category>
    </item>
    <item>
      <title>The Flutter Release Gauntlet: How to Build Your First Android APK Without the Headache</title>
      <dc:creator>Ikegbo Ogochukwu</dc:creator>
      <pubDate>Thu, 16 Apr 2026 13:03:10 +0000</pubDate>
      <link>https://forem.com/kenryikegbo/the-flutter-release-gauntlet-how-to-build-your-first-android-apk-without-the-headache-4c06</link>
      <guid>https://forem.com/kenryikegbo/the-flutter-release-gauntlet-how-to-build-your-first-android-apk-without-the-headache-4c06</guid>
      <description>&lt;p&gt;You’ve spent weeks perfecting your Flutter app. The widgets are beautiful, the state management is solid, and it runs perfectly on your emulator. But now comes the real challenge: getting it onto a real device.&lt;br&gt;
In this guide, we’ll skip the fluff and look at exactly how to build and share your first Android APK.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Quick &amp;amp; Dirty: Generating Your First APK
&lt;/h2&gt;

&lt;p&gt;If you just want to send a file to your friend or client right now, the standard command is your best friend:&lt;/p&gt;

&lt;p&gt;flutter build apk --release&lt;/p&gt;

&lt;p&gt;What’s happening here?&lt;br&gt;
Flutter is "tree-shaking" your code—removing unused resources—and compiling your Dart code into a high-performance release binary. Once finished, you’ll find your prize at:&lt;br&gt;
build/app/outputs/flutter-apk/app-release.apk.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The "Fat APK" Problem (and the Solution)
&lt;/h2&gt;

&lt;p&gt;The standard build command creates a "Fat APK," which contains code for all device architectures (arm64, armeabi, x86_64). While convenient, it makes your file size unnecessarily large.&lt;br&gt;
To create smaller, optimized files for specific devices, use:&lt;/p&gt;

&lt;p&gt;flutter build apk --split-per-abi&lt;/p&gt;

&lt;p&gt;This gives you three separate APKs. Most modern phones will use the app-arm64-v8a-release.apk version.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Signing Your App (Don't Skip This!)
&lt;/h2&gt;

&lt;p&gt;Android won’t let you install a "blank" app for long. To make your app official, you need a digital signature called a Keystore.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate the key: Use the keytool command in your terminal to create a .jks file.&lt;/li&gt;
&lt;li&gt;Reference it: Create a key.properties file in your android/ folder to store your passwords.&lt;/li&gt;
&lt;li&gt;Update Gradle: Configure your android/app/build.gradle to use these credentials during the build process.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pro Tip: Never, ever upload your key.properties or .jks file to GitHub. Add them to your .gitignore immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. APK vs. App Bundle (AAB): Which one do you need?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use APK for direct sharing (WhatsApp, Google Drive, or Slack).&lt;/li&gt;
&lt;li&gt;Use AAB (flutter build appbundle) for the Google Play Store. Google now requires AABs because they allow the store to generate the smallest possible APK for every specific user.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Final Checklist Before You Share
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Change the App Name: Update the android:label in your AndroidManifest.xml so it doesn't just say "Flutter App" on the home screen.&lt;/li&gt;
&lt;li&gt;Update the Package Name: Change com.example.yourapp to something unique like com.yourname.appname.&lt;/li&gt;
&lt;li&gt;Add an Icon: Use the flutter_launcher_icons package to replace the default Flutter logo with your own branding.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Summary Table: Your Build Toolkit&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Quick Test&lt;/td&gt;
&lt;td&gt;flutter build apk&lt;/td&gt;
&lt;td&gt;Fat APK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Small File&lt;/td&gt;
&lt;td&gt;flutter build apk --split-per-abi&lt;/td&gt;
&lt;td&gt;Multiple ABI-specific APKs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Play Store&lt;/td&gt;
&lt;td&gt;flutter build appbundle&lt;/td&gt;
&lt;td&gt;.aab file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clean Start&lt;/td&gt;
&lt;td&gt;flutter clean&lt;/td&gt;
&lt;td&gt;Clears old build files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>flutter</category>
      <category>android</category>
      <category>androiddev</category>
    </item>
  </channel>
</rss>
