{"slug": "ai-should-stop-generating-the-same-code-over-and-over", "title": "AI Should Stop Generating the Same Code Over and Over", "summary": "A developer is experimenting with an architecture for AI-built business software in which an AI writes only declarative YAML definitions of entities, relations, workflows, automations, permissions, and views, while repeatable concerns such as authentication, database access, and connectivity are compiled deterministically rather than regenerated by the model. The definitions are compiled into an internal JSON representation that a platform uses to build and run the application, with ASP.NET as the first target compiler. The developer argues the approach differs from runtimes like Lowdefy because the application is not fundamentally expressed in terms of a single runtime.", "body_md": "AI coding tools have become ridiculously good...guess we can all agree. \n\nYou can describe an application, wait a few minutes, and suddenly you have React components, API endpoints, database models, authentication, migrations and a decent-looking application...it seems to be magically. Then you dig into the code, try to change something and something you didn't even remotely touch breaks. Then you spend another few thousand tokens explaining the architecture the AI itself created 30 minutes ago.\n\nI was sick of it....\n\nAs part of a platform for small businesses I'm currently working on I am also experimenting with a different architecture for AI-built business software: let AI describe the application, then compile the repeatable parts deterministically especially do not have the AI build things like authentication, connectivity, database stuff...you name it. That has all been solved for 20 years and we shouldn't ask AI to build it over and over again, failing over and over again at getting things right.\n\nThe AI only has to write YAML using my own vocabulary. \n\nThink about something like this:\n\n```\nentity: expense_claim\n\nfields:\n  submitted_by:\n    type: reference\n    targetEntity: person\n\n  amount:\n    type: money\n    currency: EUR\n    required: true\n```\n\nor this..a little bit more involved:\n\n```\nentity: assumption\nownedBy:\n  parent: scenario\n  via: scenario\n  as: table\ndisplay: statement\nfields:\n  statement:\n    label: Assumption\n    type: text\n    required: true\n  scenario:\n    label: Scenario\n    type: reference\n    required: true\n    indexed: true\n    targetEntity: scenario\n    onDelete: cascade\n```\n\nAnd this isn't limited to entities or CRUD.\n\nAutomations can be described in the same vocabulary:\n\n```\nautomation: build_segment_grid\nname: Lay out a segment's lifecycle\neffects:\n  - type: createForEach\n    set:\n      scenario: '{{record.scenario}}'\n      segment: '{{record.id}}'\n      point: '{{source.id}}'\n      label: '{{record.name}} {{source.label}}'\n      flex:\n        pick:\n          entity: revenue_plan\n          filters:\n            - field: scenario\n              operator: eq\n              value: '{{record.scenario}}'\n            - field: tier\n              operator: eq\n              value: flex\n          sort:\n            - field: name\n              direction: asc\n```\n\nWe can describe the whole application with YAML definitions, from entities, relations, workflows, automations, permissions up to views and screens and readymade widgets...its all in YAML.\n\nYet, The exact YAML isn't really the important part.\n\nIt could be JSON. It could eventually be authored visually. Most of the time it may simply be written and modified by an AI.\n\nThe definition says what the business application should do. It doesn't describe how ASP.NET should register a controller, how EF Core should configure a relationship, how Vue should render the form or how an MCP tool should expose the operation, and ASP.NET is just an example here I use as thats the first target compiler that exists today. More to come.\n\nYet...those things can be derived.\n\nAnd hey, YAML rings a bell. Someone must have built something like this before. Absolutely!\n\nLowdefy, for example, takes a similar approach in some ways: you describe an application using YAML instead of manually writing all the implementation code.\n\nBut there is one important architectural difference.\n\nLowdefy's YAML describes an application for the Lowdefy runtime. The runtime interprets that configuration and provides the UI, data connections, actions, authentication and other application machinery.\n\nThat is a perfectly valid architecture, but your application is fundamentally expressed in terms of that runtime.\n\nMy approach is different and goes way beyond that!\n\nFor my project theres two options...The first is to run the application on the Cordango platform. The definition is compiled into an internal JSON representation which the platform uses to build and run the app.\n\nThe platform adds some nice things on top, like apps sharing company data and reacting to each other's events without somebody having to manually build an integration between every single tool. But that's not really what I want to talk about here.\n\nThe second path is the more interesting one for this article:\n\nNot a starter template. Not a few generated models you still have to wire together. An actual standalone application with a frontend, backend, database model, migrations, authentication, permissions, business logic, REST/OpenAPI and MCP.\n\nSomething you can take, build, run and host yourself.\n\nThe current architecture looks roughly like this:\n\n```\n                App Definition\n                     |\n                     v\n            Deterministic Compiler\n                     |\n          +----------+----------+\n          |                     |\n          v                     v\n       Frontend               Backend\n      Vue / Vuetify        ASP.NET Core\n          |                     |\n          |          +----------+----------+\n          |          |          |          |\n          |       REST/API     MCP      Commands\n          |       OpenAPI                Workflows\n          |                     |       Permissions\n          |                     |       Calculations\n          |                     |\n          +----------+----------+\n                     |\n                  EF Core\n                     |\n              Database Model\n                 Migrations\n                     |\n                 PostgreSQL\n```\n\nToday the first complete target generates ASP.NET Core + EF Core + PostgreSQL + Vue 3/Vuetify but Node/Typescript is on its way, Python is being planned and more to come.\n\nAnd because all of those pieces come from the same application definition, they don't have to be separately invented and kept in sync.\n\nIf the definition says an expense_claim exists, that isn't just a database table.\n\nThe compiler can derive:\n\nthe entity model\n\npersistence\n\nmigrations\n\nCRUD operations\n\npermissions\n\nforms and views\n\nREST/OpenAPI\n\nMCP access\n\ncommands and workflows\n\nChange the definition and the generated implementation changes with it.\n\nThe YAML isn't configuration for the generated application. It is the source from which the application is compiled.\n\nAnd this leads to one of my favorite slightly ridiculous consequences:\n\nI'm serious.\n\nIf your App Definition is stored in Git and you pin the compiler/generator versions required to build it, the generated source becomes a build artifact.\n\nGiven the same application definition, generator version and scaffold version, the compiler generates the same files again.\n\nSo technically your repository could look roughly like this:\n\nmy-app/\n\n├── cordango.yaml\n\n├── apps/\n\n│   └── expenses/\n\n│       ├── app.cordango.yaml\n\n│       ├── entities/\n\n│       ├── roles/\n\n│       ├── views/\n\n│       └── workflows/\n\n└── .gitignore\n\nwhile this:\n\ngenerated/\n\n├── api/\n\n├── web/\n\n├── Dockerfile\n\n└── docker-compose.yml\n\ncould simply be regenerated whenever you need it.\n\nNow, whether you should gitignore all generated source is a different discussion. Keeping generated code in Git can obviously be useful for reviewing changes, deployments and debugging.\n\nBut architecturally, you don't have to treat it as the source of truth anymore.\n\nThat's the important part.\n\nThe definition is the source. The code is an output.\n\nAnd unlike a traditional runtime-based no-code platform, taking that output doesn't mean taking a dependency on my hosted service.\n\nThere is no Cordango account requirement, licence server, model API or phone-home service involved in running the generated application.\n\nThe current standalone runtime is small enough that it can either be referenced as a package or embedded into the generated project itself.\n\nSo you can generate the application, take the source, and host it wherever you want.\n\nWith this approach, the AI gets more headroom to reason about the actual business problem instead of spending context and tokens on code we've already solved a thousand times.\n\nIt also has far less room to accidentally break unrelated implementation details. If it changes a workflow, it changes the workflow definition. The compiler handles the rest.\n\nThe AI can still misunderstand the requirement, of course. But those are business-level mistakes, not random implementation drift.\n\nAnd it doesn't even have to be a coding model...I literarily build one of the sample apps with ChatGPT...yes the old standard one, not codex.\n\nI don't want to make this the main part but yes, using YAML saved a ton of token. I compared the generated examples vs the YAML definition with Anthropic's tokenizer and the result was up to 98% fewer token consumed...lets see how that adds up when more work is done but it definitely saves you..some huge chunk.\n\nYAML alone doesn't solve much if the AI still has to read an entire repository every time something changes. So Cordango comes with a CLI around the application model.\n\nThe basic loop becomes:\n\n```\nDescribe a change\n      ↓\nAI changes the relevant definition\n      ↓\ncordango check\n      ↓\ncordango build\n      ↓\nDeterministically generated application\n```\n\nThe AI works on the small semantic representation, not hundreds of generated controllers, migrations, components and API files, the CLi gives the AI the tools it needs to do that. And because the compiler understands the vocabulary, it can reject invalid definitions before they ever turn into source code.\n\ncordango check\n\ncordango build --target app --generator dotnet-vue\n\nThat's really the whole bet.\n\nWant to have a look?\n\n[https://www.github.com/cordango](https://www.github.com/cordango)\n\n[https://docs.cordango.com](https://docs.cordango.com)\n\n[https://www.cordango.com](https://www.cordango.com)\n\nAll feedback welcome, negative, positive, roast it, praise it...give it a try!\n\nmake the thing AI has to understand smaller, more meaningful and harder to accidentally break.", "url": "https://wpnews.pro/news/ai-should-stop-generating-the-same-code-over-and-over", "canonical_source": "https://dev.to/cordango/ai-should-stop-generating-the-same-code-over-and-over-fe5", "published_at": "2026-09-11 21:55:33+00:00", "updated_at": "2026-09-11 22:51:05.566478+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools", "generative-ai", "ai-products"], "entities": ["Lowdefy", "ASP.NET", "EF Core", "Vue", "Cordango"], "alternates": {"html": "https://wpnews.pro/news/ai-should-stop-generating-the-same-code-over-and-over", "markdown": "https://wpnews.pro/news/ai-should-stop-generating-the-same-code-over-and-over.md", "text": "https://wpnews.pro/news/ai-should-stop-generating-the-same-code-over-and-over.txt", "jsonld": "https://wpnews.pro/news/ai-should-stop-generating-the-same-code-over-and-over.jsonld"}}