<?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: David</title>
    <description>The latest articles on DEV Community by David (@davidbc01).</description>
    <link>https://dev.to/davidbc01</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%2F4043586%2F0a86db97-792d-4f50-bc67-3647c3d8e0e8.jpg</url>
      <title>DEV Community: David</title>
      <link>https://dev.to/davidbc01</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidbc01"/>
    <language>en</language>
    <item>
      <title>Commitea now has challenges verified against your real GitHub</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sat, 01 Aug 2026 19:22:31 +0000</pubDate>
      <link>https://dev.to/davidbc01/commitea-now-has-challenges-verified-against-your-real-github-28k3</link>
      <guid>https://dev.to/davidbc01/commitea-now-has-challenges-verified-against-your-real-github-28k3</guid>
      <description>&lt;p&gt;A while back I shared &lt;a href="https://github.com/davidbc01/commitea" rel="noopener noreferrer"&gt;Commitea&lt;/a&gt;, my project to teach Git and GitHub in Spanish, with a repo of docs and an interactive visualizer. Since then I kept adding things — search, feedback widget, dark mode, a changelog page.&lt;/p&gt;

&lt;p&gt;But there was still a gap between "reading how something works" and "actually knowing how to do it." So I built the piece that closes that gap: &lt;strong&gt;challenges verified against your real GitHub account.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What changed
&lt;/h3&gt;

&lt;p&gt;Instead of reading how a merge or a Pull Request works and moving on, you now do it — in your own GitHub, with your own Git — and Commitea checks the result against the real API, not a checkbox you tick yourself.&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You connect your GitHub account (OAuth, &lt;code&gt;repo&lt;/code&gt; scope).&lt;/li&gt;
&lt;li&gt;You pick a challenge. Commitea generates a private repo in your account from a template (&lt;code&gt;POST /repos/{owner}/{repo}/generate&lt;/code&gt;), pre-configured with whatever starting state that challenge needs.&lt;/li&gt;
&lt;li&gt;You solve it locally, with your actual Git — clone, branch, commit, push, whatever the challenge asks for.&lt;/li&gt;
&lt;li&gt;You hit "Verify." Commitea queries the GitHub API and tells you exactly what's missing, not just pass/fail.
Three challenges are live right now, each verified differently:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Branches &amp;amp; commits&lt;/strong&gt; — checks a specific branch exists and has enough commits ahead of the default branch (&lt;code&gt;GET /repos/.../compare/{base}...{branch}&lt;/code&gt;, reading &lt;code&gt;ahead_by&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull Request&lt;/strong&gt; — checks at least one PR exists with a real description (not empty, not a single character).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolve a conflict&lt;/strong&gt; — the template repo ships with two branches that genuinely conflict on the same line. Verification checks for a merge commit (a commit with 2+ parents) &lt;em&gt;and&lt;/em&gt; that the file's final content matches the expected resolved value — so you can't just accept one side blindly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A few technical details
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo-per-challenge, not branch-per-challenge.&lt;/strong&gt; I considered a single "progress" repo per user with one branch per challenge, but repo generation via GitHub's template API is built exactly for the one-repo-per-instance case, and verification stays unambiguous — no risk of cross-contamination between unrelated challenges living in the same repo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The default branch is never assumed.&lt;/strong&gt; Early on I hardcoded &lt;code&gt;main&lt;/code&gt; as the comparison target and broke verification for anyone whose repo defaulted to &lt;code&gt;master&lt;/code&gt;. Every verify call now reads &lt;code&gt;default_branch&lt;/code&gt; from &lt;code&gt;GET /repos/{owner}/{repo}&lt;/code&gt; first and compares against that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progress lives in Redis (Vercel KV)&lt;/strong&gt;, one JSON blob per user (&lt;code&gt;progress:{username} → { [challengeId]: { completedAt } }&lt;/code&gt;), not a relational table — a single read gets everything needed to render the dashboard, and a single write marks a challenge complete. No migrations to manage for something this shaped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The OAuth connect flow has an explanatory step before redirecting to GitHub.&lt;/strong&gt; Clicking "connect" used to jump straight to GitHub's authorization screen; now there's a &lt;code&gt;/login&lt;/code&gt; page first that explains what gets created (private repos, what gets read, what gets stored) and is explicit that the &lt;code&gt;repo&lt;/code&gt; scope is broad because classic OAuth Apps don't offer a narrower option — GitHub Apps would, but that's a heavier model I'm not ready to take on yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The public challenge catalog (&lt;code&gt;/retos&lt;/code&gt;) and the connection status in the header are fully static pages&lt;/strong&gt; — they don't read cookies server-side, since most of the site is prerendered for performance/SEO. Instead there's a tiny &lt;code&gt;/api/auth/status&lt;/code&gt; endpoint each page pings client-side to swap "Connect with GitHub" for "Dashboard" once it knows you're logged in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why this matters for the project
&lt;/h3&gt;

&lt;p&gt;Git tutorials that stop at "here's the theory" are everywhere. What's rare is something that tells you, against your actual repository, whether you got it right — and &lt;em&gt;why not&lt;/em&gt;, when you didn't. That's the difference between reading about a merge conflict and actually knowing what to do the next time Git throws one at you for real.&lt;/p&gt;

&lt;h3&gt;
  
  
  How you can help
&lt;/h3&gt;

&lt;p&gt;Still a living project, not a closed course. Issues and PRs are open — especially ideas for new challenges (rebase, cherry-pick, and GitHub Actions checks are next on my list).&lt;/p&gt;

&lt;p&gt;🔗 Repo: &lt;a href="https://github.com/davidbc01/commitea" rel="noopener noreferrer"&gt;https://github.com/davidbc01/commitea&lt;/a&gt;&lt;br&gt;
🔗 Site: &lt;a href="https://commitea-web.vercel.app" rel="noopener noreferrer"&gt;https://commitea-web.vercel.app&lt;/a&gt;&lt;br&gt;
🔗 Challenges: &lt;a href="https://commitea-web.vercel.app/retos" rel="noopener noreferrer"&gt;https://commitea-web.vercel.app/retos&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built Commitea: Git and GitHub explained in Spanish, with an interactive visualizer</title>
      <dc:creator>David</dc:creator>
      <pubDate>Fri, 24 Jul 2026 20:46:34 +0000</pubDate>
      <link>https://dev.to/davidbc01/i-built-commitea-git-and-github-explained-in-spanish-with-an-interactive-visualizer-2hom</link>
      <guid>https://dev.to/davidbc01/i-built-commitea-git-and-github-explained-in-spanish-with-an-interactive-visualizer-2hom</guid>
      <description>&lt;p&gt;When I started programming, Git was hard for me — like anything new is at first. Over time I noticed something: most of the best resources for learning it are in English. And for a lot of people just starting out, that's one more obstacle they shouldn't have to deal with.&lt;/p&gt;

&lt;p&gt;So in my spare time I built the thing I wish I'd had back then: &lt;strong&gt;&lt;a href="https://github.com/davidbc01/commitea" rel="noopener noreferrer"&gt;Commitea&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is it?
&lt;/h3&gt;

&lt;p&gt;Two pieces, designed to complement each other:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An open source repo&lt;/strong&gt; with the full documentation in Spanish — from what a commit actually is, to how to get yourself out of trouble with &lt;code&gt;rebase&lt;/code&gt;, a &lt;code&gt;cherry-pick&lt;/code&gt;, or a &lt;code&gt;push&lt;/code&gt; you regret. Every entry follows the same format: the concept in one sentence, a real example with commands, and "how this breaks" (the typical mistake people make).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A web app with an interactive visualizer&lt;/strong&gt; (&lt;a href="https://commitea-web.vercel.app" rel="noopener noreferrer"&gt;commitea-web.vercel.app&lt;/a&gt;) where you type real Git commands and watch, live, what happens to the branch/commit graph. It doesn't touch any real repo — it's an in-memory simulator, but the engine actually replicates real Git behavior: fast-forward vs. merge commit detection, history rewriting on rebase, blocking a branch switch when you have uncommitted changes (just like real Git does), etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's in it right now
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7 built-in scenarios&lt;/strong&gt; you can run with one click and watch play out step by step: branch + merge, fast-forward, rebase, cherry-pick + reset --hard, fixing a commit made on the wrong branch, several branches merging in sequence, and stashing changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full command support&lt;/strong&gt;: &lt;code&gt;branch&lt;/code&gt;, &lt;code&gt;checkout&lt;/code&gt;, &lt;code&gt;commit&lt;/code&gt;, &lt;code&gt;merge&lt;/code&gt;, &lt;code&gt;rebase&lt;/code&gt;, &lt;code&gt;cherry-pick&lt;/code&gt;, &lt;code&gt;reset --hard&lt;/code&gt;, &lt;code&gt;stash&lt;/code&gt; (with an &lt;code&gt;edit&lt;/code&gt; helper command to simulate uncommitted changes, since the simulator has no real filesystem), &lt;code&gt;status&lt;/code&gt;, and &lt;code&gt;log&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Site-wide search&lt;/strong&gt; (⌘K), powered by Pagefind, indexing only the actual article content — not nav or boilerplate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A feedback widget&lt;/strong&gt; on every article ("was this helpful?") that stores vote counts in Redis, so I know which content needs work without guessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Light/dark mode&lt;/strong&gt;, respecting system preference by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A changelog page&lt;/strong&gt;, because this is a living project and I want the history of what's shipped to be visible, not buried in commit messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A few technical details, if you're curious
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The site is built with &lt;strong&gt;Astro + Tailwind v4&lt;/strong&gt;, no UI framework — everything interactive (the terminal, the visualizer, the search modal) is vanilla JS inside Astro components.&lt;/li&gt;
&lt;li&gt;The content &lt;strong&gt;doesn't live duplicated in the website's repo&lt;/strong&gt;. There's a custom Astro Content Layer loader that pulls the &lt;code&gt;.md&lt;/code&gt; files straight from the public GitHub repo at build time, so the repo stays the single source of truth. A GitHub Action in the public repo pings a Vercel deploy hook on every content push, so the site rebuilds itself automatically.&lt;/li&gt;
&lt;li&gt;The graph renders as SVG with &lt;strong&gt;incremental DOM updates&lt;/strong&gt; — nodes and edges are diffed by a stable id and their attributes updated in place, instead of destroying and recreating the whole SVG on every command. That's what makes the transitions actually animate instead of just snapping into place.&lt;/li&gt;
&lt;li&gt;The feedback endpoint is the only non-static route on the site — a single Vercel serverless function (&lt;code&gt;export const prerender = false&lt;/code&gt;), everything else is prerendered HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How you can help
&lt;/h3&gt;

&lt;p&gt;This is a living project, not a closed course. If you get stuck on something that isn't documented, or spot a mistake, issues and PRs are open. The more real questions it collects, the more useful it becomes for the next person who hits the same wall.&lt;/p&gt;

&lt;p&gt;🔗 Repo: &lt;a href="https://github.com/davidbc01/commitea" rel="noopener noreferrer"&gt;https://github.com/davidbc01/commitea&lt;/a&gt;&lt;br&gt;
🔗 Site: &lt;a href="https://commitea-web.vercel.app" rel="noopener noreferrer"&gt;https://commitea-web.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you know someone learning to code (or someone who's been at it a while but never quite got &lt;code&gt;rebase&lt;/code&gt;), this is for them.&lt;/p&gt;

</description>
      <category>git</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>astro</category>
    </item>
    <item>
      <title>Hello, dev.to! 👋 Full-stack dev building in public</title>
      <dc:creator>David</dc:creator>
      <pubDate>Thu, 23 Jul 2026 16:59:53 +0000</pubDate>
      <link>https://dev.to/davidbc01/hello-devto-full-stack-dev-building-in-public-45ej</link>
      <guid>https://dev.to/davidbc01/hello-devto-full-stack-dev-building-in-public-45ej</guid>
      <description>&lt;p&gt;Hey dev.to! 👋&lt;/p&gt;

&lt;p&gt;I'm David, a full-stack developer specialized in Laravel, Livewire, Alpine.js and Tailwind.&lt;/p&gt;

&lt;p&gt;For the past 3 years I've been job hunting as a Laravel dev while building my own products on the side — right now I'm deep into WorkoutNote, an app connecting personal trainers with their clients, currently in closed alpha with real users. I'm also co-building Snipply with a friend.&lt;/p&gt;

&lt;p&gt;I'll be sharing my build-in-public journey here: the wins, the bugs, the late nights, and everything in between. If you're into Laravel, indie hacking, or just want to talk shop, say hi!&lt;/p&gt;

</description>
      <category>introduction</category>
      <category>laravel</category>
      <category>php</category>
      <category>buildinpublic</category>
    </item>
  </channel>
</rss>
