I’ve been studying event modeling for almost a year and only now it has started to click. Not just from reading articles or watching talks but from actually modeling simple hobby projects. I thought I’d spend yesterday starting another one.

The Project

The idea is straightforward: register an occasion reminder (birthday, anniversary, whatever), and one month before, the service sends you an email or text asking if you’d like to purchase a gift from a local supplier.

Simple enough. But as soon as I opened Miro and started modeling, I fell into a familiar trap.

The Trap: Modeling Around “Customer”

My first instinct was to save everything under a Customer aggregate. It felt natural—someone comes to the site, they become a customer, they create reminders.

So I modeled it that way. Registration flows, customer entities, the whole thing.

But when I stepped back and looked at the full picture, something felt off. These people aren’t customers yet. They’re not customers until they actually buy something. It might be months away, or never.

I tried modeling a PotentialCustomer instead. That got complicated fast. How do I handle someone who comes back with the same email? When do they graduate to a real customer? The entity started accumulating responsibilities it shouldn’t have.

Then I looked at the UI I’d sketched.

The Insight: Let the UI Guide You

What does the user actually do on the first screen? They create a reminder. That’s it. They’re not “signing up” or “becoming a customer”, they’re just telling the system about an occasion they want to remember.

I don’t like sites that force you to create an account before you can do anything useful. So I wanted users to create a reminder immediately, with verification happening afterward via email or SMS.

Once I modeled Reminder as the main aggregate, everything simplified:

  • No need to reconcile duplicate customers with the same email
  • No complex state machine for “potential” vs “real” customers
  • The verification flow attaches naturally to the reminder itself
  • Customer identity only matters later, if and when they decide to purchase

The domain boundaries became obvious. This part of the system is lead generation, not customer management. The model should reflect that.

It took me most of a morning to get to this point. But I was genuinely happy with the output and my brain was exhausted. Time to switch gears and actually build it.


Part 2: Building It with AI in a Day

With a clear event model in hand, I wanted to see how fast I could get to a working system. We’d been exploring .NET Aspire, Marten, and Wolverine at work, so this felt like a good opportunity to test them together.

Frontend: Aligning Angular with Vertical Slices

At work we have a .NET backend with Angular on the frontend, and the code structures don’t really match. The backend is organised by feature slice; the frontend… less so.

I took a screenshot of my event model and asked Claude how to structure an Angular frontend to align with a vertically sliced backend. After some back and forth about component organisation, we landed on something sensible.

The key move: I asked Claude to generate an architecture.md document summarizing our discussion. That document included slice specifications I could hand off to an AI coding agent.

The agent built out the entire frontend slice—components, services, all the way to the API calls. It wasn’t pretty visually, but the code structure made sense. When I needed to make adjustments, I knew exactly where to look.

Backend: The RFC Prompt

For the backend, I’d read that asking for an “RFC” instead of a “plan” produces better results from AI. So I tested it: I pasted my event model screenshot and asked for an RFC on implementing those slices with Marten and Wolverine.

I placed the resulting RFC at the root of my API project alongside a claude.md with implementation instructions, then told Claude Code to “build this.”

When I came back from getting coffee, I had an API service with 20 compiler errors.

The Reality of AI-Generated Code

The errors were all fixable: renamed packages, deprecated methods, namespace conflicts. Nothing mysterious if you understand the error messages. This is the part people don’t always mention, AI gets you 80% of the way fast, but you still need to understand what you’re looking at.

I generated a .http file to test the endpoints. They all fired successfully, though some returned empty data.

Wiring up the frontend to the API, I entered test data and… nothing happened on screen. But a quick check of the database showed the data had persisted correctly. The frontend just had no feedback mechanism.

The Debugging You Still Have to Do

After wrestling with CSS for longer than I’d like to admit (the card was too narrow, and I am not a frontend person), I went back to familiar territory: figuring out why my pending verifications returned empty lists.

The issue? Some slices were appending to the event store correctly; others were just returning the event without persisting it. Classic inconsistency that tests would have caught.

I probably should have written tests first. That’s next up, exploring Testcontainers and testing patterns for event-sourced systems.


What I Learned

Event modeling works best when you let the UI lead. I spent too long thinking about domain concepts in the abstract. Looking at what the user actually does on screen cut through the complexity.

AI shines at bootstrapping. The boring parts (project structure, boilerplate, wiring, etc.) happen fast. That’s genuinely fun. It lets you stay in the creative and architectural headspace longer.

You still need to understand the code. Every AI-generated file needed review. Some needed fixes. The 20 compiler errors weren’t a failure of the tool; they were a reminder that I’m the one responsible for what ships.

Document your decisions for the agents. The architecture.md and RFC documents weren’t just for me, they gave the AI enough context to generate coherent code. Garbage in, garbage out applies here too.

One day. From Miro board to working full-stack app. I learned more doing this than I would have in a week without the help of AI.

Leave a comment