<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nishant Gaurav </title>
    <description>The latest articles on DEV Community by Nishant Gaurav  (@im_nishant).</description>
    <link>https://dev.to/im_nishant</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3755207%2Fccfc2018-a401-48be-ac00-4b0aed7027c9.jpeg</url>
      <title>DEV Community: Nishant Gaurav </title>
      <link>https://dev.to/im_nishant</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/im_nishant"/>
    <language>en</language>
    <item>
      <title>Your Code Runs Locally. GitHub Actions Makes It Run Everywhere, Automatically.</title>
      <dc:creator>Nishant Gaurav </dc:creator>
      <pubDate>Tue, 16 Jun 2026 14:30:00 +0000</pubDate>
      <link>https://dev.to/im_nishant/your-code-runs-locally-github-actions-makes-it-run-everywhere-automatically-13bc</link>
      <guid>https://dev.to/im_nishant/your-code-runs-locally-github-actions-makes-it-run-everywhere-automatically-13bc</guid>
      <description>&lt;p&gt;You've pushed code to GitHub before. You know the drill: write something, commit it, push it, then manually do whatever comes next. Run the tests. Deploy the site. Update the docs. Every time, by hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions&lt;/strong&gt; is the answer to "what if that next step just happened on its own?" It lets you define automated workflows that trigger whenever something happens in your repository. A push, a pull request, a schedule, even a manual button click. The workflow runs on GitHub's servers, not yours. You define the steps in a YAML file, commit it to your repo, and GitHub takes it from there.&lt;/p&gt;

&lt;p&gt;This article walks through exactly how that works, using a real project as the example throughout: &lt;strong&gt;&lt;a href="//nishant05gaurav.github.io/recLog/"&gt;recLog&lt;/a&gt;&lt;/strong&gt;, an automated pipeline that fetches articles from Dev.to and injects them into a portfolio's HTML without any manual update.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Manual Steps After Every Push Don't Scale
&lt;/h2&gt;

&lt;p&gt;Here's the situation that &lt;strong&gt;&lt;a href="//nishant05gaurav.github.io/recLog/"&gt;recLog&lt;/a&gt;&lt;/strong&gt; was built to solve.&lt;/p&gt;

&lt;p&gt;You write an article on Dev.to. You publish it. Now your portfolio is out of date because it lists your articles as static HTML that you maintain by hand. So you open your portfolio repo, copy in a new article card, adjust the HTML, commit, and push. Every. Single. Time.&lt;/p&gt;

&lt;p&gt;This is fine once. It's annoying at ten articles. By twenty, you've already stopped doing it, which means your portfolio is quietly going stale while your actual writing keeps going.&lt;/p&gt;

&lt;p&gt;The broader pattern is everywhere in software development. You push code and need to run tests before merging. You merge to main and need to deploy. You update a dependency and need to check if anything breaks. These are predictable, repeatable steps. Doing them manually introduces delay, inconsistency, and the very human tendency to skip them when you're in a hurry.&lt;/p&gt;

&lt;p&gt;GitHub Actions turns these steps into automated workflows that live inside your repository. When the trigger fires, GitHub spins up a fresh machine, runs your defined steps in order, and reports back what happened. No server to maintain, no third-party CI tool to configure separately, no deploy keys to manage outside the repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  How GitHub Actions Actually Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The mental model
&lt;/h3&gt;

&lt;p&gt;GitHub Actions is built around four concepts you need to understand before writing a single line of YAML: &lt;strong&gt;workflows&lt;/strong&gt;, &lt;strong&gt;events&lt;/strong&gt;, &lt;strong&gt;jobs&lt;/strong&gt;, and &lt;strong&gt;steps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;workflow&lt;/strong&gt; is the top-level automation unit. It's a single YAML file that lives in &lt;code&gt;.github/workflows/&lt;/code&gt; inside your repository. One repo can have multiple workflow files, and each one is independent.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;event&lt;/strong&gt; is what triggers the workflow. Push to main, open a pull request, publish a release, or run on a cron schedule. You define which events activate a given workflow in the &lt;code&gt;on:&lt;/code&gt; block at the top of the file.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;job&lt;/strong&gt; is a collection of steps that run together on the same machine. By default, jobs in the same workflow run in parallel. If one job depends on another, you declare that explicitly and GitHub sequences them accordingly.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;step&lt;/strong&gt; is a single action within a job. It's either a shell command you write directly, or a pre-built action from the GitHub Actions marketplace that someone else wrote and you call by name.&lt;/p&gt;

&lt;p&gt;Every job runs on a fresh virtual machine, called a &lt;strong&gt;runner&lt;/strong&gt;, that GitHub provisions and discards after the job completes. This means each run starts from a clean state. Anything you need (dependencies, credentials, files from your repo) has to be explicitly set up within the workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  The workflow file
&lt;/h3&gt;

&lt;p&gt;Here's the recLog workflow file, which is the actual file that keeps the portfolio in sync automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/main.yml&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sync Dev.to Articles&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;          &lt;span class="c1"&gt;# runs whenever code is pushed to main&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*/6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;    &lt;span class="c1"&gt;# also runs every 6 hours automatically&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sync&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;    &lt;span class="c1"&gt;# GitHub provisions a fresh Ubuntu machine for this job&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Step 1: check out the repository so the runner has access to the code&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repo&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="c1"&gt;# Step 2: install Python on the runner&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.11'&lt;/span&gt;

      &lt;span class="c1"&gt;# Step 3: install the project's dependencies&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;

      &lt;span class="c1"&gt;# Step 4: run the pipeline (fetch, deduplicate, inject)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run sync pipeline&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python main.py&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;DEVTO_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DEVTO_API_KEY }}&lt;/span&gt;  &lt;span class="c1"&gt;# pulled from repo secrets, never hardcoded&lt;/span&gt;

      &lt;span class="c1"&gt;# Step 5: commit and push the updated index.html back to the repo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Commit updated portfolio&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name "github-actions[bot]"&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email "github-actions[bot]@users.noreply.github.com"&lt;/span&gt;
          &lt;span class="s"&gt;git add index.html&lt;/span&gt;
          &lt;span class="s"&gt;git diff --staged --quiet || git commit -m "chore: sync articles $(date -u +%Y-%m-%dT%H:%M:%SZ)"&lt;/span&gt;
          &lt;span class="s"&gt;git push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Walk through what this does. When code is pushed to main or when the 6-hour cron fires, GitHub provisions a fresh Ubuntu machine. It checks out the repository, installs Python 3.11, installs the dependencies from &lt;code&gt;requirements.txt&lt;/code&gt;, runs &lt;code&gt;main.py&lt;/code&gt; (which calls the Dev.to API, deduplicates articles against the existing HTML, and injects new cards), and then commits the updated &lt;code&gt;index.html&lt;/code&gt; back to the repo. The portfolio updates without anyone touching it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;git diff --staged --quiet ||&lt;/code&gt; before the commit is worth noting. If &lt;code&gt;main.py&lt;/code&gt; ran but found no new articles, &lt;code&gt;index.html&lt;/code&gt; won't have changed. Without that check, the workflow would fail trying to commit a file with no changes. The &lt;code&gt;||&lt;/code&gt; means: if the diff is empty (exit code 0), skip the commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  How &lt;code&gt;uses&lt;/code&gt; and &lt;code&gt;run&lt;/code&gt; differ
&lt;/h3&gt;

&lt;p&gt;You'll notice two kinds of steps in the file above.&lt;/p&gt;

&lt;p&gt;Steps with &lt;code&gt;uses:&lt;/code&gt; call a pre-built action. &lt;code&gt;actions/checkout@v3&lt;/code&gt; is maintained by GitHub and handles cloning your repo onto the runner correctly, including dealing with authentication. &lt;code&gt;actions/setup-python@v4&lt;/code&gt; installs Python and adds it to the runner's PATH. These are reusable building blocks from the Actions marketplace, versioned with the &lt;code&gt;@v3&lt;/code&gt; syntax so your workflow doesn't silently break when the action gets updated.&lt;/p&gt;

&lt;p&gt;Steps with &lt;code&gt;run:&lt;/code&gt; execute shell commands directly. This is where your own logic lives. Anything you'd type into a terminal, you can write here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secrets
&lt;/h3&gt;

&lt;p&gt;Notice &lt;code&gt;${{ secrets.DEVTO_API_KEY }}&lt;/code&gt; in the workflow. This is how GitHub Actions handles credentials. You store the actual key value in your repository's Settings under Secrets and Variables, and reference it in the workflow using the &lt;code&gt;${{ secrets.NAME }}&lt;/code&gt; syntax. The value is never written to the workflow file, never visible in logs, and never committed to source control.&lt;/p&gt;

&lt;p&gt;For recLog, this is where the Dev.to API key lives. The workflow reads it at runtime, passes it to the Python script as an environment variable, and the script uses it to authenticate against the Dev.to REST API.&lt;/p&gt;

&lt;h3&gt;
  
  
  The cron trigger
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;schedule:&lt;/code&gt; event uses standard cron syntax. &lt;code&gt;0 */6 * * *&lt;/code&gt; means "at minute 0 of every 6th hour." GitHub runs this on UTC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;┌──── &lt;span class="n"&gt;minute&lt;/span&gt; (&lt;span class="m"&gt;0&lt;/span&gt;-&lt;span class="m"&gt;59&lt;/span&gt;)
│  ┌─── &lt;span class="n"&gt;hour&lt;/span&gt; (&lt;span class="m"&gt;0&lt;/span&gt;-&lt;span class="m"&gt;23&lt;/span&gt;)
│  │   ┌── &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt; (&lt;span class="m"&gt;1&lt;/span&gt;-&lt;span class="m"&gt;31&lt;/span&gt;)
│  │   │  ┌─ &lt;span class="n"&gt;month&lt;/span&gt; (&lt;span class="m"&gt;1&lt;/span&gt;-&lt;span class="m"&gt;12&lt;/span&gt;)
│  │   │  │  ┌ &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;week&lt;/span&gt; (&lt;span class="m"&gt;0&lt;/span&gt;-&lt;span class="m"&gt;7&lt;/span&gt;, &lt;span class="n"&gt;Sunday&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;)
│  │   │  │  │
&lt;span class="m"&gt;0&lt;/span&gt;  */&lt;span class="m"&gt;6&lt;/span&gt;  *  *  *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For recLog, this means the portfolio checks for new articles four times a day without any manual trigger. If you publish at 2am, the site reflects it by 8am at the latest.&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%2Fjldr1f5kyzobq1hw8p94.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%2Fjldr1f5kyzobq1hw8p94.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Where It Gets Tricky
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The runner starts empty every time
&lt;/h3&gt;

&lt;p&gt;The runner GitHub provisions do not know your previous runs. It doesn't have your dependencies cached, it doesn't have your environment variables set, it doesn't have any state from the last time the workflow ran. This catches beginners every time.&lt;/p&gt;

&lt;p&gt;If your script writes a file during one run and expects that file to exist on the next run, it won't. Everything ephemeral needs to either be committed back to the repo (like recLog does with &lt;code&gt;index.html&lt;/code&gt;), stored in an external service, or regenerated each run.&lt;/p&gt;

&lt;p&gt;For recLog this was a deliberate design choice. The deduplication logic reads the &lt;em&gt;current state of index.html in the repo&lt;/em&gt; to know which articles already exist. The runner checks out the repo fresh each time, runs the diff, and commits only changes. The repo itself is the state store.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow permissions for committing back
&lt;/h3&gt;

&lt;p&gt;By default, the &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; that GitHub provides to each workflow run has read-only access to the repository contents. If your workflow tries to &lt;code&gt;git push&lt;/code&gt; without the right permissions, it will fail with a 403.&lt;/p&gt;

&lt;p&gt;To fix this, go to your repository Settings, then Actions, then General, and set "Workflow permissions" to "Read and write permissions." Alternatively, you can set it per-workflow in the YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of the most common silent failure points for beginners writing their first workflow that commits back to the repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cron schedules aren't guaranteed
&lt;/h3&gt;

&lt;p&gt;GitHub's documentation states that scheduled workflows may be delayed during periods of high load on their infrastructure. A workflow scheduled for 6:00 UTC might run at 6:07, or occasionally later. For most use cases, this is fine. For anything where exact timing matters, scheduled Actions aren't the right tool.&lt;/p&gt;

&lt;p&gt;There's also a lesser-known behaviour: GitHub will disable scheduled workflows on repositories that have had no activity for 60 days. If your portfolio repo goes quiet for two months, the sync stops. The fix is either to push something (anything) to keep the repo active, or to trigger the workflow manually from the Actions tab when you notice it's stopped.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secrets in forks and pull requests
&lt;/h3&gt;

&lt;p&gt;If someone forks your repo and opens a pull request, workflows triggered by that PR will not have access to your repository secrets. This is a security measure, not a bug. It means a fork-based PR can't exfiltrate your API keys. But it also means if your workflow requires a secret to run, it will fail on PRs from forks. Keep this in mind if you ever open-source a project that has required secrets in its workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building recLog's Pipeline Step by Step
&lt;/h2&gt;

&lt;p&gt;Here's how to set up a workflow like recLog's from scratch, assuming you have a repository with a Python project that you want to automate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: create the workflow directory&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .github/workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: write the workflow file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/main.yml&lt;/code&gt; and start with the trigger and job definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sync Dev.to Articles&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*/6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sync&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: add the checkout and Python setup steps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These two steps appear in nearly every Python-based workflow. The checkout action clones the repo onto the runner. Without it, the runner has no access to your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repo&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.11'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: install dependencies and run your script&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run sync pipeline&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python main.py&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;DEVTO_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DEVTO_API_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5: add the secret to your repository&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to your repository on GitHub. Settings, then Secrets and variables, then Actions, then "New repository secret." Name it &lt;code&gt;DEVTO_API_KEY&lt;/code&gt; and paste in your Dev.to API key. The workflow will now have access to it at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: commit and push if the output changed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the step that closes the loop. The &lt;code&gt;git diff --staged --quiet ||&lt;/code&gt; guard ensures the commit only runs when there's actually something new to commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Commit updated portfolio&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name "github-actions[bot]"&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email "github-actions[bot]@users.noreply.github.com"&lt;/span&gt;
          &lt;span class="s"&gt;git add index.html&lt;/span&gt;
          &lt;span class="s"&gt;git diff --staged --quiet || git commit -m "chore: sync articles $(date -u +%Y-%m-%dT%H:%M:%SZ)"&lt;/span&gt;
          &lt;span class="s"&gt;git push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this file is committed and pushed to main, GitHub picks it up automatically. You'll see the workflow appear in the Actions tab of your repository. Every run shows the status of each step, the logs, and how long it took.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Now Understand
&lt;/h2&gt;

&lt;p&gt;A GitHub Actions workflow is not magic. It's a YAML file that tells GitHub: when this event happens, spin up a machine, run these steps in order, and report back. Every concept in that sentence is something you now have a working mental model of: events, runners, steps, secrets, and how to commit results back to the repo.&lt;/p&gt;

&lt;p&gt;The recLog pipeline is a clean example of the pattern in its simplest useful form: trigger on push and on schedule, run Python, commit the output. That structure applies directly to dozens of other automation problems: syncing data, running tests, publishing packages, and generating reports.&lt;/p&gt;

&lt;p&gt;Your next step is to open the Actions tab on any of your existing GitHub repositories and look at the starter workflows GitHub suggests. Pick the simplest one that applies to your stack, read through it line by line against what you've learned here, and run it. Seeing a green checkmark on your first workflow is how the mental model becomes a reflex.&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubactions</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>GitHub Already Knows When You Push. It Can Do a Lot More Than Just Watch.</title>
      <dc:creator>Nishant Gaurav </dc:creator>
      <pubDate>Wed, 10 Jun 2026 14:30:00 +0000</pubDate>
      <link>https://dev.to/im_nishant/github-already-knows-when-you-push-it-can-do-a-lot-more-than-just-watch-bh7</link>
      <guid>https://dev.to/im_nishant/github-already-knows-when-you-push-it-can-do-a-lot-more-than-just-watch-bh7</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%2Fte0jt4x0bkt4l4nux7rl.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%2Fte0jt4x0bkt4l4nux7rl.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every time you push code to GitHub, something happens on their end. A record is created, your repo updates, collaborators can see the change. GitHub is already reacting to your push. The question is whether you want it to stop there, or do something useful with that event.&lt;/p&gt;

&lt;p&gt;That's the idea behind GitHub Actions. It's GitHub's built-in automation layer. When something happens in your repository, a workflow runs. That workflow can test your code, deploy your app, send a notification, sync data, or do anything else a computer can do. No external service required. No separate CI tool to configure. It lives inside your repo, runs on GitHub's infrastructure, and triggers off the same events your repository already produces.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why GitHub Built This When AWS Already Exists
&lt;/h2&gt;

&lt;p&gt;This is a fair question. AWS CodePipeline, Jenkins, CircleCI, and a dozen other tools already handle CI/CD. Why did GitHub build their own?&lt;/p&gt;

&lt;p&gt;The honest answer is friction. Every existing tool required you to leave GitHub, set up an account somewhere else, connect it to your repo via webhooks or API tokens, configure a pipeline in a separate interface, and then debug failures across two different platforms. For large engineering teams with dedicated DevOps engineers, that cost is manageable. For an individual developer or a small team, it's enough friction to skip automation entirely.&lt;/p&gt;

&lt;p&gt;GitHub Actions removes the "leave GitHub" part. Your workflow file lives in &lt;code&gt;.github/workflows/&lt;/code&gt; inside your repo. It's version-controlled alongside your code. You see the results in the same tab where you see your commits and pull requests. When something breaks, the logs are right there.&lt;/p&gt;

&lt;p&gt;AWS and other cloud platforms are still the right choice when you need deep infrastructure control, complex deployment pipelines across multiple environments, or tight integration with AWS-specific services. GitHub Actions is not trying to replace that. It's solving a different problem: making basic automation accessible to anyone who already uses GitHub, without requiring infrastructure expertise to get started.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Actually Works
&lt;/h2&gt;

&lt;p&gt;GitHub Actions is built on four concepts. Understand these and everything else is just syntax.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflows&lt;/strong&gt; are the top-level unit. Each workflow is a YAML file in &lt;code&gt;.github/workflows/&lt;/code&gt;. One repository can have multiple workflows, and each one is completely independent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Events&lt;/strong&gt; are what trigger a workflow. A push to main, a pull request being opened, a release being published, or a scheduled time. You define which events activate a workflow in the &lt;code&gt;on:&lt;/code&gt; block at the top of the file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jobs&lt;/strong&gt; are groups of steps that run together on the same machine. Multiple jobs in a workflow run in parallel by default. If one job needs the output of another, you declare that dependency explicitly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps&lt;/strong&gt; are individual tasks within a job. A step is either a shell command you write directly using &lt;code&gt;run:&lt;/code&gt;, or a pre-built action from the marketplace that you call using &lt;code&gt;uses:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every job runs on a fresh virtual machine that GitHub provisions for the duration of the job and discards afterward. This machine is called a &lt;strong&gt;runner&lt;/strong&gt;. The most common choice is &lt;code&gt;ubuntu-latest&lt;/code&gt;. The runner starts with nothing except a base OS, so anything your workflow needs (Python, Node, dependencies, credentials) has to be set up explicitly within the steps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your First Workflow
&lt;/h2&gt;

&lt;p&gt;Here's a minimal workflow that runs your Python tests automatically every time code is pushed to the main branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/ci.yml&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;      &lt;span class="c1"&gt;# triggers on every push to main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;      &lt;span class="c1"&gt;# clones your repo onto the runner&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.11'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pytest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use this, create the file at &lt;code&gt;.github/workflows/ci.yml&lt;/code&gt; in your repo, commit it, and push. GitHub picks it up automatically. Go to the Actions tab in your repository and you'll see the workflow run in real time.&lt;/p&gt;

&lt;p&gt;That's it. No external accounts. No webhooks to configure. The workflow file being in the right directory is all GitHub needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Secrets: Credentials Without Hardcoding
&lt;/h2&gt;

&lt;p&gt;Almost every real workflow needs a credential of some kind: an API key, a deploy token, a database password. You should never write these directly in your workflow file, because workflow files are committed to your repository and potentially public.&lt;/p&gt;

&lt;p&gt;GitHub solves this with &lt;strong&gt;secrets&lt;/strong&gt;. You store the value in your repository settings (Settings, then Secrets and variables, then Actions), and reference it in the workflow using &lt;code&gt;${{ secrets.YOUR_SECRET_NAME }}&lt;/code&gt;. The value is masked in logs and never exposed in the workflow file itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Call external API&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python sync.py&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.API_KEY }}&lt;/span&gt;    &lt;span class="c1"&gt;# injected at runtime, never hardcoded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where GitHub Actions Fits (and Where It Doesn't)
&lt;/h2&gt;

&lt;p&gt;GitHub Actions handles most automation needs for individual projects and small teams well: running tests on pull requests, deploying static sites, syncing data on a schedule, publishing packages on release. The setup cost is low and the integration with GitHub is tight.&lt;/p&gt;

&lt;p&gt;It starts showing limits when you need long-running jobs (there's a 6-hour cap per job), complex multi-environment deployments with approval gates, or workloads that need dedicated infrastructure rather than ephemeral runners. For those cases, dedicated platforms like AWS CodePipeline or a self-hosted Jenkins instance are still the right tool.&lt;/p&gt;

&lt;p&gt;For most projects, though, GitHub Actions covers what you need without requiring you to leave the platform you're already using.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up Your First Workflow: The Short Version
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In your repository, create the directory &lt;code&gt;.github/workflows/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add a YAML file inside it (the name can be anything, e.g. &lt;code&gt;ci.yml&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Define your trigger in the &lt;code&gt;on:&lt;/code&gt; block&lt;/li&gt;
&lt;li&gt;Define a job with &lt;code&gt;runs-on: ubuntu-latest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add steps using &lt;code&gt;uses:&lt;/code&gt; for marketplace actions and &lt;code&gt;run:&lt;/code&gt; for shell commands&lt;/li&gt;
&lt;li&gt;Commit and push. Check the Actions tab.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Any secrets your workflow needs go in Settings, then Secrets and variables, then Actions, referenced in the workflow as &lt;code&gt;${{ secrets.NAME }}&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;Once this mental model is solid, the natural next step is building a workflow that actually does something specific to your project: runs your test suite, deploys on merge, or automates a repetitive task you currently do by hand.&lt;/p&gt;

&lt;p&gt;A deeper walkthrough of a complete real-world pipeline (fetching data, transforming it, committing the result back to the repo automatically) is covered in the follow-up article: &lt;strong&gt;&lt;a href="https://dev.to/im_nishant/your-code-runs-locally-github-actions-makes-it-run-everywhere-automatically-13bc?preview=54224baa9871f67acc26e87612edacfbfef9b326eb72f75b3de0ba1d05216be1e795344fe360101b5e59f801899ee6229f231fe11167f258c53dcd35"&gt;Building an Automated Content Pipeline with GitHub Actions&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The foundation is what this article covered. The follow-up shows what it looks like when you apply it to a production project from start to finish.&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubactions</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>You Don't Have a "Works on My Machine" Problem. You Have a Dependency Problem.</title>
      <dc:creator>Nishant Gaurav </dc:creator>
      <pubDate>Mon, 08 Jun 2026 05:53:48 +0000</pubDate>
      <link>https://dev.to/im_nishant/you-dont-have-a-works-on-my-machine-problem-you-have-a-dependency-problem-349l</link>
      <guid>https://dev.to/im_nishant/you-dont-have-a-works-on-my-machine-problem-you-have-a-dependency-problem-349l</guid>
      <description>&lt;p&gt;Every developer has said it. You write code, it runs perfectly on your laptop, you push it to a server or hand it to a teammate, and something breaks. Wrong Python version. A library installed globally that you forgot about. An environment variable that was set in your shell profile but nowhere else.&lt;/p&gt;

&lt;p&gt;Docker doesn't fix your code. It fixes the gap between the environment where you wrote your code and the environment where it runs. That's the whole job. And once you see that clearly, everything else about Docker follows logically.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Environments Are Invisible Dependencies
&lt;/h2&gt;

&lt;p&gt;Here's a scenario that plays out constantly on engineering teams.&lt;/p&gt;

&lt;p&gt;A developer builds a data processing script. It works on their machine. They hand it to a teammate. The teammate runs it and it crashes because a library is the wrong version, or isn't installed at all. So they spend an hour aligning their setups. Two weeks later, it's deployed to production. It crashes again because the server is running a different OS version, and a native dependency that compiled fine locally doesn't compile there.&lt;/p&gt;

&lt;p&gt;None of this is a code problem. The code is fine. The problem is that every machine carries hidden state: installed packages, runtime versions, system libraries, OS quirks. And your application depends on all of it, invisibly.&lt;/p&gt;

&lt;p&gt;The traditional solutions are painful. You write a &lt;code&gt;requirements.txt&lt;/code&gt; or a &lt;code&gt;package.json&lt;/code&gt; and hope everyone runs it. You write a setup script. You document the expected environment in a README that gets out of date. You use a virtual environment, which helps for language-level dependencies but doesn't capture system-level ones. You use a VM, which captures everything but is heavy, slow to start, and awkward to share.&lt;/p&gt;

&lt;p&gt;Docker solves this by packaging the application &lt;em&gt;and&lt;/em&gt; its entire environment (OS libraries, runtime, config, dependencies) into a single portable unit. That unit runs the same way everywhere Docker is installed.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Docker Actually Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The core idea: containers vs virtual machines
&lt;/h3&gt;

&lt;p&gt;The most common misconception about Docker is that it's a lightweight virtual machine. It isn't, and the difference matters.&lt;/p&gt;

&lt;p&gt;A virtual machine emulates hardware. When you run a VM, your computer pretends to be a different computer, running a full operating system on top of fake hardware. That's expensive. A VM typically takes seconds to minutes to start and consumes gigabytes of RAM just for the OS layer.&lt;/p&gt;

&lt;p&gt;Docker uses a different mechanism called &lt;strong&gt;containerisation&lt;/strong&gt;. Containers don't emulate hardware. They run as isolated processes directly on your actual OS kernel, using two Linux features to create the illusion of separation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Namespaces&lt;/strong&gt; give each container its own view of the system. A container has its own process list, its own network interfaces, its own filesystem tree. From inside the container, it looks like it's the only thing running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cgroups (control groups)&lt;/strong&gt; limit how much CPU, memory, and I/O a container can consume. This is how Docker prevents one container from starving others.&lt;/p&gt;

&lt;p&gt;Because containers share the host kernel rather than running their own, they start in milliseconds and use a fraction of the memory a VM would. A container running a Python web app might consume 50MB of RAM. A VM running the same app would consume 50MB for the app &lt;em&gt;plus&lt;/em&gt; roughly 500MB for the guest OS.&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%2F2si1f77frhlfase5uzml.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%2F2si1f77frhlfase5uzml.png" alt="VM Architecture vs Docker Container Architecture" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Images and containers
&lt;/h3&gt;

&lt;p&gt;Docker has two concepts you need to keep straight: &lt;strong&gt;images&lt;/strong&gt; and &lt;strong&gt;containers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;image&lt;/strong&gt; is a read-only template. It describes an environment: which OS layer to use, which packages to install, which files to include, which command to run on startup. An image is not running anything. It's a blueprint, like a class definition in code.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;container&lt;/strong&gt; is a running instance of an image. When you tell Docker to run an image, it creates a container: a live, isolated process using that image as its starting state. You can run ten containers from the same image simultaneously and each will be isolated from the others. This is the class-vs-object analogy made literal.&lt;/p&gt;

&lt;p&gt;Images are built in layers. Every instruction in your image definition adds a layer on top of the previous one: start with a base OS layer, add a Python layer, add your application code. Docker caches each layer separately. If you rebuild an image after changing only your application code, Docker reuses the OS and Python layers from cache and only rebuilds the final layer. This makes rebuilds fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Dockerfile
&lt;/h3&gt;

&lt;p&gt;You define an image with a &lt;code&gt;Dockerfile&lt;/code&gt;, a plain text file that lists the build instructions.&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;# Start from an official Python base image (OS + Python bundled together)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;

&lt;span class="c"&gt;# Set the working directory inside the container&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy and install dependencies first so this layer gets cached&lt;/span&gt;
&lt;span class="c"&gt;# as long as requirements.txt doesn't change&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Now copy your application code (this layer rebuilds on every code change)&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;# Tell Docker what to run when the container starts&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ordering here is deliberate. &lt;code&gt;requirements.txt&lt;/code&gt; is copied and installed &lt;em&gt;before&lt;/em&gt; the application code. Because Docker caches layers, if you change your code but not your dependencies, Docker will reuse the cached dependency layer and only redo the final &lt;code&gt;COPY&lt;/code&gt;. If you put &lt;code&gt;COPY . .&lt;/code&gt; first, every code change would invalidate the dependency cache and reinstall everything, turning a two-second rebuild into a two-minute one.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Docker Hub and base images
&lt;/h3&gt;

&lt;p&gt;You don't build images from scratch. You start &lt;code&gt;FROM&lt;/code&gt; an existing image, usually an official one from Docker Hub, which is a public registry of images. &lt;code&gt;python:3.11-slim&lt;/code&gt; is an image that includes Debian Linux and Python 3.11, maintained by the Python team. There are official base images for nearly every language runtime, database, and common tool.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;slim&lt;/code&gt; suffix is a convention for smaller variants that strip out documentation and tools you don't need at runtime. For production use, smaller images mean faster deploys and a smaller attack surface.&lt;/p&gt;

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

&lt;p&gt;A real application is rarely just one container. You have your app, a database, maybe a caching layer. &lt;strong&gt;Docker Compose&lt;/strong&gt; lets you define and manage multiple containers as a single unit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml defines a web app and its database together&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;                    &lt;span class="c1"&gt;# build from the Dockerfile in this directory&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8000:8000"&lt;/span&gt;             &lt;span class="c1"&gt;# map port 8000 on your machine to port 8000 in the container&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;                      &lt;span class="c1"&gt;# don't start web until db is running&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres://user:pass@db:5432/mydb&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:15&lt;/span&gt;          &lt;span class="c1"&gt;# use the official Postgres image directly&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pass&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this file in your project, &lt;code&gt;docker compose up&lt;/code&gt; starts both containers with the right configuration. A new developer on your team clones the repo and runs one command. No database installation required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where It Gets Complicated
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Persistence: containers are ephemeral by default
&lt;/h3&gt;

&lt;p&gt;A container's filesystem is disposable. When you delete a container, anything written inside it is gone. For a stateless web app that's fine because you rebuild and redeploy. For a database, it's a disaster.&lt;/p&gt;

&lt;p&gt;Docker handles this with &lt;strong&gt;volumes&lt;/strong&gt;: directories on your host machine (or a managed storage backend) that get mounted into containers. Anything the container writes to the volume path persists even after the container is removed.&lt;/p&gt;

&lt;p&gt;Beginners consistently skip volumes when running databases locally, then wonder why their data disappears every time they restart. Add this to your Compose file for the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:15&lt;/span&gt;
  &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;   &lt;span class="c1"&gt;# named volume for persistence&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# declare the named volume&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Image size creep
&lt;/h3&gt;

&lt;p&gt;The single most common mistake when writing Dockerfiles is producing images that are far larger than they need to be. A Python image built naively can easily reach 1-2GB. The production version of the same app can be under 100MB with &lt;strong&gt;multi-stage builds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Multi-stage builds let you use one image to &lt;em&gt;build&lt;/em&gt; your application (with compilers, test tools, all of it) and a separate, leaner image to &lt;em&gt;run&lt;/em&gt; it. The final image only contains what the runtime needs.&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;# Stage 1: build stage with full tooling&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;python:3.11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/install &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Stage 2: runtime stage, slim and minimal&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /install /usr/local   # copy only the installed packages&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Secrets and environment variables
&lt;/h3&gt;

&lt;p&gt;Don't put secrets in your Dockerfile. If you write &lt;code&gt;ENV API_KEY=abc123&lt;/code&gt; in a Dockerfile and push it to a registry, that key is baked into every layer of the image and visible to anyone who pulls it.&lt;/p&gt;

&lt;p&gt;Pass secrets at runtime using environment variables, Docker secrets, or a tool like Vault. Your Compose file can reference variables from a &lt;code&gt;.env&lt;/code&gt; file that you never commit to source control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Networking between containers
&lt;/h3&gt;

&lt;p&gt;Containers on the same Docker network can reach each other by service name. In the Compose example above, the web app connects to &lt;code&gt;db:5432&lt;/code&gt;. The name &lt;code&gt;db&lt;/code&gt; is not a hostname you configured anywhere. Docker's internal DNS resolves it to the database container automatically. This trips up beginners who try to use &lt;code&gt;localhost&lt;/code&gt; inside a container and can't reach a sibling container. Inside a container, &lt;code&gt;localhost&lt;/code&gt; refers to &lt;em&gt;that container&lt;/em&gt;, not the host machine or anything running alongside it.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Concrete Scenario: Onboarding Without the Setup Tax
&lt;/h2&gt;

&lt;p&gt;Here's where the value becomes tangible. You're working on a team building a backend API in Python. The app needs Python 3.11, PostgreSQL 15, and Redis. Without Docker, onboarding a new engineer means installing Python 3.11 (maybe using pyenv, maybe not), installing and configuring PostgreSQL, installing Redis, setting a dozen environment variables, and running migrations. This takes anywhere from 30 minutes to half a day, and something always breaks on someone's machine.&lt;/p&gt;

&lt;p&gt;With Docker, the repository contains a &lt;code&gt;docker-compose.yml&lt;/code&gt; and a &lt;code&gt;.env.example&lt;/code&gt;. The onboarding instruction is two commands:&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;cp&lt;/span&gt; .env.example .env
docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first run downloads base images, which takes a few minutes once. Every subsequent run starts in under five seconds. The entire environment (exact Python version, exact Postgres version, exact Redis version, correct config) is encoded in files that live in version control alongside the application code.&lt;/p&gt;

&lt;p&gt;When you upgrade from PostgreSQL 15 to 16, you change one line in &lt;code&gt;docker-compose.yml&lt;/code&gt; and commit it. Every developer on the team gets the upgrade on their next pull. No announcement in Slack. No "make sure you've upgraded your local Postgres" in the README.&lt;/p&gt;

&lt;p&gt;This is Docker's most underrated value for teams. The environment becomes a first-class artifact of the project, versioned, reproducible, and reviewable just like the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Now Understand
&lt;/h2&gt;

&lt;p&gt;The phrase "it works on my machine" describes a configuration management failure, not a code problem. Docker's answer is to make the environment part of the artifact, not documented alongside it but included inside it.&lt;/p&gt;

&lt;p&gt;That's the shift. Not "write better setup instructions." Bundle the setup into something that runs.&lt;/p&gt;

&lt;p&gt;Your concrete next step: take an existing project, a simple web app or a script, and write a Dockerfile for it. Don't worry about making it production-perfect. Get it building and running locally. The feedback loop of seeing what breaks and why is how this becomes intuition rather than theory.&lt;/p&gt;

&lt;p&gt;Once you're comfortable with that, the natural next steps are multi-stage builds for smaller production images, volumes for stateful workloads, and eventually Kubernetes for running containers across multiple machines. But those are layers built on top of this foundation. Get the foundation first.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Build a Portfolio Website From Scratch – A Complete Journey</title>
      <dc:creator>Nishant Gaurav </dc:creator>
      <pubDate>Fri, 13 Feb 2026 20:22:01 +0000</pubDate>
      <link>https://dev.to/im_nishant/how-to-build-a-portfolio-website-from-scratch-a-complete-journey-2mj3</link>
      <guid>https://dev.to/im_nishant/how-to-build-a-portfolio-website-from-scratch-a-complete-journey-2mj3</guid>
      <description>&lt;h2&gt;
  
  
  PART 1: The Full Journey
&lt;/h2&gt;




&lt;h3&gt;
  
  
  Preview: Light Mode
&lt;/h3&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%2Fzc43u7yzxs42cjgfcge4.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%2Fzc43u7yzxs42cjgfcge4.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. When I Started Building My Portfolio
&lt;/h2&gt;

&lt;p&gt;When I decided to build my portfolio, I knew I didn’t want it to look like a “template-based” website. I wanted my site to show who I was as a developer: organized, clean, and systematic.&lt;/p&gt;

&lt;p&gt;So long before I wrote even one line of code, I planned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The sections I wanted to show on my portfolio.&lt;/li&gt;
&lt;li&gt;How do recruiters view portfolios?&lt;/li&gt;
&lt;li&gt;What is shown at the top of my portfolio (above the fold).&lt;/li&gt;
&lt;li&gt;How to balance content with images on my portfolio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final structure is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navbar&lt;/li&gt;
&lt;li&gt;Hero / About&lt;/li&gt;
&lt;li&gt;Projects&lt;/li&gt;
&lt;li&gt;Skills&lt;/li&gt;
&lt;li&gt;Achievements &amp;amp; Certifications&lt;/li&gt;
&lt;li&gt;Contact&lt;/li&gt;
&lt;li&gt;Footer&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt;&lt;br&gt;
“If someone spends 30 seconds on my site, they should be able to identify who I am technically.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Structuring the HTML Layout
&lt;/h2&gt;

&lt;p&gt;I built everything using &lt;strong&gt;semantic HTML + Bootstrap grid&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each section was wrapped inside a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; tag:&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="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"about"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"projects"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"skills"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allowed me to achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anchor navigation&lt;/li&gt;
&lt;li&gt;SEO-friendly structure&lt;/li&gt;
&lt;li&gt;Clean scroll targeting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layout scaffolding:&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="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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&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;"col-md-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bootstrap handled responsiveness, while custom CSS handled visual identity.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Designing the Navbar
&lt;/h2&gt;

&lt;p&gt;Since the navbar is the first thing people see when they enter the application, it was important for me to keep it in the following ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed at the top&lt;/li&gt;
&lt;li&gt;Minimal&lt;/li&gt;
&lt;li&gt;Navigation-focused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logo + Name branding&lt;/li&gt;
&lt;li&gt;Anchor navigation links&lt;/li&gt;
&lt;li&gt;Theme toggle switch
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&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-expand-lg fixed-top custom-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hover animation:&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;.navbar-nav&lt;/span&gt; &lt;span class="nc"&gt;.nav-link&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&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;width&lt;/span&gt; &lt;span class="m"&gt;0.3s&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;h2&gt;
  
  
  4. Building the Hero / About Section
&lt;/h2&gt;

&lt;p&gt;This section had to communicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who I am&lt;/li&gt;
&lt;li&gt;What I do&lt;/li&gt;
&lt;li&gt;What I’ve achieved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two-column layout:&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="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row align-items-center"&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;"col-md-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Image&lt;span class="nt"&gt;&amp;lt;/div&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;"col-md-7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Content&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;UI decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rounded profile image&lt;/li&gt;
&lt;li&gt;Shadow wrapper&lt;/li&gt;
&lt;li&gt;Using GIFs for accents.&lt;/li&gt;
&lt;li&gt;Using bold text for highlights.&lt;/li&gt;
&lt;li&gt;Resume links
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.about_img--wrapper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Projects Section: Card Architecture
&lt;/h2&gt;

&lt;p&gt;I designed projects as product tiles.&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="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-md-6 col-lg-4"&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;"project-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Design decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;25px radius&lt;/li&gt;
&lt;li&gt;Muted teal background&lt;/li&gt;
&lt;li&gt;Hover lift
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.project-card&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Skills Section: Visualizing Competence
&lt;/h2&gt;

&lt;p&gt;Custom progress bars:&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="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"skill-bar"&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;"skill-fill"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:85%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.skill-bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#7c8d8f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.skill-fill&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1f2022&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;Split into two columns for balance.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Achievements &amp;amp; Certifications:
&lt;/h2&gt;

&lt;p&gt;Image-driven proof cards.&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;.achievement-img-wrapper&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;260px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&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;Hover zoom:&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;.achievement-card&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="nc"&gt;.achievement-img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. Contact Section:
&lt;/h2&gt;

&lt;p&gt;Two layers:&lt;br&gt;
&lt;strong&gt;Quick Links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Contact Form&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="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hover elevation:&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;.contact-card&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Footer: Closing Identity
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Logo&lt;/li&gt;
&lt;li&gt;Copyright&lt;/li&gt;
&lt;li&gt;Social icons
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.footer-icon&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Dark &amp;amp; Light Mode Implementation:
&lt;/h2&gt;

&lt;p&gt;Theme toggle via JS &amp;amp; Persistence:&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;toggleBtn&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;change&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="nx"&gt;body&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;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark-mode&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;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theme&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;dark&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;h2&gt;
  
  
  Dark Mode
&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%2Fbwhb9jveixjxruy5thct.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%2Fbwhb9jveixjxruy5thct.png" alt=" " width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Dark-Mode Decisions:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="nc"&gt;.dark-mode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0f1115&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e6e6e6&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;Adjustments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gradient cards&lt;/li&gt;
&lt;li&gt;Teal skill bars&lt;/li&gt;
&lt;li&gt;Dark inputs&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Goal: Reduce eye strain.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  11. Layout Engineering:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bootstrap Grid → Structure&lt;/li&gt;
&lt;li&gt;Flexbox → Alignment
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;display&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;align-items&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;center&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. Color &amp;amp; Typography:
&lt;/h2&gt;

&lt;p&gt;Palette:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;#7eaeb4&lt;/code&gt; Accent&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#393E46&lt;/code&gt; Dark&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#f4f5f7&lt;/code&gt; Light
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card-title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Courier New'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. Responsiveness:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;767px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.skill-bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&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;h2&gt;
  
  
  14. Challenges:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dark mode contrast&lt;/li&gt;
&lt;li&gt;Card consistency&lt;/li&gt;
&lt;li&gt;Image scaling&lt;/li&gt;
&lt;li&gt;Navbar shadows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Micro-UI Decisions:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hover lifts&lt;/li&gt;
&lt;li&gt;Underline nav animation&lt;/li&gt;
&lt;li&gt;Skill transitions&lt;/li&gt;
&lt;li&gt;Icon scaling&lt;/li&gt;
&lt;li&gt;Section accents&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  PART 2: What I Learned
&lt;/h1&gt;

&lt;h3&gt;
  
  
  HTML Semantics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"projects"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CSS Positioning
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;position&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;fixed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Flexbox
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;display&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;flex&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Grid
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&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;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Responsive Design
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Media Queries
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Theme Switching
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theme&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;dark&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;h3&gt;
  
  
  Clean UI Principles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Spacing&lt;/li&gt;
&lt;li&gt;Contrast&lt;/li&gt;
&lt;li&gt;Hierarchy&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Reflection
&lt;/h2&gt;

&lt;p&gt;This portfolio became more than a website.&lt;/p&gt;

&lt;p&gt;It taught me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI architecture&lt;/li&gt;
&lt;li&gt;Theme systems&lt;/li&gt;
&lt;li&gt;Responsive thinking&lt;/li&gt;
&lt;li&gt;Developer storytelling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it represents me better than any resume.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>css</category>
      <category>portfolio</category>
    </item>
    <item>
      <title>Building Production-Grade Networking Foundations — From Single Server to Kubernetes</title>
      <dc:creator>Nishant Gaurav </dc:creator>
      <pubDate>Thu, 05 Feb 2026 17:49:44 +0000</pubDate>
      <link>https://dev.to/im_nishant/building-production-grade-networking-foundations-from-single-server-to-kubernetes-7gp</link>
      <guid>https://dev.to/im_nishant/building-production-grade-networking-foundations-from-single-server-to-kubernetes-7gp</guid>
      <description>&lt;h2&gt;
  
  
  Why Networking Fundamentals Are Important for CS/IT Students
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For any CS/IT student, networking is not just a subject; it is the backbone of all digital systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you are building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web applications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mobile backends&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microservices architectures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything depends on &lt;strong&gt;Data Communication&lt;/strong&gt; across networks.&lt;/p&gt;

&lt;p&gt;Understanding networking helps in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Debugging production issues&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Designing scalable systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Securing applications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cracking system design &amp;amp; interview rounds&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It bridges the gap between coding and real-world deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Evolution of Modern Application Networking
&lt;/h2&gt;

&lt;p&gt;Let’s start with the big picture — how application networking evolves as systems scale.&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%2Fwe5lezb0akkq2p949v4q.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%2Fwe5lezb0akkq2p949v4q.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This visual represents the journey from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Single Server → Multiple Servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security Segmentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet Access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud Migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker Containers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kubernetes Orchestration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It shows that networking is not static; it grows with system complexity. As applications gain users, traffic increases. This forces architectural and networking transformations.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Single Server Architecture — The Starting Point
&lt;/h2&gt;

&lt;p&gt;Every application begins simply.&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%2F8ah73harhgvc96a5yfb5.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%2F8ah73harhgvc96a5yfb5.png" alt=" " width="800" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this stage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The entire application runs on one machine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backend, frontend, and database share resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment and networking are straightforward&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Users Reach the Server
&lt;/h3&gt;

&lt;p&gt;This introduces IP Addressing.&lt;/p&gt;

&lt;p&gt;An IP address is a unique numeric identifier assigned to every device on a network.&lt;/p&gt;

&lt;p&gt;Example: &lt;code&gt;203.0.109.88&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When a user sends a request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The browser contacts the IP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request travels via routers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server responds&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process follows the &lt;strong&gt;TCP/IP Model&lt;/strong&gt;, where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;IP handles addressing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TCP ensures reliable delivery&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Role of DNS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Humans cannot remember IPs, so we use DNS (Domain Name System).&lt;/p&gt;

&lt;p&gt;DNS translates:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;travelDestination.com → 203.0.109.88&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It works like the internet’s phonebook.&lt;/p&gt;

&lt;p&gt;Without DNS, accessing websites would require memorizing numeric IPs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Multiple Applications on a Single Server
&lt;/h3&gt;

&lt;p&gt;As applications grow, multiple services run on the same server.&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%2F5spa3t8ecbq4i6jzuv96.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%2F5spa3t8ecbq4i6jzuv96.png" alt=" " width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web Application&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MySQL Database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payment Service&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But they share the same IP.&lt;/p&gt;

&lt;p&gt;So how does the server differentiate requests?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer: Ports&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ports are logical communication channels.&lt;/p&gt;

&lt;p&gt;Common ports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;80&lt;/strong&gt; → HTTP (Web)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;443&lt;/strong&gt; → HTTPS (Secure Web)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;3306&lt;/strong&gt; → MySQL&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Port range: &lt;code&gt;0 – 65535&lt;/code&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;IP → Building address&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port → Apartment number&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This mapping happens at the Transport Layer (OSI Model).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Security &amp;amp; Network Segmentation
&lt;/h3&gt;

&lt;p&gt;Running everything together creates risk.&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%2Fsy54gc3526mxdlvbs3ut.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%2Fsy54gc3526mxdlvbs3ut.png" alt=" " width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem: Single Point of Failure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If one layer is compromised:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The entire system is exposed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database becomes vulnerable&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution: Network Segmentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The network is divided into subnets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Frontend Layer (Subnet 1)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application Layer (Subnet 2)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database Layer (Subnet 3)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Security&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Traffic control&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fault isolation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Supporting Components&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Direct traffic between subnets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose optimal paths&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Firewalls&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Control incoming/outgoing traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Types shown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Host-based firewall&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network firewall&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This layered approach reduces the attack surface, a key cybersecurity principle.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Private Servers &amp;amp; Internet Access (NAT)
&lt;/h3&gt;

&lt;p&gt;When databases and backend services move to private networks, they lose direct internet access.&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%2Fw51z2vz57cvoejr1vax5.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%2Fw51z2vz57cvoejr1vax5.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Private servers use &lt;strong&gt;private IP ranges&lt;/strong&gt; like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;10.x.x.x&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;172.16.x.x&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;192.168.x.x&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  These are not routable on the public internet.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Solution: NAT (Network Address Translation)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NAT allows private servers to access the internet via a gateway.&lt;/p&gt;

&lt;p&gt;Working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Private server sends a request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NAT gateway replaces private IP with public IP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet responds&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gateway maps response back&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;IP conservation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security masking&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Controlled exposure&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Bottleneck risk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Latency increase&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mapping overhead&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Moving to the Cloud
&lt;/h3&gt;

&lt;p&gt;To overcome hardware and scaling limits, systems migrate to cloud platforms.&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%2F90ny2pgdf612swu9d5b1.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%2F90ny2pgdf612swu9d5b1.png" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of owning servers, we rent infrastructure.&lt;/p&gt;

&lt;p&gt;This introduces &lt;strong&gt;Cloud Networking&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Key Component: VPC (Virtual Private Cloud)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A VPC is an isolated virtual network inside the cloud.&lt;/p&gt;

&lt;p&gt;It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Public Subnet → Frontend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Private Subnet → App &amp;amp; DB&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Internet Gateway&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connects VPC resources to the internet.
&lt;/h2&gt;

&lt;p&gt;Benefits&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;High availability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto scaling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Managed infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better isolation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloud networking still follows TCP/IP and OSI principles, just virtualized.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Containerization with Docker
&lt;/h3&gt;

&lt;p&gt;As microservices grow, dependency management becomes complex.&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%2F5iam02n1tmr86b7cdv0s.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%2F5iam02n1tmr86b7cdv0s.png" alt=" " width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Different runtimes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Library conflicts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment inconsistency&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution: Containers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A container package:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runtime&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libraries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependencies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So it runs identically everywhere.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Container Networking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bridge Network (Single Host)&lt;/em&gt;&lt;br&gt;
Containers communicate internally.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Overlay Network (Multi-Host)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Containers communicate across servers.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Port Mapping&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;9090 → 9090&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Maps the host port to the container port so external users can access services. This integrates container workloads into existing network stacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Orchestrating with Kubernetes
&lt;/h3&gt;

&lt;p&gt;When containers scale across many servers, orchestration is required.&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%2F9cjwk6n9onqonbxv79vd.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%2F9cjwk6n9onqonbxv79vd.png" alt=" " width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes automates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Scheduling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scaling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto-healing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Networking&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Pods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Smallest deployable unit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Contain one or more containers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get temporary IPs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Problem: Pods are dynamic.&lt;/p&gt;

&lt;p&gt;If a Pod dies, its IP changes.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Kubernetes Services&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stable IP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load balancing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service discovery&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  They act as a bridge between users and Pods.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ingress Controller&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Handles external traffic routing.&lt;/p&gt;

&lt;p&gt;Functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Single entry point&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL-based routing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduces need for multiple public IPs&lt;br&gt;
This is production-grade networking.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Additional Networking Concepts (Value Add)
&lt;/h2&gt;

&lt;p&gt;To connect everything academically:&lt;/p&gt;

&lt;h3&gt;
  
  
  OSI Model in This Architecture
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Role Here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Application&lt;/td&gt;
&lt;td&gt;Web apps, APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transport&lt;/td&gt;
&lt;td&gt;TCP ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;IP routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Link&lt;/td&gt;
&lt;td&gt;MAC communication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Physical&lt;/td&gt;
&lt;td&gt;Cloud/DC hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;TCP/IP Model Mapping&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Application → HTTP, DNS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transport → TCP/UDP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet → IP, NAT&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network Access → Ethernet, Wi-Fi&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Network Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LAN&lt;/strong&gt; → Within data center/VPC&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MAN&lt;/strong&gt; → City-wide ISP networks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WAN&lt;/strong&gt; → Internet backbone&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud systems operate across WANs.
&lt;/h2&gt;

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

&lt;p&gt;My journey through Networking Fundamentals transformed how I view software systems.&lt;/p&gt;

&lt;p&gt;Key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Applications start simple, but networking grows with scale&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IP addressing and DNS enable global connectivity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ports allow multi-service communication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Segmentation improves security&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NAT enables controlled internet access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud networking virtualizes infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker standardizes deployments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kubernetes orchestrates at scale&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>cloud</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building Production-Grade Networking Foundations — From Single Server to Kubernetes</title>
      <dc:creator>Nishant Gaurav </dc:creator>
      <pubDate>Thu, 05 Feb 2026 17:49:44 +0000</pubDate>
      <link>https://dev.to/im_nishant/building-production-grade-networking-foundations-from-single-server-to-kubernetes-2k61</link>
      <guid>https://dev.to/im_nishant/building-production-grade-networking-foundations-from-single-server-to-kubernetes-2k61</guid>
      <description>&lt;h2&gt;
  
  
  Why Networking Fundamentals Are Important for CS/IT Students
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For any CS/IT student, networking is not just a subject; it is the backbone of all digital systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you are building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web applications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mobile backends&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microservices architectures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything depends on &lt;strong&gt;Data Communication&lt;/strong&gt; across networks.&lt;/p&gt;

&lt;p&gt;Understanding networking helps in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Debugging production issues&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Designing scalable systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Securing applications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cracking system design &amp;amp; interview rounds&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It bridges the gap between coding and real-world deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Evolution of Modern Application Networking
&lt;/h2&gt;

&lt;p&gt;Let’s start with the big picture — how application networking evolves as systems scale.&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%2Fwe5lezb0akkq2p949v4q.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%2Fwe5lezb0akkq2p949v4q.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This visual represents the journey from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Single Server → Multiple Servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security Segmentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet Access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud Migration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker Containers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kubernetes Orchestration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It shows that networking is not static; it grows with system complexity. As applications gain users, traffic increases. This forces architectural and networking transformations.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Single Server Architecture — The Starting Point
&lt;/h2&gt;

&lt;p&gt;Every application begins simply.&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%2F8ah73harhgvc96a5yfb5.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%2F8ah73harhgvc96a5yfb5.png" alt=" " width="800" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this stage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The entire application runs on one machine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backend, frontend, and database share resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment and networking are straightforward&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Users Reach the Server
&lt;/h3&gt;

&lt;p&gt;This introduces IP Addressing.&lt;/p&gt;

&lt;p&gt;An IP address is a unique numeric identifier assigned to every device on a network.&lt;/p&gt;

&lt;p&gt;Example: &lt;code&gt;203.0.109.88&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When a user sends a request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The browser contacts the IP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request travels via routers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server responds&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process follows the &lt;strong&gt;TCP/IP Model&lt;/strong&gt;, where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;IP handles addressing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TCP ensures reliable delivery&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Role of DNS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Humans cannot remember IPs, so we use DNS (Domain Name System).&lt;/p&gt;

&lt;p&gt;DNS translates:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;travelDestination.com → 203.0.109.88&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It works like the internet’s phonebook.&lt;/p&gt;

&lt;p&gt;Without DNS, accessing websites would require memorizing numeric IPs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Multiple Applications on a Single Server
&lt;/h3&gt;

&lt;p&gt;As applications grow, multiple services run on the same server.&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%2F5spa3t8ecbq4i6jzuv96.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%2F5spa3t8ecbq4i6jzuv96.png" alt=" " width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Web Application&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MySQL Database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payment Service&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But they share the same IP.&lt;/p&gt;

&lt;p&gt;So how does the server differentiate requests?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer: Ports&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ports are logical communication channels.&lt;/p&gt;

&lt;p&gt;Common ports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;80&lt;/strong&gt; → HTTP (Web)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;443&lt;/strong&gt; → HTTPS (Secure Web)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;3306&lt;/strong&gt; → MySQL&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Port range: &lt;code&gt;0 – 65535&lt;/code&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;IP → Building address&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port → Apartment number&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This mapping happens at the Transport Layer (OSI Model).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Security &amp;amp; Network Segmentation
&lt;/h3&gt;

&lt;p&gt;Running everything together creates risk.&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%2Fsy54gc3526mxdlvbs3ut.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%2Fsy54gc3526mxdlvbs3ut.png" alt=" " width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem: Single Point of Failure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If one layer is compromised:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The entire system is exposed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database becomes vulnerable&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution: Network Segmentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The network is divided into subnets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Frontend Layer (Subnet 1)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application Layer (Subnet 2)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database Layer (Subnet 3)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Security&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Traffic control&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Fault isolation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Supporting Components&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Direct traffic between subnets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose optimal paths&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Firewalls&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Control incoming/outgoing traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Types shown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Host-based firewall&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network firewall&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This layered approach reduces the attack surface, a key cybersecurity principle.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Private Servers &amp;amp; Internet Access (NAT)
&lt;/h3&gt;

&lt;p&gt;When databases and backend services move to private networks, they lose direct internet access.&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%2Fw51z2vz57cvoejr1vax5.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%2Fw51z2vz57cvoejr1vax5.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Private servers use &lt;strong&gt;private IP ranges&lt;/strong&gt; like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;10.x.x.x&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;172.16.x.x&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;192.168.x.x&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  These are not routable on the public internet.
&lt;/h2&gt;

&lt;p&gt;*&lt;em&gt;Solution: NAT (Network Address Translation)&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
NAT allows private servers to access the internet via a gateway.&lt;/p&gt;

&lt;p&gt;Working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Private server sends a request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NAT gateway replaces private IP with public IP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet responds&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gateway maps response back&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;IP conservation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security masking&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Controlled exposure&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Bottleneck risk&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Latency increase&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mapping overhead&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Moving to the Cloud
&lt;/h3&gt;

&lt;p&gt;To overcome hardware and scaling limits, systems migrate to cloud platforms.&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%2F90ny2pgdf612swu9d5b1.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%2F90ny2pgdf612swu9d5b1.png" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of owning servers, we rent infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  This introduces &lt;strong&gt;Cloud Networking&lt;/strong&gt;.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Key Component: VPC (Virtual Private Cloud)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A VPC is an isolated virtual network inside the cloud.&lt;/p&gt;

&lt;p&gt;It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Public Subnet → Frontend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Private Subnet → App &amp;amp; DB&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Internet Gateway&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connects VPC resources to the internet.
&lt;/h2&gt;

&lt;p&gt;Benefits&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;High availability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto scaling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Managed infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better isolation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloud networking still follows TCP/IP and OSI principles, just virtualized.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Containerization with Docker
&lt;/h3&gt;

&lt;p&gt;As microservices grow, dependency management becomes complex.&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%2F5iam02n1tmr86b7cdv0s.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%2F5iam02n1tmr86b7cdv0s.png" alt=" " width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Different runtimes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Library conflicts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment inconsistency&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution: Containers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A container package:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runtime&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Libraries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependencies&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So it runs identically everywhere.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Container Networking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bridge Network (Single Host)&lt;/em&gt;&lt;br&gt;
Containers communicate internally.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Overlay Network (Multi-Host)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Containers communicate across servers.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Port Mapping&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;9090 → 9090&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Maps the host port to the container port so external users can access services. This integrates container workloads into existing network stacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Orchestrating with Kubernetes
&lt;/h3&gt;

&lt;p&gt;When containers scale across many servers, orchestration is required.&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%2F9cjwk6n9onqonbxv79vd.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%2F9cjwk6n9onqonbxv79vd.png" alt=" " width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes automates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Scheduling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scaling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto-healing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Networking
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Smallest deployable unit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Contain one or more containers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get temporary IPs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Problem: Pods are dynamic.&lt;/p&gt;

&lt;p&gt;If a Pod dies, its IP changes.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Kubernetes Services&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stable IP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load balancing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Service discovery&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  They act as a bridge between users and Pods.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ingress Controller&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Handles external traffic routing.&lt;/p&gt;

&lt;p&gt;Functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Single entry point&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL-based routing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduces need for multiple public IPs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  This is production-grade networking.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Additional Networking Concepts (Value Add)
&lt;/h2&gt;

&lt;p&gt;To connect everything academically:&lt;/p&gt;

&lt;h3&gt;
  
  
  OSI Model in This Architecture
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Role Here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Application&lt;/td&gt;
&lt;td&gt;Web apps, APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transport&lt;/td&gt;
&lt;td&gt;TCP ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;IP routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Link&lt;/td&gt;
&lt;td&gt;MAC communication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Physical&lt;/td&gt;
&lt;td&gt;Cloud/DC hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;TCP/IP Model Mapping&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Application → HTTP, DNS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transport → TCP/UDP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet → IP, NAT&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - Network Access → Ethernet, Wi-Fi
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Network Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LAN&lt;/strong&gt; → Within data center/VPC&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MAN&lt;/strong&gt; → City-wide ISP networks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WAN&lt;/strong&gt; → Internet backbone&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud systems operate across WANs.
&lt;/h2&gt;

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

&lt;p&gt;My journey through Networking Fundamentals transformed how I view software systems.&lt;/p&gt;

&lt;p&gt;Key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Applications start simple, but networking grows with scale&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IP addressing and DNS enable global connectivity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ports allow multi-service communication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Segmentation improves security&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NAT enables controlled internet access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud networking virtualizes infrastructure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker standardizes deployments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kubernetes orchestrates at scale&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>cloud</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
