<?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: Philip Damwanza</title>
    <description>The latest articles on DEV Community by Philip Damwanza (@kahenda).</description>
    <link>https://dev.to/kahenda</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%2F3937261%2F3721da6e-5b7b-40d8-b5f0-34d2e401a4d8.png</url>
      <title>DEV Community: Philip Damwanza</title>
      <link>https://dev.to/kahenda</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kahenda"/>
    <language>en</language>
    <item>
      <title>Calculating Days in JS: A Beginner's Guide</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Thu, 13 Aug 2026 07:19:12 +0000</pubDate>
      <link>https://dev.to/kahenda/calculating-days-in-js-a-beginners-guide-1ii8</link>
      <guid>https://dev.to/kahenda/calculating-days-in-js-a-beginners-guide-1ii8</guid>
      <description>&lt;p&gt;Ever wanted to know what numerical "day of the year" a date falls on (e.g., January 31st is day 31, but February 1st is day 32)?&lt;/p&gt;

&lt;p&gt;We can do this easily by subtracting January 1st from our target date and converting milliseconds into days!&lt;/p&gt;

&lt;p&gt;JavaScript&lt;br&gt;
function dayOfTheYear(date) {&lt;br&gt;
  const year = date.getFullYear();&lt;/p&gt;

&lt;p&gt;// Get January 1st of that exact year&lt;br&gt;
  const startOfYear = new Date(year, 0, 1);&lt;/p&gt;

&lt;p&gt;// Find the difference in milliseconds&lt;br&gt;
  const diffTime = date.getTime() - startOfYear.getTime();&lt;/p&gt;

&lt;p&gt;// Convert milliseconds to days (1000ms * 60s * 60m * 24hrs)&lt;br&gt;
  // Plus 1 because January 1st itself is Day 1, not Day 0!&lt;br&gt;
  const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)) + 1;&lt;/p&gt;

&lt;p&gt;return diffDays;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;console.log(dayOfTheYear(new Date("2026-01-01"))); // Output: 1&lt;br&gt;
console.log(dayOfTheYear(new Date("2026-02-01"))); // Output: 32&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building QrStamp: A Lightning-Fast QR Code &amp; Analytics Tracker in Go</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Mon, 03 Aug 2026 07:12:05 +0000</pubDate>
      <link>https://dev.to/kahenda/building-qrstamp-a-lightning-fast-qr-code-analytics-tracker-in-go-15p6</link>
      <guid>https://dev.to/kahenda/building-qrstamp-a-lightning-fast-qr-code-analytics-tracker-in-go-15p6</guid>
      <description>&lt;p&gt;Need a lightweight, self-hosted service to generate trackable QR codes without dealing with third-party SaaS limits? I built QrStamp—a minimalist, high-performance web application powered by Go, SQLite, and vanilla web tech.&lt;/p&gt;

&lt;p&gt;Why Go &amp;amp; SQLite?&lt;br&gt;
Go (net/http): Delivers blazing-fast server execution and concurrency for handling redirects and stats tracking effortlessly.&lt;/p&gt;

&lt;p&gt;SQLite (modernc.org/sqlite): Provides zero-config, embedded data storage so the entire app runs as a single portable file.&lt;/p&gt;

&lt;p&gt;QR Generation: Uses &lt;a href="https://github.com/skip2/go-qrcode" rel="noopener noreferrer"&gt;github.com/skip2/go-qrcode&lt;/a&gt; to encode PNG assets on the fly.&lt;/p&gt;

&lt;p&gt;Core Backend Architecture&lt;br&gt;
The heart of QrStamp relies on atomic database transactions. When someone scans a unique tracking link (e.g., /qr/{id}), the server immediately looks up the destination URL and increments the scan counter in a single step:&lt;/p&gt;

&lt;p&gt;Go&lt;br&gt;
func (db *DB) ScanAndGetURL(id string) (string, error) {&lt;br&gt;
    tx, err := db.Begin()&lt;br&gt;
    if err != nil {&lt;br&gt;
        return "", err&lt;br&gt;
    }&lt;br&gt;
    defer tx.Rollback()&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var originalURL string
err = tx.QueryRow(`SELECT original_url FROM qrcodes WHERE id = ?`, id).Scan(&amp;amp;originalURL)
if err != nil {
    return "", err
}

_, err = tx.Exec(`UPDATE qrcodes SET scans = scans + 1 WHERE id = ?`, id)
if err != nil {
    return "", err
}

return originalURL, tx.Commit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
The Result&lt;br&gt;
With a modern dark-mode UI, instant QR rendering, and a real-time scan metrics counter, QrStamp is the ultimate quick utility project for anyone looking to sharpen their backend skills in Go.&lt;/p&gt;

</description>
      <category>go</category>
      <category>ai</category>
      <category>productivity</category>
      <category>qrstamp</category>
    </item>
    <item>
      <title>Building DevSpot Kenya: A Lightweight Tech Event Aggregator in Go</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Mon, 03 Aug 2026 06:13:00 +0000</pubDate>
      <link>https://dev.to/kahenda/building-devspot-kenya-a-lightweight-tech-event-aggregator-in-go-3b47</link>
      <guid>https://dev.to/kahenda/building-devspot-kenya-a-lightweight-tech-event-aggregator-in-go-3b47</guid>
      <description>&lt;p&gt;If you have ever tried keeping up with tech meetups, developer workshops, and hackathons across Kenya, you know how scattered the information can be. Announcements are often buried across various social platforms, making it tough to stay in the loop.&lt;/p&gt;

&lt;p&gt;To solve this, I built DevSpot Kenya—a lightweight platform designed to aggregate local technology events into a single, centralized hub.&lt;/p&gt;

&lt;p&gt;The Tech Stack&lt;br&gt;
To keep things fast, reliable, and straightforward, I used:&lt;/p&gt;

&lt;p&gt;Backend: Go (using the Gin framework) for high-performance routing and lightweight API endpoints.&lt;/p&gt;

&lt;p&gt;Database: SQLite for simple, file-based data storage during development.&lt;/p&gt;

&lt;p&gt;Scraper &amp;amp; Ingestion: Custom event scraper and API handlers to ingest event batches and clean up link data.&lt;/p&gt;

&lt;p&gt;Containerization: Docker for smooth deployment and local testing.&lt;/p&gt;

&lt;p&gt;How the Backend Comes Together&lt;br&gt;
Here is a quick look at how the core Gin router handles setting up endpoints for incoming events:&lt;/p&gt;

&lt;p&gt;Go&lt;br&gt;
package main&lt;/p&gt;

&lt;p&gt;import (&lt;br&gt;
    "net/http"&lt;br&gt;
    "github.com/gin-gonic/gin"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;type Event struct {&lt;br&gt;
    ID          string &lt;code&gt;json:"id"&lt;/code&gt;&lt;br&gt;
    Title       string &lt;code&gt;json:"title"&lt;/code&gt;&lt;br&gt;
    Location    string &lt;code&gt;json:"location"&lt;/code&gt;&lt;br&gt;
    EventDate   string &lt;code&gt;json:"event_date"&lt;/code&gt;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;func main() {&lt;br&gt;
    r := gin.Default()&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;r.GET("/api/events", func(c *gin.Context) {
    // Fetch events logic here
    c.JSON(http.StatusOK, gin.H{
        "message": "Fetching DevSpot Kenya events...",
    })
})

r.Run(":8080")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
What I Learned&lt;br&gt;
Simplicity Wins: Using Go combined with SQLite cut out unnecessary configuration overhead, letting me focus entirely on clean data ingestion and API logic.&lt;/p&gt;

&lt;p&gt;Environment Management: Properly setting up .gitignore early on saved me from pushing local database files and build binaries to GitHub.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>devspotke</category>
    </item>
    <item>
      <title>3 Simple Go Habits That Will Save You Hours of Debugging</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Mon, 03 Aug 2026 05:59:02 +0000</pubDate>
      <link>https://dev.to/kahenda/3-simple-go-habits-that-will-save-you-hours-of-debugging-47j3</link>
      <guid>https://dev.to/kahenda/3-simple-go-habits-that-will-save-you-hours-of-debugging-47j3</guid>
      <description>&lt;p&gt;We have all been there. You look at a Go function you wrote just two weeks ago, and it looks like a complete mystery. Writing code that compiles is easy. Writing Go code that is readable, maintainable, and easy to debug is the real superpower.The Go philosophy values simplicity and clarity over cleverness. You do not need to master complex architecture to write better code today. Here are three simple, actionable habits you can start using in your next package.1. Use Meaningful Names (But Keep Go Idioms in Mind)Go prefers short variable names, but they must still carry clear meaning based on their scope. Avoid cryptic, single-letter names for long functions or global states.❌ Bad:gofunc process(d time.Duration) {&lt;br&gt;
    // confusing if the function is long&lt;br&gt;
    let t := time.Now().Add(d) &lt;br&gt;
}&lt;br&gt;
Use code with caution.✅ Good:gofunc process(expiryTimeout time.Duration) {&lt;br&gt;
    deadline := time.Now().Add(expiryTimeout)&lt;br&gt;
}&lt;br&gt;
Use code with caution.Why it matters: Code is read far more often than it is written. While a short r is fine for a receiver or a brief loop index, use descriptive names for data that travels through your application logic.2. Keep Functions Small and Return EarlyGo code can quickly become unreadable if you deeply nest your if statements. Use the "return early" strategy by handling errors immediately. This keeps your successful code path aligned to the left of your screen.❌ Bad (Deeply Nested):gofunc SaveUser(u *User) error {&lt;br&gt;
    if u != nil {&lt;br&gt;
        if u.IsValid() {&lt;br&gt;
            err := db.Save(u)&lt;br&gt;
            if err == nil {&lt;br&gt;
                return nil&lt;br&gt;
            }&lt;br&gt;
            return err&lt;br&gt;
        }&lt;br&gt;
        return errors.New("invalid user")&lt;br&gt;
    }&lt;br&gt;
    return errors.New("nil user")&lt;br&gt;
}&lt;br&gt;
Use code with caution.✅ Good (Return Early):gofunc SaveUser(u *User) error {&lt;br&gt;
    if u == nil {&lt;br&gt;
        return errors.New("nil user")&lt;br&gt;
    }&lt;br&gt;
    if !u.IsValid() {&lt;br&gt;
        return errors.New("invalid user")&lt;br&gt;
    }&lt;br&gt;
    return db.Save(u)&lt;br&gt;
}&lt;br&gt;
Use code with caution.Why it matters: Returning early eliminates the "arrow anti-pattern" (deeply nested code). It makes your functions incredibly easy to read, test, and debug from top to bottom.3. Comment the "Why," Not the "What"Go features self-documenting syntax. Your comments should not repeat what the code plainly states. Instead, use them to explain why a specific approach or workaround was necessary.❌ Bad:go// Increment total by one&lt;br&gt;
total++&lt;br&gt;
Use code with caution.✅ Good:go// Retry limit is set to 3 to prevent hammering the third-party billing API&lt;br&gt;
const maxRetries = 3&lt;br&gt;
Use code with caution.Why it matters: Avoid stating the obvious. Use comments to provide critical business context or architectural constraints that the code itself cannot show.&lt;br&gt;
Clean Go code is not about perfection. It is about empathy for the next developer who touches your project—even if that developer is you.Pick just one of these habits for your next pull request, and notice how much easier debugging becomes!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>go</category>
    </item>
    <item>
      <title>The One-Line Bug That Broke Five People's Imports at Once</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Tue, 28 Jul 2026 07:07:47 +0000</pubDate>
      <link>https://dev.to/kahenda/the-one-line-bug-that-broke-five-peoples-imports-at-once-35m2</link>
      <guid>https://dev.to/kahenda/the-one-line-bug-that-broke-five-peoples-imports-at-once-35m2</guid>
      <description>&lt;p&gt;We're building a forum app in Go for our Zone01 Kisumu cohort — five of us, split by feature: auth, posts, comments, filters, and me leading the core/integration side. Two weeks in, everything was compiling fine. Then one morning I pulled the latest code and the whole project refused to build.&lt;/p&gt;

&lt;p&gt;The error looked something like this:&lt;/p&gt;

&lt;p&gt;internal/posts/categories.go:6:2: package forum/internal/models is not in std&lt;/p&gt;

&lt;p&gt;"Not in std"? My package isn't in the standard library. Weird flex, Go, but okay — what actually happened?&lt;/p&gt;

&lt;p&gt;The setup&lt;/p&gt;

&lt;p&gt;Here's the thing about Go modules that I hadn't really internalized until this bit me: the line at the top of go.mod&lt;/p&gt;

&lt;p&gt;go&lt;br&gt;
module github.com/kahenda/forum&lt;/p&gt;

&lt;p&gt;isn't just a label. It's the namespace your entire project lives inside. Every internal import — internal/models, internal/auth, whatever — has to be spelled out as github.com/kahenda/forum/internal/models, because that prefix is literally derived from that one line.&lt;/p&gt;

&lt;p&gt;Somewhere along the way, a teammate's branch had a go.mod that said module forum instead — probably from running go mod init fresh without checking what was already there. When that got merged, our shared go.mod briefly had the wrong module name. Nobody noticed immediately, because that specific person's own code still compiled — they'd written their imports against the wrong name too, so it was internally consistent for them.&lt;/p&gt;

&lt;p&gt;The explosion happened for everyone else, because our code was written against the correct name, and now the correct name didn't exist anymore.&lt;/p&gt;

&lt;p&gt;Why the error message was so confusing&lt;/p&gt;

&lt;p&gt;package forum/internal/models is not in std doesn't sound like "your go.mod changed." It sounds like Go is looking for your package in its own standard library folder — which, technically, it is! Once the module name changes, Go has no idea forum/internal/models is your code. It just goes looking for it in /usr/lib/go/src/forum/..., finds nothing, and reports exactly that.&lt;/p&gt;

&lt;p&gt;If I hadn't already known what module in go.mod actually controls, I'd have spent an hour convinced my Go installation was broken.&lt;/p&gt;

&lt;p&gt;The fix&lt;/p&gt;

&lt;p&gt;Two-part fix, and both parts matter:&lt;/p&gt;

&lt;p&gt;Restore the correct module line:&lt;br&gt;
go&lt;br&gt;
module github.com/kahenda/forum&lt;br&gt;
Fix every file that had been written against the wrong prefix:&lt;br&gt;
go&lt;br&gt;
// before&lt;br&gt;
import "forum/internal/models"&lt;/p&gt;

&lt;p&gt;// after&lt;br&gt;
import "github.com/kahenda/forum/internal/models"&lt;/p&gt;

&lt;p&gt;That second part is the annoying one — it's not a global find-and-replace across the whole codebase, just whichever files got written during the window when go.mod was wrong. We caught them one build error at a time, which is tedious but at least Go tells you exactly which file and line.&lt;/p&gt;

&lt;p&gt;What I'd tell past-me&lt;/p&gt;

&lt;p&gt;Treat go.mod like you'd treat a database schema in a team project — something one person owns and everyone else pulls, never something anyone regenerates locally without checking first. It's such a small file that it's easy to forget it's load-bearing for literally every import in the project.&lt;/p&gt;

&lt;p&gt;Anyone else had a one-line config change cascade into a dozen confusing error messages? What was yours?&lt;/p&gt;

</description>
      <category>go</category>
      <category>git</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Made Sure You Can't Like and Dislike the Same Post at Once</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Tue, 28 Jul 2026 07:05:31 +0000</pubDate>
      <link>https://dev.to/kahenda/how-i-made-sure-you-cant-like-and-dislike-the-same-post-at-once-56io</link>
      <guid>https://dev.to/kahenda/how-i-made-sure-you-cant-like-and-dislike-the-same-post-at-once-56io</guid>
      <description>&lt;p&gt;Quick one today. While building the reactions feature for our team's forum project (Go + SQLite), I hit a question that sounds obvious until you actually have to implement it: what happens when a user likes a post, then clicks dislike on the same post? Do they end up with both a like and a dislike registered? Because that would be a bug — a post shouldn't be simultaneously liked and disliked by the same person.&lt;/p&gt;

&lt;p&gt;The naive approach (don't do this)&lt;/p&gt;

&lt;p&gt;The tempting first instinct is: every click on Like or Dislike just inserts a new row into a reactions table.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
INSERT INTO reactions (user_id, target_type, target_id, value)&lt;br&gt;
VALUES (?, ?, ?, ?);&lt;/p&gt;

&lt;p&gt;This breaks immediately. Click like, then dislike, and now you've got two rows for the same user and the same post — one with value = 1, one with value = -1. Your like/dislike counts are now both incremented, which is exactly the bug we're trying to avoid.&lt;/p&gt;

&lt;p&gt;The fix: let the database enforce the rule&lt;/p&gt;

&lt;p&gt;Instead of trying to handle this entirely in application code, I put a constraint directly on the table:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
CREATE TABLE reactions (&lt;br&gt;
    id INTEGER PRIMARY KEY AUTOINCREMENT,&lt;br&gt;
    user_id INTEGER NOT NULL,&lt;br&gt;
    target_type TEXT NOT NULL CHECK (target_type IN ('post','comment')),&lt;br&gt;
    target_id INTEGER NOT NULL,&lt;br&gt;
    value INTEGER NOT NULL CHECK (value IN (1,-1)),&lt;br&gt;
    UNIQUE (user_id, target_type, target_id)&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;That UNIQUE (user_id, target_type, target_id) line is doing the real work. It tells SQLite: this combination can only exist once. No matter what your application code does, the database itself won't let a user have two reaction rows for the same post.&lt;/p&gt;

&lt;p&gt;Now the application logic gets simple&lt;/p&gt;

&lt;p&gt;With that constraint in place, "toggle a reaction" becomes a clean three-way decision:&lt;/p&gt;

&lt;p&gt;go&lt;br&gt;
func SetReaction(db *sql.DB, userID, targetID int64, targetType string, value int) error {&lt;br&gt;
    var existing int&lt;br&gt;
    err := db.QueryRow(&lt;br&gt;
        &lt;code&gt;SELECT value FROM reactions WHERE user_id = ? AND target_type = ? AND target_id = ?&lt;/code&gt;,&lt;br&gt;
        userID, targetType, targetID,&lt;br&gt;
    ).Scan(&amp;amp;existing)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;switch {
case err == sql.ErrNoRows:
    // no reaction yet — insert
    _, err = db.Exec(`INSERT INTO reactions (user_id, target_type, target_id, value) VALUES (?, ?, ?, ?)`,
        userID, targetType, targetID, value)
    return err

case existing == value:
    // clicked the same button again — remove it (toggle off)
    _, err = db.Exec(`DELETE FROM reactions WHERE user_id = ? AND target_type = ? AND target_id = ?`,
        userID, targetType, targetID)
    return err

default:
    // switching like &amp;lt;-&amp;gt; dislike — update in place
    _, err = db.Exec(`UPDATE reactions SET value = ? WHERE user_id = ? AND target_type = ? AND target_id = ?`,
        value, userID, targetType, targetID)
    return err
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;Three outcomes, mapped directly to what a user actually expects:&lt;/p&gt;

&lt;p&gt;First click → your reaction gets recorded.&lt;br&gt;
Click the same button again → your reaction gets removed (un-like / un-dislike).&lt;br&gt;
Click the other button → your reaction flips.&lt;br&gt;
Proving it actually works&lt;/p&gt;

&lt;p&gt;The satisfying part was writing a test that walks through all three states in sequence and checks the counts after each step:&lt;/p&gt;

&lt;p&gt;go&lt;br&gt;
repo.ToggleReaction(userID, "post", postID, Like)&lt;br&gt;
// likes = 1, dislikes = 0&lt;/p&gt;

&lt;p&gt;repo.ToggleReaction(userID, "post", postID, Like) // same button again&lt;br&gt;
// likes = 0, dislikes = 0 (toggled off)&lt;/p&gt;

&lt;p&gt;repo.ToggleReaction(userID, "post", postID, Like)&lt;br&gt;
repo.ToggleReaction(userID, "post", postID, Dislike) // switch&lt;br&gt;
// likes = 0, dislikes = 1&lt;/p&gt;

&lt;p&gt;Seeing that last assertion pass — dislikes went up exactly as likes went down, never both — was a nice moment. It's a small feature, but it's the kind of thing that's genuinely broken in a lot of quickly-built apps, and a single UNIQUE constraint is all it took to make it structurally impossible to get wrong.&lt;/p&gt;

&lt;p&gt;Anyone else have a case where a database constraint saved you from writing a pile of application-level validation code?&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>sql</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Mon, 20 Jul 2026 07:39:32 +0000</pubDate>
      <link>https://dev.to/kahenda/-1238</link>
      <guid>https://dev.to/kahenda/-1238</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kahenda/sqlite-vs-postgresql-two-sql-giants-built-for-different-worlds-5ac2" class="crayons-story__hidden-navigation-link"&gt;SQLite vs. PostgreSQL: Two SQL Giants Built for Different Worlds&lt;/a&gt;


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

          &lt;a href="/kahenda" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3937261%2F3721da6e-5b7b-40d8-b5f0-34d2e401a4d8.png" alt="kahenda profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kahenda" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Philip Damwanza
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Philip Damwanza
                
              
              &lt;div id="story-author-preview-content-4185243" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kahenda" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3937261%2F3721da6e-5b7b-40d8-b5f0-34d2e401a4d8.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Philip Damwanza&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kahenda/sqlite-vs-postgresql-two-sql-giants-built-for-different-worlds-5ac2" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kahenda/sqlite-vs-postgresql-two-sql-giants-built-for-different-worlds-5ac2" id="article-link-4185243"&gt;
          SQLite vs. PostgreSQL: Two SQL Giants Built for Different Worlds
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/database"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;database&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kahenda/sqlite-vs-postgresql-two-sql-giants-built-for-different-worlds-5ac2" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kahenda/sqlite-vs-postgresql-two-sql-giants-built-for-different-worlds-5ac2#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

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

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>SQLite vs. PostgreSQL: Two SQL Giants Built for Different Worlds</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Mon, 20 Jul 2026 07:39:01 +0000</pubDate>
      <link>https://dev.to/kahenda/sqlite-vs-postgresql-two-sql-giants-built-for-different-worlds-5ac2</link>
      <guid>https://dev.to/kahenda/sqlite-vs-postgresql-two-sql-giants-built-for-different-worlds-5ac2</guid>
      <description>&lt;p&gt;If you are writing raw SQL queries, your code might look identical whether you use SQLite or PostgreSQL. However, under the hood, they operate in completely opposite ways. SQLite is a serverless database, meaning the entire database is just a single file sitting directly on your disk with zero setup required. PostgreSQL, on the other hand, is a full client-server database that runs as a dedicated background process, requiring network connections to read and write data.&lt;/p&gt;

&lt;p&gt;Because of this difference, they solve entirely different problems. SQLite shines in local development, mobile apps, and standalone CLI tools because it completely bypasses the network, making it incredibly fast and lightweight for single-user scenarios. However, the moment an application goes live on the web and needs to handle multiple users saving data at the exact same millisecond, SQLite will lock up. That is where PostgreSQL takes over, utilizing advanced row-level locking to handle thousands of concurrent readers and writers flawlessly.&lt;/p&gt;

</description>
      <category>database</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Fixed a Git Merge Conflict (Without Losing My Code)</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Mon, 20 Jul 2026 06:53:20 +0000</pubDate>
      <link>https://dev.to/kahenda/how-i-fixed-a-git-merge-conflict-without-losing-my-code-558j</link>
      <guid>https://dev.to/kahenda/how-i-fixed-a-git-merge-conflict-without-losing-my-code-558j</guid>
      <description>&lt;p&gt;We’ve all been there: you are busy coding, and suddenly you get a scary error saying your code conflicts with a teammate's work. Git won't let you pull their changes because it's afraid of overwriting your unsaved files. Instead of panicking, I used git stash. This command acts like a temporary clipboard—it safely hides your current work away so your workspace becomes completely clean.&lt;/p&gt;

&lt;p&gt;With a clean screen, I was able to safely update the project, fix the conflicting lines of code by hand, and make sure everything compiled perfectly. Once the team's updates were safely pushed, I ran git stash pop to bring my hidden work right back. Git wasn't trying to break my project; it was just protecting my code. Next time you get stuck, remember the golden rule: Stash your work, fix the conflict, and pop it back!&lt;/p&gt;

</description>
      <category>git</category>
      <category>programming</category>
      <category>devjournal</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Everyone Says "It Depends" When You Ask About the Best Programming Language</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Fri, 10 Jul 2026 12:03:20 +0000</pubDate>
      <link>https://dev.to/kahenda/why-everyone-says-it-depends-when-you-ask-about-the-best-programming-language-32h6</link>
      <guid>https://dev.to/kahenda/why-everyone-says-it-depends-when-you-ask-about-the-best-programming-language-32h6</guid>
      <description>&lt;p&gt;Ask any developer "what's the best programming language?" and you'll get the same annoying answer: "it depends."&lt;/p&gt;

&lt;p&gt;For example, Go is great for fast, simple backend services. Python is great for quick scripts and data work. JavaScript basically runs the entire web whether you like it or not. Rust is great when you can't afford a single memory bug. None of them are "the best" — they're just the best tool for a specific job.&lt;/p&gt;

&lt;p&gt;Asking for the best language is like asking a carpenter for the best tool. Hammer? Screwdriver? &lt;br&gt;
So all in all it actually depends what you're building.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Nobody Warns You How Much Debugging Is Reading, Not Coding</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Thu, 09 Jul 2026 12:41:59 +0000</pubDate>
      <link>https://dev.to/kahenda/nobody-warns-you-how-much-debugging-is-reading-not-coding-2nm7</link>
      <guid>https://dev.to/kahenda/nobody-warns-you-how-much-debugging-is-reading-not-coding-2nm7</guid>
      <description>&lt;p&gt;When people picture "coding," they picture fast typing and features coming to life. Nobody pictures the real majority of the job: staring at a stack trace or lets say a particular project trying to figure out why something that should work, isn't.&lt;/p&gt;

&lt;p&gt;Here's what nobody tells you starting out — getting good at debugging has almost nothing to do with how well you write code, and everything to do with how well you read.&lt;/p&gt;

&lt;p&gt;The real difference between beginners and experienced devs isn't complex knowledge — it's that experienced devs read carefully and form a hypothesis before touching anything. Beginners (me included) tend to skip straight to changing code and hoping. It feels faster. It rarely is.&lt;br&gt;
One thing i'd like to advise other fellow beginner devs is ....Slow down, read the error properly, and follow the stack trace to where it actually starts — not where it ends up.&lt;/p&gt;

&lt;p&gt;What's a bug that taught you this the hard way?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Philip Damwanza</dc:creator>
      <pubDate>Thu, 09 Jul 2026 08:25:32 +0000</pubDate>
      <link>https://dev.to/kahenda/-4p9i</link>
      <guid>https://dev.to/kahenda/-4p9i</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/dumebii/has-the-audience-for-technical-articles-dropped-5ceh" class="crayons-story__hidden-navigation-link"&gt;Has the audience for technical articles dropped?&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/dumebii/has-the-audience-for-technical-articles-dropped-5ceh" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;AI tools reshaping technical reading habits&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/dumebii" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F941720%2Ff316bf93-ef0b-4bc5-aee2-5e062255d5f0.jpg" alt="dumebii profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/dumebii" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Dumebi Okolo
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Dumebi Okolo
                
              
              &lt;div id="story-author-preview-content-4097205" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/dumebii" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F941720%2Ff316bf93-ef0b-4bc5-aee2-5e062255d5f0.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Dumebi Okolo&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/dumebii/has-the-audience-for-technical-articles-dropped-5ceh" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 8&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/dumebii/has-the-audience-for-technical-articles-dropped-5ceh" id="article-link-4097205"&gt;
          Has the audience for technical articles dropped?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/dumebii/has-the-audience-for-technical-articles-dropped-5ceh" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;70&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/dumebii/has-the-audience-for-technical-articles-dropped-5ceh#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              24&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

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

&lt;/div&gt;


</description>
      <category>community</category>
      <category>discuss</category>
      <category>writing</category>
    </item>
  </channel>
</rss>
