Skip to content
Philosophy

Architecture-first agentic coding.

Deep technical expertise across the whole stack, and an AI-native way of building. I start with the system map, so the model reasons instead of guessing, and what I build is secure, scalable, and fast.

The problem

AI agents guess. Without architectural context, that guessing compounds into structural debt.

Point an AI agent at a codebase with no context and it pattern-matches the nearest file: finds something similar, copies the pattern, bolts new code wherever it lands.

The result is silent coupling. Business logic leaks into UI layers, shared utilities become dumping grounds, and modules that shouldn't know about each other suddenly do. The model had no map, so it guessed.

The approach

Three principles that change the output.

Structure before code

Before the AI writes a line, it gets the architecture: dependency maps, module boundaries, data flow, and a CLAUDE.md that explains how the system fits together.

So instead of asking "what file looks similar?", the model asks "where does this change belong?". A different question, and a different answer.

Boundaries prevent coupling

When an agent can see component boundaries, it respects them. It stops importing across the system, creating circular dependencies, and leaking state across layers.

A boundary in the architecture doc is worth a hundred lint rules. The model treats it as a constraint, not an afterthought.

The codebase IS the prompt

Your file structure, naming, and module organization are a prompt. Every time an agent reads the code to make a change, how you organized it does the prompting.

Most teams tune their prompts and ignore the biggest one: the codebase itself. Clean structure is not just good engineering, it is prompt engineering.

In practice

What this looks like.

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. No new 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 is the foundation, not an add-on. Every project starts with architecture docs written for two audiences: the humans who maintain the code, and the AI agents that help them.

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

Ready to build software that AI can actually work with?

Get in touch to discuss your project. I'll show you how architecture-first development changes the output across the lifecycle.