Structure a UI Codebase for AI Coding Agents
A well-structured UI codebase helps coding agents find the right components, understand project conventions, and make changes without breaking unrelated screens. Before you begin, have a working application, a reliable way to run its checks, and access to the repository; this guide focuses on improving the codebase rather than choosing a particular framework.
What You’ll Need
- A UI repository that you can edit, plus its package manager and development instructions.
- A test, lint, type-check, or build command you can run before and after changes. Use the checks your project already supports.
- A short list of common tasks agents will handle, such as adding a form, adjusting a page, or fixing a component.
- Version control and a clean working branch, so changes are reviewable and easy to revert.
Step-by-Step
- Make the project entry points obvious. Keep the top-level directory focused, and give important folders descriptive names such as
src,tests, anddocs. Add a concise README that explains how to install dependencies, start the app, run checks, and locate the main UI entry point. Include any required environment setup without publishing secrets. An agent should not have to infer which of several similarly named apps is the one to change. - Choose a predictable folder structure. Organize files around a small number of clear responsibilities. For example, group reusable interface components separately from routes or pages, and keep shared utilities, styles, and tests discoverable. If the application is large, feature-based folders can keep a feature’s UI, tests, and local helpers together. Avoid imposing a large architecture on a small project: consistency matters more than a particular pattern.
- Separate shared components from feature-specific ones. Put a component in a shared location only when multiple parts of the product use it or it has a clearly general purpose. Keep one-off page components close to the page or feature that owns them. Use names that describe what a component does, such as
AccountMenuorSearchField, rather than vague labels likeWidget. This makes it easier to find the correct place for a requested change. - Define component boundaries and contracts. Keep each component responsible for a coherent piece of UI. Make its inputs explicit with the project’s type system or documented prop conventions, and use clear names for callbacks and state. Avoid components that accept many unrelated flags or silently depend on distant global state. Document unusual behavior, accessibility requirements, and expected loading or error states near the code that implements them.
- Make styling conventions consistent. Decide how the project handles styles—such as CSS modules, scoped styles, or a shared design system—and explain the convention. Keep global resets, theme tokens, and shared layout rules in predictable locations. Use existing spacing, color, and typography tokens rather than introducing near-duplicates. Avoid mixing several styling approaches for the same kind of component unless there is a documented reason.
- Put tests near the behavior they protect. Use a consistent naming and location convention for component and feature tests. Cover important interactions and visible states, not just whether a component renders. Add accessible selectors or stable test identifiers only when appropriate; prefer queries that reflect what a user can see or do. Make the test command and any required setup easy to find, and keep fixtures small and understandable.
- Document rules an agent cannot safely infer. Add a short contributor or agent guide describing file placement, naming, styling, test expectations, and commands. State boundaries such as “reuse the existing button component” or “do not edit generated files,” when those rules apply. Keep instructions concrete and scoped; link to longer documentation instead of copying it into multiple files.
- Make checks fast and failures legible. Provide reliable commands for formatting, linting, type checking, tests, and production builds where available. Ensure failures point to useful file names and line numbers. Do not require unrelated services for routine checks if lightweight alternatives are possible. Tell contributors which checks are required for a UI change and which are optional.
- Keep examples and generated files distinct. Mark scaffolds, generated assets, and snapshots so they are not mistaken for source files. Keep sample components representative and current. If generation is part of normal development, document the command and identify the source of truth; avoid asking an agent to edit output that will be overwritten.
- Validate the structure with a real task. Choose a small change, such as adding a field to an existing form. Ask an agent to locate the page, update the UI, add or adjust a test, and report the checks it ran. Review whether it found the right files and followed project conventions. Fix confusing names or missing instructions, then repeat with a different type of task.
Common Mistakes
- Overengineering for hypothetical agents. A new layer or elaborate naming system can make navigation harder. Start with the simplest structure that fits the application.
- Creating duplicate sources of truth. If component rules appear in several documents, they can drift. Keep one canonical guide and link to it.
- Making shared components too generic. A component with many modes and exceptions is difficult to change safely. Split it when responsibilities genuinely differ.
- Relying on folder names alone. A tidy tree does not explain behavior, test commands, or design constraints. Add focused documentation where decisions are not apparent from the code.
- Skipping visual and interaction checks. Passing a type check cannot confirm that a layout works at narrow widths or that keyboard interactions remain usable.
Tips
- Use one consistent naming convention for files and exports, and match related test names to the code they cover.
- Keep instructions brief and task-oriented. Include exact commands and tell contributors where to look when a command fails.
- Make accessibility part of component contracts: identify labels, focus behavior, keyboard use, and meaningful status messages where relevant.
- Prefer small, reviewable changes. Ask for a summary of modified files and checks rather than broad, unspecified refactors.
- Update the guide when the project changes; stale instructions can be more damaging than no instructions.
Troubleshooting
The agent edits the wrong component: Add a route map or a short note identifying the source of truth for the affected screen. Check for duplicate or obsolete implementations and label them clearly before deleting anything.
It invents a new pattern instead of reusing one: Point to a concrete, current example and state which existing component or style convention to follow. If similar examples disagree, reconcile them first.
Checks pass but the UI is wrong: Run the application and inspect the affected screen at relevant viewport sizes. Test the interaction manually or with an existing browser test, and add coverage for the missing state. Build and type checks do not replace visual review.
Tests are flaky or hard to run: Identify environmental dependencies, make setup deterministic where possible, and document prerequisites. Separate failures caused by the change from known unrelated failures rather than silently ignoring them.
Changes keep breaking unrelated screens: Look for overly broad shared styles, implicit global state, or components with too many responsibilities. Narrow the change’s scope, add a targeted regression test, and consider separating feature-specific behavior.
Frequently Asked Questions
Should the codebase use a feature-based or layer-based structure?
Use the structure that makes files easiest to locate in your application. Feature-based organization often helps larger products keep related UI together; a small app may be clearer with a few simple shared folders.
Do I need a special folder for AI agents?
No. A repository guide can live in an existing documentation location or a clearly named instruction file. The important part is that its purpose and location are easy to discover.
Should every component have a test?
Not necessarily. Prioritize tests for meaningful behavior, shared components, complex states, and areas where regressions would be costly. Avoid tests that only repeat implementation details.
How much project guidance should I write?
Document the conventions that affect safe changes: setup, file placement, styling, tests, and important constraints. Keep it concise, and add detail when repeated mistakes show that a rule is missing.
How can I tell if the structure is working?
Try representative tasks and see whether contributors can identify the right files, follow existing patterns, and run relevant checks without extensive clarification. Use repeated friction to guide improvements.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.