I find it's perfectly possible to write large maintainable projects using these tools. I have a Rust project I built with LLMs that's over 150k loc now, and it's structure is a lot better than anything I would've ended up on my own. One of the things I do is ask the LLM to come up with a phased plan for introducing new features. I also ask the model to make mermaidjs diagrams I can inspect and come up with file layout up front. Then I get it to make a branch for each phase and implement a focused feature. Then I can review it and I have good context for what it's supposed to be doing, and it's scoped so that the code is manageable enough to fit in my head. Doing that alone gets you a long way. Another thing I do is ask it to make refactors by looking through the code base and finding repeating patterns in code that can be consolidated, or large files that need to be split up. If you do this regularly, you end up with much cleaner code, and the agent is much better at doing that at scale than you could by hand.
Testing is another really important aspect. I always ask the model to do TDD, and then add end to end integration tests for features. For web apps, using playwright storybooks is really effective. You can define exactly what the user workflow is and then have the model test it through a headless browser end to end. This creates a contract where you know what that functionality is actually working end to end.
As long as you don't just let the model crap out tons of code unsupervised, and box it in sufficiently with a contract, then the code is no worse than what a human would produce. And I'd argue that it's often better.