Vibe Coding with Nette

An AI agent will write you a hundred lines of PHP in a few seconds. Whether those hundred lines actually run is decided by something the agent cannot supply on its own: a foundation it can read, verify and build on.

Nette has been building that foundation for years – back when it still looked like a detail only purists cared about.

  • Typed to the bone – the agent reads types instead of guessing them
  • Clear conventions – it knows where every class belongs
  • A closed loop – it sees your real application and checks its own work

The IDE Was for You. Types Are for the Agent.

For years we judged our tools by how well they helped a human: autocomplete, a type popping up on hover, jump-to-definition. An agent never looks at your screen. It needs information it can read as plain text and, above all, verify on its own.

That is the whole difference between an IDE and static analysis. PhpStorm discreetly underlines a place where you might be passing null. PHPStan prints the same thing to the console as an error the agent reads, understands and fixes – without you sitting there watching.

So the question stopped being “how nicely does my editor describe this API?” and became “how much does the code say about itself?”

Nette Says a Lot

When PHP 7.1 completed the type system with nullable types, Nette was the first full-stack framework to type its entire API through, declare(strict_types=1) in every file included. Typed properties followed the moment PHP 7.4 shipped them. Whatever the language could express, Nette used – usually before anyone else.

And where PHP itself falls short, annotations take over. Native types cannot say “a non-empty list of strings” or “the return value depends on the argument”. Nette says both, right where it matters:

$data = $form->getValues(RegistrationData::class);
echo $data->email;   // $data is a RegistrationData, fully typed

There is no native PHP type for “if you hand me a class name, I hand you back an instance of it”. A conditional return type says exactly that, and static analysis, your IDE and the agent all read it. Write $data->emial and the mistake surfaces before the code is ever run.

The same care runs through the whole framework: array shapes, class-string<T>, positive-int, non-empty-string. Every Nette package passes PHPStan at level 8 – not in parts, not with a pile of exceptions. You are building on a foundation typed as rigorously as it makes sense to type anything, and a well-typed foundation is what makes a well-typed application easy.

The full story is in the article Your AI Agent Is Only as Good as Your Types.

It's All About the Loop

An agent is only as good as the feedback it gets, and the best feedback is a loop. It writes something, runs the analysis and the tests, reads the result, fixes the error and tries again. Write, check, fix, repeat. That loop is the moment a text generator turns into something that genuinely tunes code into working shape.

Nette hands the agent every part of it:

  • PHPStan with the Nette extension, which teaches the analyzer framework specifics – it knows that $this['menu'] is your MenuControl, it infers the control type from addText(), it understands #[Inject]
  • Nette Tester for the tests. Don't have any yet? That is the very first thing to have the agent write, because without them it cannot tell that it just broke something.
  • Automatic linting of PHP, Latte, NEON, JSON and JavaScript after every single edit, so a broken template never makes it as far as the browser

Your Application, Not a Guess

Ask any AI to “generate an entity for the product table” and it will guess your columns from patterns it picked up during training. Except your price column is called unit_price, and there is a currency_id you never mentioned.

MCP Inspector takes the guessing away. It is a server that lets the agent look straight into your running application: the services in your DI container, your real database schema, your routes, your Tracy logs. Everything it exposes is strictly read-only, and it works from any editor that speaks the Model Context Protocol: Claude Code, Cursor, VS Code with Continue and others.

Debugging changes shape too. Instead of copying a stack trace into a chat window, you say “check the log and tell me what broke” – and the agent reads the exception itself.

Nette Knowledge, Built In

The Claude Code plugin supplies the part that is nowhere in your codebase: how things are actually done in Nette. A whole family of skills covering architecture, forms, database, components, security, Latte, NEON and more, each one switching itself on when the conversation turns to its topic. Ask about form validation and the forms skill wakes up. Ask about a BlueScreen and the Tracy one does.

What comes out reads like an experienced Nette developer wrote it, not like generic PHP stitched together from snippets.

Get Started

The whole setup takes about ten minutes:

  1. Install your AI tool – we recommend Claude Code
  2. Add the Nette plugin so the agent knows the framework
  3. Set up MCP Inspector so it knows your application

Then describe what you want, close the agent into the loop, and let it work. When you want to get more out of your agent, read Vibe Coding in Practice.