<?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: Alberto Arena</title>
    <description>The latest articles on DEV Community by Alberto Arena (@alberto_arena_25a48484ed5).</description>
    <link>https://dev.to/alberto_arena_25a48484ed5</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%2F1584618%2F8916c43c-3e5f-4896-b701-9e82ab63893f.jpeg</url>
      <title>DEV Community: Alberto Arena</title>
      <link>https://dev.to/alberto_arena_25a48484ed5</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alberto_arena_25a48484ed5"/>
    <language>en</language>
    <item>
      <title>AI Code Hallucinations: When Your AI Writes Confident Nonsense</title>
      <dc:creator>Alberto Arena</dc:creator>
      <pubDate>Sat, 18 Jul 2026 14:51:18 +0000</pubDate>
      <link>https://dev.to/alberto_arena_25a48484ed5/ai-code-hallucinations-when-your-ai-writes-confident-nonsense-l3g</link>
      <guid>https://dev.to/alberto_arena_25a48484ed5/ai-code-hallucinations-when-your-ai-writes-confident-nonsense-l3g</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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr75t27l0p1ihcmxoundi.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr75t27l0p1ihcmxoundi.png" alt="AI Hallucination in Coding Agents" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI coding agents are becoming part of our daily workflow. Tools like GitHub Copilot, Cursor, and Claude Code can write functions, refactor modules, and scaffold entire features in seconds. They're genuinely useful.&lt;/p&gt;

&lt;p&gt;But they have a problem: &lt;strong&gt;they hallucinate&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AI hallucination?
&lt;/h2&gt;

&lt;p&gt;In the context of coding agents, hallucination means the AI generates code that looks correct, reads well, follows reasonable patterns, but is factually wrong. It invents APIs that don't exist, references packages that were never published, or creates logic that subtly breaks under edge cases.&lt;/p&gt;

&lt;p&gt;The tricky part? Hallucinated code often &lt;em&gt;compiles&lt;/em&gt;. It passes a quick glance. It has the right shape. That's what makes it dangerous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it happens
&lt;/h2&gt;

&lt;p&gt;Large language models don't "know" things the way we do. They predict the most likely next token based on patterns in their training data. When they encounter a gap in their knowledge, they don't stop and say "I don't know." They fill the gap with something plausible.&lt;/p&gt;

&lt;p&gt;This means an AI coding agent will confidently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call a method that doesn't exist in the library version you're using&lt;/li&gt;
&lt;li&gt;Import a package with a name that sounds right but isn't real&lt;/li&gt;
&lt;li&gt;Generate test assertions that pass by coincidence, not by correctness&lt;/li&gt;
&lt;li&gt;Produce code that works for the happy path but silently fails on edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5 practical tips to spot hallucination
&lt;/h2&gt;

&lt;p&gt;Here's what I've learned from working with AI agents on real projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Verify every import and dependency
&lt;/h3&gt;

&lt;p&gt;If the AI suggests a package or module you don't recognise, check it exists before installing it. A quick search on npm, Packagist, or PyPI takes seconds. I've seen AI agents invent package names that are plausible but fictional.&lt;/p&gt;

&lt;p&gt;This also applies to methods. If the agent calls &lt;code&gt;response.getStatusText()&lt;/code&gt; and you're not sure that method exists, check the docs. Don't trust the autocomplete.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Read the code, don't just run it
&lt;/h3&gt;

&lt;p&gt;It's tempting to accept generated code if it compiles and the tests pass. Resist that urge. Read through the logic line by line. Ask yourself: &lt;em&gt;does this actually do what I intended?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;AI-generated code can be syntactically perfect and logically wrong. A function might return the right result for your test input but fail for negative numbers, empty strings, or concurrent access.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Test the edges, not just the happy path
&lt;/h3&gt;

&lt;p&gt;AI agents tend to generate code that works for the obvious case. Write tests for boundary conditions, null inputs, large datasets, and error scenarios. This is where hallucinated logic breaks down.&lt;/p&gt;

&lt;p&gt;If the AI also wrote your tests, be extra sceptical. It may have written tests that confirm its own assumptions rather than truly validating behaviour.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Cross-reference with official documentation
&lt;/h3&gt;

&lt;p&gt;When an AI agent generates code using a framework or library, open the official docs and verify the API calls. Check parameter order, return types, and version compatibility.&lt;/p&gt;

&lt;p&gt;I've caught hallucinations where the AI mixed up APIs from different library versions, or combined method signatures from two different frameworks into something that looked right but wasn't.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Watch for confident but vague explanations
&lt;/h3&gt;

&lt;p&gt;When you ask an AI agent &lt;em&gt;why&lt;/em&gt; it wrote something a certain way, pay attention to the explanation. Hallucinating models tend to give answers that sound authoritative but lack specifics. If the explanation is vague or circular ("this is the standard approach" without citing where), dig deeper.&lt;/p&gt;

&lt;p&gt;A reliable answer references specific documentation, versions, or known patterns. A hallucinated answer just sounds good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trust but verify
&lt;/h2&gt;

&lt;p&gt;AI coding agents are a genuine productivity multiplier. I use them daily and I've built projects entirely with their help. But they work best when you treat their output as a &lt;strong&gt;first draft&lt;/strong&gt;, not a final answer.&lt;/p&gt;

&lt;p&gt;The developer's job hasn't changed: understand the problem, validate the solution, and take responsibility for what ships. The AI writes the code faster. You make sure it's correct.&lt;/p&gt;

&lt;p&gt;Stay sceptical. Stay curious. And always read the diff.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codequality</category>
      <category>developertools</category>
    </item>
    <item>
      <title>Heads up: GitHub user @doraemonxxx is squatting on 359+ repositories including Laravel packages. If you see their fork in search results, use the original author's version instead.</title>
      <dc:creator>Alberto Arena</dc:creator>
      <pubDate>Tue, 14 Jul 2026 04:04:09 +0000</pubDate>
      <link>https://dev.to/alberto_arena_25a48484ed5/heads-up-github-user-doraemonxxx-is-squatting-on-359-repositories-including-laravel-packages-if-3bf3</link>
      <guid>https://dev.to/alberto_arena_25a48484ed5/heads-up-github-user-doraemonxxx-is-squatting-on-359-repositories-including-laravel-packages-if-3bf3</guid>
      <description></description>
      <category>github</category>
      <category>laravel</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>Curious to know how big everyone's CLAUDE.md has gotten. Mine hit 300 lines before I figured out why Claude kept getting worse, not better.</title>
      <dc:creator>Alberto Arena</dc:creator>
      <pubDate>Wed, 08 Jul 2026 12:19:05 +0000</pubDate>
      <link>https://dev.to/alberto_arena_25a48484ed5/curious-to-know-how-big-everyones-claudemd-has-gotten-mine-hit-300-lines-before-i-figured-out-5him</link>
      <guid>https://dev.to/alberto_arena_25a48484ed5/curious-to-know-how-big-everyones-claudemd-has-gotten-mine-hit-300-lines-before-i-figured-out-5him</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/alberto_arena_25a48484ed5/claudemd-is-ram-not-disk-2lpa" class="crayons-story__hidden-navigation-link"&gt;CLAUDE.md Is RAM, Not Disk: A Memory Model for Claude Code Projects&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="/alberto_arena_25a48484ed5" 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%2F1584618%2F8916c43c-3e5f-4896-b701-9e82ab63893f.jpeg" alt="alberto_arena_25a48484ed5 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/alberto_arena_25a48484ed5" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Alberto Arena
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Alberto Arena
                
              
              &lt;div id="story-author-preview-content-4017914" 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="/alberto_arena_25a48484ed5" 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%2F1584618%2F8916c43c-3e5f-4896-b701-9e82ab63893f.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Alberto Arena&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/alberto_arena_25a48484ed5/claudemd-is-ram-not-disk-2lpa" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 29&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/alberto_arena_25a48484ed5/claudemd-is-ram-not-disk-2lpa" id="article-link-4017914"&gt;
          CLAUDE.md Is RAM, Not Disk: A Memory Model for Claude Code Projects
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/claude"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;claude&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/laravel"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;laravel&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/php"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;php&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/alberto_arena_25a48484ed5/claudemd-is-ram-not-disk-2lpa#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&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;
            4 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>CLAUDE.md Is RAM, Not Disk: A Memory Model for Claude Code Projects</title>
      <dc:creator>Alberto Arena</dc:creator>
      <pubDate>Mon, 29 Jun 2026 07:00:47 +0000</pubDate>
      <link>https://dev.to/alberto_arena_25a48484ed5/claudemd-is-ram-not-disk-2lpa</link>
      <guid>https://dev.to/alberto_arena_25a48484ed5/claudemd-is-ram-not-disk-2lpa</guid>
      <description>&lt;p&gt;Most Claude Code projects I see have one giant &lt;code&gt;CLAUDE.md&lt;/code&gt; that keeps growing until it is three hundred lines long, and somewhere around line two hundred the assistant starts getting worse instead of better. That is not bad luck. That file is loaded into context at the start of the session and stays resident there, so every line you add is a line Claude carries in front of it on every turn that follows — context it reads past before it gets to your actual task. The fix is not a longer file. It is treating &lt;code&gt;CLAUDE.md&lt;/code&gt; like RAM and the rest of your docs like disk.&lt;/p&gt;

&lt;p&gt;Here is the whole idea in one sentence: &lt;code&gt;CLAUDE.md&lt;/code&gt; is working memory, loaded constantly and paid for constantly, so it stays small; the &lt;code&gt;docs/&lt;/code&gt; folder is long-term memory, loaded only when something points to it. Once that distinction clicks, every other decision about where a piece of information should live answers itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the big file hurts
&lt;/h2&gt;

&lt;p&gt;Claude Code reads &lt;code&gt;CLAUDE.md&lt;/code&gt; automatically at the start of every session and keeps it in context the whole time. That is exactly what you want for the handful of things Claude needs on every task: your stack, your commands, the rules that must always hold. It is exactly what you do not want for the things Claude needs once a week. A long domain description or a full architecture writeup sitting in &lt;code&gt;CLAUDE.md&lt;/code&gt; does not make Claude smarter. It crowds the context with detail that is irrelevant to the task in front of it, and it costs you tokens on every turn whether you use it or not.&lt;/p&gt;

&lt;p&gt;The test I use is simple. Does Claude need this every time, or only sometimes? Every time goes in &lt;code&gt;CLAUDE.md&lt;/code&gt;. Sometimes goes in &lt;code&gt;docs/&lt;/code&gt;, with a one-line pointer from &lt;code&gt;CLAUDE.md&lt;/code&gt; so Claude knows where to look when it actually needs it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What belongs in RAM
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; should be short enough that you can read it in under a minute. Mine for a Laravel project holds five things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A two or three sentence overview of what the project is.&lt;/li&gt;
&lt;li&gt;The stack with versions pinned. "Laravel" is not enough. "Laravel 11, PHP 8.3, Pest 3" is.&lt;/li&gt;
&lt;li&gt;The exact commands: test, lint, static analysis, dev server. Claude should never guess these.&lt;/li&gt;
&lt;li&gt;The conventions that must hold on every change. For me that is TDD with Pest first, KISS, event sourcing through Spatie where it earns its place, domain logic kept free of framework code, and &lt;code&gt;envaudit&lt;/code&gt; validating &lt;code&gt;.env&lt;/code&gt; in CI.&lt;/li&gt;
&lt;li&gt;Pointers out. One line each: architecture is in &lt;code&gt;docs/DESIGN.md&lt;/code&gt;, current work is in &lt;code&gt;docs/PLAN.md&lt;/code&gt;, decisions are in &lt;code&gt;docs/DECISIONS.md&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last group is the trick. &lt;code&gt;CLAUDE.md&lt;/code&gt; does not contain the architecture. It contains the address of the architecture. Claude loads the detail on demand when a task needs it, and the rest of the time that detail is not burning context.&lt;/p&gt;

&lt;h2&gt;
  
  
  What belongs on disk
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;docs/&lt;/code&gt; folder is where the long material lives, and because it loads on demand it can be as long as it needs to be. Three files cover most projects:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DESIGN.md&lt;/code&gt; is the architecture and domain model. Bounded contexts, aggregates, the events each one records, the invariants they protect. This is your thinking written down once so Claude does not reinvent it every session, and so that when it asks "where does this logic belong" the answer is derivable from the file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PLAN.md&lt;/code&gt; is the phased, plan-first breakdown of the work. Small phases, each finishable and verifiable, checked off as they land, with a short done log at the bottom so progress survives between sessions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DECISIONS.md&lt;/code&gt; is a lightweight decision log. One short entry per significant choice: context, decision, trade-off. This is the file that stops you and Claude relitigating the same question three sessions later.&lt;/p&gt;

&lt;p&gt;Add more only when a real need shows up. A &lt;code&gt;TESTING.md&lt;/code&gt; when your test strategy is genuinely non-obvious. A separate &lt;code&gt;DOMAIN.md&lt;/code&gt; when the glossary outgrows &lt;code&gt;DESIGN.md&lt;/code&gt;. Not before. Empty scaffolding is just more for Claude to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick most setups miss: nested files
&lt;/h2&gt;

&lt;p&gt;Claude Code does not only read the root &lt;code&gt;CLAUDE.md&lt;/code&gt;. It also reads a &lt;code&gt;CLAUDE.md&lt;/code&gt; in the directory it happens to be working in, layered on top of the root one. That means rules which only matter inside one folder can live in that folder instead of bloating the root file.&lt;/p&gt;

&lt;p&gt;In a Laravel project with a real domain layer, I put a &lt;code&gt;CLAUDE.md&lt;/code&gt; inside &lt;code&gt;app/Domains&lt;/code&gt; that says: no framework imports here, aggregates extend Spatie's &lt;code&gt;AggregateRoot&lt;/code&gt; and only record events, events are immutable and past-tense, and every change starts with a Pest test. None of that needs to be in the root file, because it is irrelevant when Claude is editing a controller or a Blade view. It loads exactly when Claude steps into the domain layer, and not before.&lt;/p&gt;

&lt;h2&gt;
  
  
  The starter
&lt;/h2&gt;

&lt;p&gt;I put all of this into a small template repo you can copy straight into a project: &lt;a href="https://github.com/albertoarena/claude-code-laravel-starter" rel="noopener noreferrer"&gt;claude-code-laravel-starter&lt;/a&gt;. It is the structure above, with every file as a fillable template rather than lorem ipsum, the Laravel and event sourcing conventions already baked in, and a nested domain-layer &lt;code&gt;CLAUDE.md&lt;/code&gt; so the pattern is concrete.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;claude-code-laravel-starter/
├── CLAUDE.md              # the lean anchor, auto-loaded every session
├── README.md
├── docs/
│   ├── DESIGN.md         # domain model, aggregates, events
│   ├── PLAN.md           # phased, plan-first implementation
│   └── DECISIONS.md      # lightweight ADR log
└── app/
    └── Domains/
        └── CLAUDE.md     # rules for the domain layer only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy it onto a fresh Laravel app, fill in your real stack and commands, replace the example domain with yours, and keep the root file tight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three rules to take away
&lt;/h2&gt;

&lt;p&gt;If Claude needs it every time, it goes in &lt;code&gt;CLAUDE.md&lt;/code&gt;. If only sometimes, it goes in &lt;code&gt;docs/&lt;/code&gt;. Start with three files and add more only when something real demands it. And when a folder gets its own rules, give it its own &lt;code&gt;CLAUDE.md&lt;/code&gt; instead of stretching the root one.&lt;/p&gt;

&lt;p&gt;Start small, keep working memory tight, and let the disk hold the rest.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>What if every Filament write went through an aggregate?</title>
      <dc:creator>Alberto Arena</dc:creator>
      <pubDate>Tue, 23 Jun 2026 13:15:35 +0000</pubDate>
      <link>https://dev.to/alberto_arena_25a48484ed5/what-if-every-filament-write-went-through-an-aggregate-49c6</link>
      <guid>https://dev.to/alberto_arena_25a48484ed5/what-if-every-filament-write-went-through-an-aggregate-49c6</guid>
      <description>&lt;p&gt;Filament is a great admin panel. Event sourcing is a great architectural pattern. Getting the two to work together, though, has always meant compromises: either you bypass your aggregates and write directly to the database, or you ditch Filament's create/edit flows and build everything from scratch. I've been using both in the same projects for a while, and that friction kept bothering me. So I built a plugin to remove it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/albertoarena/filament-event-sourcing" rel="noopener noreferrer"&gt;filament-event-sourcing&lt;/a&gt; is a Filament plugin that intercepts the standard create, edit, and delete actions and routes them through your domain aggregates. Your forms stay the same. Your validations and notifications stay the same. The only change is what happens on write: instead of an Eloquent save, the data flows through your aggregate and gets stored as a domain event. The read model is still updated by your projectors, exactly as you'd expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get out of the box
&lt;/h2&gt;

&lt;p&gt;The plugin ships with a few things I found myself needing every time I mixed Filament with event sourcing.&lt;/p&gt;

&lt;p&gt;The first is an event history browser. Every record gets a dedicated view of its event log: event class, timestamp, version, and the full JSON payload on expand. It's available either as a relation manager tab or as a slide-over action on the table. No extra setup, add the trait to your resource and it appears.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjrr66xvxb2tpi4xzyvt0.webp" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjrr66xvxb2tpi4xzyvt0.webp" alt="Per-record event history with expandable JSON payloads" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second is a system-wide stored events browser. This gives you a searchable, filterable view of every event in your application, across all aggregates. You can filter by event class, aggregate UUID, or date range. It's read-only by design, which keeps the event log immutable.&lt;/p&gt;

&lt;p&gt;The third is a projector replay page. You can trigger a replay for any registered projector directly from the admin panel, one at a time, with a live count of how many events were processed. Access is controlled by a three-layer authorization system: a plugin-level option, a config flag, and a Gate ability for fine-grained control.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to install it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require albertoarena/filament-event-sourcing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need Laravel 11 or 12, Filament 4.0+, and Spatie's &lt;code&gt;laravel-event-sourcing&lt;/code&gt; 7.0+. The plugin registers itself automatically via Filament's plugin system.&lt;/p&gt;

&lt;p&gt;From there, you add two traits to your resource (&lt;code&gt;CreatesEventSourcedRecord&lt;/code&gt; and &lt;code&gt;EditsEventSourcedRecord&lt;/code&gt;), wire up the delete action, and the rest is your aggregate logic. The plugin doesn't try to generate your events or commands, that's your domain, and it should stay that way.&lt;/p&gt;

&lt;p&gt;A full working example with a &lt;code&gt;Post&lt;/code&gt; entity is available in the &lt;a href="https://github.com/albertoarena/filament-event-sourcing-demo/" rel="noopener noreferrer"&gt;demo repository&lt;/a&gt;, which walks through the complete setup from aggregate to Filament resource.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go from here
&lt;/h2&gt;

&lt;p&gt;The package is at version 0.1.0 and working. There's more I want to add, but the core is solid enough to use in real projects today. The &lt;a href="https://albertoarena.github.io/filament-event-sourcing/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; covers installation, each feature in detail, configuration, and authorization. If you're already using Spatie's event sourcing package with Filament, this plugin is probably the missing piece.&lt;/p&gt;

&lt;p&gt;Feedback and contributions are welcome.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>eventsourcing</category>
      <category>filament</category>
    </item>
    <item>
      <title>Your README Deserves Real Numbers</title>
      <dc:creator>Alberto Arena</dc:creator>
      <pubDate>Fri, 05 Jun 2026 07:21:44 +0000</pubDate>
      <link>https://dev.to/alberto_arena_25a48484ed5/your-readme-deserves-real-numbers-lhb</link>
      <guid>https://dev.to/alberto_arena_25a48484ed5/your-readme-deserves-real-numbers-lhb</guid>
      <description>&lt;p&gt;If you maintain an open-source repo, you have probably wondered at some point how many people actually visit it. GitHub has the answer buried in the Insights tab, but nobody looks there. It resets after 14 days, there is no history, and your README, the thing everyone sees, tells them nothing.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/marketplace/actions/traffic-badge" rel="noopener noreferrer"&gt;traffic-badge&lt;/a&gt; to fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;It is a GitHub Action that runs on a schedule, hits the official GitHub Traffic API, and commits a live SVG badge to a dedicated branch in your repo. You embed that badge in your README once and it updates automatically from then on.&lt;/p&gt;

&lt;p&gt;The badge shows whatever you care about: total views, unique visitors, clones, unique cloners. One workflow file per metric, or stack them all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it is different from the alternatives
&lt;/h2&gt;

&lt;p&gt;A lot of traffic badge solutions rely on a third-party counting server. Which means you are trusting someone else's infrastructure, someone else's uptime, and someone else's definition of "a view." When that server goes down or changes its counting logic, your badge quietly becomes wrong.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;traffic-badge&lt;/code&gt; does not phone home. The numbers come straight from GitHub's own API, the same data you would see in your Insights tab. The raw JSON is committed to your repo under a &lt;code&gt;traffic-data&lt;/code&gt; branch, so you can inspect every data point, diff it, delete it, whatever you want. Full transparency.&lt;/p&gt;

&lt;p&gt;It also handles the awkward overlap problem. GitHub's Traffic API returns a rolling 14-day window, so if you run the action daily you would normally double-count the days that appear in both runs. &lt;code&gt;traffic-badge&lt;/code&gt; deduplicates by date automatically, so your cumulative totals stay accurate without any extra work on your end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting it up
&lt;/h2&gt;

&lt;p&gt;First, a heads-up that saves you the most common mistake: the default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; does not work here. The Traffic API requires push or admin access, which that token does not have, so it fails with &lt;code&gt;403 Resource not accessible by integration&lt;/code&gt;. You need a Personal Access Token instead: a classic PAT with the &lt;code&gt;repo&lt;/code&gt; scope, or a fine-grained PAT with &lt;code&gt;Administration: read&lt;/code&gt; on the repo. Add it as a repository secret called &lt;code&gt;TRAFFIC_TOKEN&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then add a workflow file:&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;Traffic Badge&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;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="s2"&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;0&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;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&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;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;badge&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;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;albertoarena/github-traffic-badge@v1&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;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TRAFFIC_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;metric&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;views&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;blue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it once manually, then grab the badge URL it creates and drop it in your README:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Views&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://raw.githubusercontent.com/OWNER/REPO/traffic-data/badge.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it. No server to maintain, no API key for a third-party service, no monthly bill. It runs on free GitHub-hosted runners.&lt;/p&gt;

&lt;h2&gt;
  
  
  The options worth knowing
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;metric&lt;/code&gt; field accepts &lt;code&gt;views&lt;/code&gt;, &lt;code&gt;clones&lt;/code&gt;, &lt;code&gt;views-unique&lt;/code&gt;, and &lt;code&gt;clones-unique&lt;/code&gt;. You can run multiple workflows with different metrics if you want to show both.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;color&lt;/code&gt; takes any named colour or a hex value. &lt;code&gt;style&lt;/code&gt; supports the standard shields.io styles: &lt;code&gt;flat&lt;/code&gt;, &lt;code&gt;flat-square&lt;/code&gt;, &lt;code&gt;plastic&lt;/code&gt;, &lt;code&gt;for-the-badge&lt;/code&gt;. And if your numbers get large enough that the badge looks cluttered, there is an &lt;code&gt;abbreviated&lt;/code&gt; flag that turns &lt;code&gt;12345&lt;/code&gt; into &lt;code&gt;12.3K&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on how it is built
&lt;/h2&gt;

&lt;p&gt;If you like to read the code before trusting an Action with a PAT, it is worth a look. Zero runtime dependencies, Node 20+ with built-in &lt;code&gt;fetch&lt;/code&gt; and the built-in test runner. The counting and rendering logic is written as pure functions with the network, filesystem, and clock injected, so it is fully tested without touching disk or hitting the API. The zero-dependency constraint is enforced in CI.&lt;/p&gt;




&lt;p&gt;It is open source, MIT licensed, and available on the &lt;a href="https://github.com/marketplace/actions/traffic-badge" rel="noopener noreferrer"&gt;GitHub Marketplace&lt;/a&gt;. The source is at &lt;a href="https://github.com/albertoarena/github-traffic-badge" rel="noopener noreferrer"&gt;albertoarena/github-traffic-badge&lt;/a&gt;. If you run into anything odd or have a feature request, issues are open.&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubactions</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
