Philosophy

Architecture-First Agentic Coding

Most developers throw AI at their codebase and hope for the best. I start with the system map. The difference is night and day.

The Problem

AI agents guess. And guessing creates spaghetti.

Here is what happens when you point an AI agent at a codebase without context: it pattern-matches the nearest file. It finds something that looks similar, copies the pattern, and bolts on new code wherever it lands.

The result? Silent coupling everywhere. Components that shouldn't know about each other suddenly depend on each other. Business logic leaks into UI layers. Shared utilities become dumping grounds. The AI had no idea where things should go, so it guessed.

This is not the AI's fault. It is doing exactly what you would expect from a model with no architectural context. You gave it code. It found the nearest match. It wrote more code. Without a map, that is all it can do.

The Approach

Three principles that change everything

Structure before code

Before the AI writes a single line, it gets the architecture. Dependency maps. Module boundaries. Data flow diagrams. A CLAUDE.md file that explains how the system is organized and why.

This flips the entire dynamic. Instead of the model asking "what file looks similar?", it asks "where does this change belong in the system?". That is a fundamentally different question, and it produces fundamentally different code.

The model reasons about placement. It understands layers. It knows that a database query does not belong in a React component, not because of a lint rule, but because the architecture doc says so.

Boundaries prevent coupling

When an AI agent can see component boundaries visually, something interesting happens: it respects them. It will not silently import from a module on the other side of the system. It will not create circular dependencies. It will not leak state across layers.

Boundaries are not just documentation. They are guardrails for AI behavior. A well-drawn boundary in your architecture doc is worth a hundred lint rules. The model internalizes it as a constraint, not an afterthought.

This is why I obsess over making boundaries explicit. Not for the humans on the team (though they benefit too) but because the AI agents that touch this code every day need to see the walls.

The codebase IS the prompt

Your file structure, your naming conventions, your module organization. All of it is a prompt. Every time an AI agent reads your code to make a change, it is being "prompted" by how you have organized things.

Messy structure produces messy output. If your utils folder has 47 files with vague names, the AI will add file 48. If your components are organized by feature with clear naming, the AI will follow the pattern and put new code exactly where it should go.

This is the insight most people miss. They optimize their prompts in ChatGPT but ignore the biggest prompt of all: the codebase itself. Clean structure is not just good engineering. It is prompt engineering.

In Practice

What this looks like in practice

Without architecture context
src/
components/
Dashboard.tsx (500 lines, fetches data, manages state, renders UI)
utils.ts (87 unrelated helpers)
api.ts (mixed endpoints, no grouping)
pages/
index.tsx (imports from everywhere)
AI adds new feature to Dashboard.tsx because it is the closest match. Coupling increases. File grows. Nobody notices until it breaks.
With architecture context
CLAUDE.md (architecture, boundaries, conventions)
src/
features/
dashboard/
components/ hooks/ api/ types/
analytics/
components/ hooks/ api/ types/
shared/
ui/ lib/ types/
AI reads CLAUDE.md, sees the feature boundary, creates analytics/components/Chart.tsx. Clean separation. Zero coupling.
AI Agent Session
# Agent reads architecture context first
$ cat CLAUDE.md | head -20
Module: analytics (isolated feature)
Dependencies: shared/ui, shared/lib
Never import from: features/dashboard, features/auth
$ claude "add a conversion funnel chart"
Reading CLAUDE.md...
Identified target: features/analytics/components/
Creating: FunnelChart.tsx
Using shared/ui/Card for layout
Done. 1 file created, 0 cross-boundary imports.
How I Work

This is how I build

When I build for clients, this philosophy is not an add-on. It is the foundation. Every project starts with architecture documentation that serves two audiences: the humans who will maintain the code, and the AI agents that will help them do it.

I design codebases so that AI makes them better over time, not worse. Clear module boundaries. Explicit dependency rules. Convention files that any model can read and follow. The result is a system that gets easier to work with as it grows, not harder.

This is the difference between using AI as a fancy autocomplete and using it as a real development partner. The architecture is the interface between human intent and machine execution. Get it right, and everything downstream improves.

Ready to build software that AI can actually work with?

Let's talk about your project. I will show you how architecture-first development changes the game.

Get in touch