Software engineers have always been forced to commit the category error of shipping patterns as components. It was our only choice. But AI coding agents change this.
Imagine you are building an internal component library. A rigid API works fine for simple components like buttons that can only be used in a handful of valid ways. But on the other end of the spectrum, you have more complex components, like a drawer. As a content container, a drawer can be used in an almost infinite number of valid ways. You might have a template in mind for how the content should look, but this is a fuzzy standard. You might know a valid content variation when you see it, but you can't possibly anticipate and enumerate all of them preemptively. Encoding them in a rigid API is futile. Your API will never satisfy the long tail of user needs.
The core problem is that the definition of what makes a good drawer layout is not component-shaped, it is pattern-shaped. Unlike a component, a pattern naturally supports a great variety of correct solutions in a narrow range.
The problem is that you cannot install a pattern as an npm package, so we are stuck shipping patterns as components. But increasingly, AI coding agents change this. Instead of having to pull in a package and bend the API to our will, we might be able to pull in 95% of the needed code and an updated markdown from our upstream that tells AI how to do the rest. I think in the next few years we will see a shift from thinking of architecting systems purely as composing components (configurable modules, packages) to composing patterns (generative templates that AI agents can complete).
When most engineers hear "software design pattern" it conjures up the Gang of Four (factory, singleton, observer and so on). These are reusable solutions to common problems, static templates. But the idea of a pattern did not originate with the GoF. It was coined by Christopher Alexander in the field of architecture and urban design in the 1970s. Alexander was frustrated with the component-based thinking of modern architecture, with its narrow focus on functionality and standardization. His desire was to think of buildings as bundles of timeless patterns, e.g. "window place", "light on two sides of a room", "half-hidden garden", that reliably work. To him, patterns are not just solutions but solution generators. A pattern is a mapping from a context and a common problem to a solution, but it leaves the exact form of the solution open. The same pattern, applied in different contexts, produces slightly different results. Just like our drawer. Trying to design a single standard window component for all buildings ignores the local texture. But re-instantiating "window place" in each individual building fits just right. You can't preempt exactly how you'll end up applying a pattern in each use case, but you feel it when you see it (he calls this the "quality that can't be named"). To Alexander, this is the source of timeless beauty in traditional architecture.
His favorite example was Paris. The city was not master-planned as a single design. It emerged from a small number of shared patterns: courtyards opening onto streets, buildings of a certain height, balconies at particular floors. These patterns were all applied independently, thousands of times, by different builders. The result is a city with extraordinary coherence and extraordinary variety. No two buildings are identical, but they all clearly belong to the same place. A great variety of designs in a narrow range.
And crucially, you cannot get there with components. Components give you uniformity but can never generate the same variety you get with a pattern. A component is a fixed artifact. A pattern is the thing that produces artifacts, each one slightly different, each one fitted to what the end user needs.
Unfortunately, when we copied the idea of the design pattern from architecture to software engineering, we flattened it to fit our medium. We lost the generator piece. We had to. Human-written code could not quite support what Alexander envisioned for architecture. Code could not regenerate itself to fit the exact needs of every consumer; that would be unmaintainable. Instead, we ship components: black boxes with fixed APIs that consumers configure. But, and this is the core point of the essay, sufficiently advanced AI coding agents remove that restriction.
Let us return to the internal UI component library problem. Shadcn was an early bet on patterns. Shadcn's contrarian approach was to ship patterns directly by letting you copy their code, like good drawer examples, and modify it to your needs. Historically, this was seen as more of a cop-out than anything else, because it simply meant that the full maintenance burden would now fall on the consumer.
But I think Shadcn bet that AI would soon make that maintenance cost negligible. Software engineering has never just been about shipping code; it is about shipping knowledge. If you fork code you might not be able to pull patches from an npm package upstream, but an AI could still pull in new knowledge via an updated markdown file and then update your forked code to incorporate it. This moves library maintainers from shipping a static component, to shipping a static pattern, to shipping a primitive generative pattern.
Andrej Karpathy posted a perfect example of this last week. Talking about his OpenClaw setup, he noted:
"I also love their approach to configurability - it's not done via config files it's done via skills! For example, /add-telegram instructs your AI agent how to modify the actual code to integrate Telegram. I haven't come across this yet and it slightly blew my mind earlier today as a new, AI-enabled approach to preventing config mess and if-then-else monsters. Basically - the implied new meta is to write the most maximally forkable repo and then have skills that fork it into any desired more exotic configuration."
Andrej Karpathy
Notice how this is just like Christopher Alexander's idea of a pattern. The skill markdown file and code template together form a mapping from a context and a problem to a solution, but leave the exact form of the solution open. The AI coding agent can then use that pattern to create exactly the right solution for the consumer. Just like each builder in Paris could use the pattern "courtyards opening onto streets" to create something that perfectly fits the building they are working on, the AI agent in your terminal can use the /add-telegram pattern to generate exactly the correct integration for you.
Any engineer worth their salt is already thinking about the maintenance burden as I write this. Maybe the /add-telegram approach works as a one-off, but now you own this code. Previously it was outsourced; now it becomes a liability. How will you maintain it without an upstream package you can simply bump to pull in the latest knowledge?
On the other hand, why wouldn't AI be able to take care of this? Imagine a simple 1000-line library that ships as a pattern, similar to the /add-telegram example: a code template paired with a skill.md file telling the agent how to adapt it. The AI instantiates the pattern by forking the template and writing code to exactly fit your use case. Over time, the upstream publishes new versions as an updated code template plus skill.md, and your AI installs them by repeating the process. For a thousand-line dependency, this is almost trivially easy, even today (we're already seeing it with /add-telegram). We've proven the base case. What remains is a scaling problem, and scaling problems are exactly what AI has been solving, predictably, for a decade. To a sufficiently advanced AI, the entire codebase of a dependency is more legible than its API is to a human. The future of tech is unpredictable, but one thing is almost constant: any moat built on the assumption that compute won't scale is bound to fail. I wouldn't bet against the scaling laws.
If this is true, it is really just a matter of time before we can safely ship our most complex libraries as patterns. Of course that doesn't mean everything will ship as patterns. Just because AI can cheaply maintain a forked button library doesn't mean it should. Buttons are component-shaped and they work just fine through a rigid API. They'll continue shipping as such. But your drawers, in all their pattern-shaped variety, won't. If this is true, I think we can look forward to an era of beautifully designed custom software. SaaS that actually addresses the long tail of user needs. Agencies that scale. That was Christopher Alexander's dream for architecture: a pattern-based world where every house is adapted to fit its inhabitants exactly. Historically this has been almost impossible to scale, whether you're building with atoms or bits.
But I think AI has changed that for the bits.