Make Way for AI-Readable Codebases
Introduction: The Overwhelmed Developer CEO
In the early days of Ceedar, around last November, we were (still are!) a small, two-person startup with big ambitions. Like many startups, we were working hard to increase our productivity without the luxury of adding more people to the team. As CEO, I had to balance many tasks, including writing code while also running the business. So, I began experimenting with AI coding tools like aider.chat, hoping they would allow me to ship features faster and avoid hiring additional developers.
At first, the AI coding tools seemed like a dream come true. But it didnât take long for that illusion to crack. I started running into major issuesâproblems that didnât just slow me down, but made me wonder if I was actually being any more efficient at all.
The Problem: The AI Struggles with Code Context
The problem became obvious as I worked with the AI. I realized that the AI wasnât able to understand my code structure well enough to make meaningful changes. The root of the issue was how I had organized my codebase. Back then, I used the classic stack-layer structure, where different layers like endpoints, business logic, and database calls were all grouped together. This structure worked well enough for human developers (did it tho?), but for the AI, it was too much context at once.
The AI would struggle to navigate the code, often touching parts that were irrelevant or unnecessary. For example, it would try to generate code but fail to import the right dependencies. Worse, when it couldnât find a type definition or a piece of context, it would just invent one. This resulted in code that accessed non-existent properties of structs, breaking things in subtle but frustrating ways. I found myself spending more time fixing the AIâs mistakes than if I had written the code myself from scratch.
The Turning Point: Organizing by Feature, Managing Costs, and Setting Conventions
After dealing with these inefficiencies for long enough, I started looking for a solution. Thatâs when I had a crucial realization: the AI could handle a smaller, more focused context much better than larger, multi-layered files. If I could limit the code it was working with to just what was relevant, I could avoid the confusion and errors that came from giving it too much information.
But it wasnât just about efficiencyâthere was also a financial cost to consider. As any startup founder knows, running lean is critical to survival. Tokens, the currency of AI context, cost money. Passing unnecessary tokens or processing more context than required can quickly add up in financial terms. I realized that by reducing the amount of code I fed the AI, I wasnât just improving its performance; I was also lowering my operational costs.
By keeping each feature self-contained, I drastically reduced both the amount of context the AI had to process and the number of tokens I had to pay for. In a small startup, every dollar counts, and this approach helped me stay efficient while keeping expenses low. I went through quite some effort to do a major refactor, hoping for the payoff, and it has paid off so many times over.
While the example Iâve been working with here is focused on our API, Iâve found that the same principles hold true for our front-end code as well. Whether itâs handling API logic or user interface components, organizing by featureâkeeping all the related logic in one placeâhas made a significant difference in both efficiency and clarity.
A Thought on Stack Layers: A Conversation Starter
Recently, I came across a new boilerplate called v1.run by the folks building the open-source Midday product, which follows the stack-layered approach to organizing code. Take a look in the 'packages' folder to see what I mean. Itâs a well-constructed approach, and I can certainly see why developers might opt for this kind of structure, especially if theyâre used to dividing their work across layers like endpoints, business logic, and database calls.
However, after working extensively with AI coding tools, Iâve found that this traditional stack-layer structure can create unnecessary frictionâboth for the AI and for developers. When everything is separated by layers, it can be difficult to maintain a clear context, and AI models, in particular, seem to struggle with making sense of the whole system.
Thatâs why Iâd like to start a conversation around the merits of organizing code by feature rather than by stack layers. In my experience, tightly binding everything related to a specific feature into a single file or folder dramatically reduces the cognitive overhead for both humans and AI. It keeps the context clear and the dependencies obvious, which leads to fewer errors and faster development cycles.
That said, this isnât about dismissing the stack-layered approach. Iâm curious to hear from others, especially those whoâve used structures like v1.run, about their thoughts on how these different organizational strategies can complement or even improve one anotherâespecially when working with AI tools in todayâs development environment.
The Transformation: Regaining Efficiency and Control
The impact of the change we'd made was immediate and profound. Suddenly, the AI stopped making wild guesses and unnecessary changes. It became a much more reliable partner in the development process. I could add a single file or folder to its context window, write a prompt for a new feature or change in business logic, and trust the AI to follow the example of the code I had already written. With aider, the tool I was using, it would actually make commits with each iteration, streamlining my workflow even further (you can revert any change easily at any time).
The AI's ability to make surgical edits based on clear, focused context was a game-changer. Instead of spending hours fixing broken code, I could spend more time on higher-level tasks, like steering the business or developing new ideas. As CEO, I knew that coding wasnât my only responsibility, and this new structure allowed me to stay productive without getting bogged down by code issues. I didnât have to hire more people, and yet we were still shipping new features faster than ever.
Conclusion: The Power of a Well-Structured Codebase
Looking back, the real lesson here wasnât just about improving how I organized the codeâit was about building a system that could work seamlessly with AI. By focusing on a feature-based organization and maintaining consistent conventions across the codebase, I unlocked the true potential of the AI tools.
This structure didnât just make the AI better at its jobâit made me better at mine. It allowed me to balance coding with the many other demands of running a startup. By freeing myself from the chaos of a disorganized codebase, I reclaimed time, energy, and focus.
For other developers and founders out there, the message is clear: if you want to make AI an effective part of your workflow, itâs not enough to just use the tools. You need to structure your code in a way that the AI can understandâand that starts with making it as readable and consolidated as possible.
b.t.w. for the uninitiated, don't forget to use Claude Sonnet 3.5. that's where the magic happens