Most of the code in my projects is now written by AI coding agents. I design the product, decide the architecture and data model, and review what comes back. That changes the question I ask about frameworks. It’s no longer “which one do I enjoy typing?” It’s “which one does an agent write well, and which one can I review quickly when it doesn’t?”

For me, that’s SvelteKit. Version 3 shipped this week, and I’ve just upgraded Costbase and Embark to it. Here’s why I think it suits agentic development better than anything else I’ve used.

Less code is less to review

Svelte components are close to plain HTML, CSS and JavaScript. State is a variable, updating it is an assignment, and there’s no hooks layer to get wrong.

<script lang="ts">
  let count = $state(0);
  const doubled = $derived(count * 2);
</script>

<button onclick={() => count++}>{count} doubled is {doubled}</button>

When an agent writes that, there’s very little to check. There’s no dependency array to audit and no stale closure waiting to happen. Smaller components also mean smaller diffs, fewer tokens in the agent’s context, and fewer places for it to wander off.

The bottleneck in agentic development isn’t how fast code gets written. It’s how fast a person can confirm the code is right. A framework that needs less code to say the same thing speeds up the part that’s actually slow.

One obvious way to do things

Agents do their best work when there’s a clear pattern to follow. SvelteKit’s remote functions give data loading and mutations a single shape: a schema-validated function in a .remote.ts file, called directly from a component.

// src/lib/remotes/trip.remote.ts
import { form, query } from "$app/server";
import { z } from "zod";
import { eq } from "drizzle-orm";
import { db } from "#lib/server/db/index.js";
import { tripTable } from "#lib/server/db/schema.js";

export const getTrip = query(z.string(), async (id) => {
  return db.query.tripTable.findFirst({ where: eq(tripTable.id, id) });
});

export const renameTrip = form(
  z.object({ id: z.string(), name: z.string().min(1, "Name is required") }),
  async ({ id, name }) => {
    await db.update(tripTable).set({ name }).where(eq(tripTable.id, id));
    await getTrip(id).refresh();
  },
);
<script lang="ts">
  import { getTrip, renameTrip } from "#lib/remotes/trip.remote.js";

  let { id }: { id: string } = $props();
  const trip = $derived(await getTrip(id));
</script>

<h1>{trip?.name}</h1>

<form {...renameTrip}>
  <input {...renameTrip.fields.id.as("hidden", id)} />
  <input {...renameTrip.fields.name.as("text")} />
  <button>Save</button>
</form>

That’s the whole round trip. There’s no API route to invent, no fetch wrapper, no client cache keys to keep in sync, and types flow from the schema to the form fields. Once an agent has seen one remote file in a project, it writes the next one the same way. Embark has more than 50 remote functions and they all look alike, which is exactly what you want from code you didn’t type yourself.

Guardrails the compiler enforces

An agent will happily do the wrong thing if nothing stops it. SvelteKit stops a lot of it:

  • Server code stays on the server. Modules in server directories can’t be imported into client code, and SvelteKit 3 now enforces this everywhere in the project. An agent can’t accidentally ship a database client or a secret to the browser.
  • Templates are type-checked. svelte-check checks .svelte files, not just .ts, so a renamed prop or a wrong field fails the check instead of failing in production.
  • The compiler explains itself. When I upgraded to SvelteKit 3, svelte-check flagged three components that copied a prop into local state. That’s a subtle bug: the component shows stale data after the prop changes. The warning says what’s wrong and links to the fix, which is exactly the kind of feedback an agent can act on without me.

Fast, specific feedback is what turns an agent from a guesser into something closer to a careful junior developer. Svelte’s compiler gives you a lot of it for free.

The training data gap is closing

The honest weakness: models have seen far more React than Svelte, and Svelte 5’s runes are newer than a lot of their training data. Early on, agents kept writing Svelte 4 syntax like export let and $: statements.

The Svelte team has done more about this than any other framework team I know of:

  • LLM-ready docs. svelte.dev/llms.txt publishes the full Svelte and SvelteKit documentation in formats built for models, including abridged and compressed versions.
  • An official MCP server. It lets an agent look up current documentation, and its svelte-autofixer tool runs static analysis on generated code before you ever see it.
  • Official skills and plugins for Claude Code, Cursor, Codex and others, including a subagent dedicated to editing Svelte files.

With those in place, the old-syntax problem has mostly gone away for me. The agent checks the docs instead of guessing from memory.

Where React still wins

React has the bigger ecosystem and the bigger hiring pool, and that matters for large teams. If you’re on a React team, I’d look at TanStack Start before Next.js: its types are excellent and its data flow is explicit rather than hidden behind caching layers.

For a solo developer or a small team building app-shaped products with agents, the maths is different. Less code means less to review, one pattern means less drift between files, and good compiler feedback means fewer bugs reach you. That’s why SvelteKit is my default for everything behind a login.