BoilerplateHub

SvelteKit App AGENTS.md Template

For a SvelteKit 2 application with Svelte 5 runes, server load functions, form actions, and a Postgres database accessed from the server only. It assumes Tailwind for styling and adapter based deployment. Use it when the load and action boundary is what an agent most often gets wrong.

SvelteKitSvelte 5TypeScriptTailwindPostgres
AGENTS.md
Download
# AGENTS.md

This is a SvelteKit application with server rendered routes, form actions, and a Postgres backend.

## Project

Stack: SvelteKit 2, Svelte 5 (runes), TypeScript, Tailwind, Postgres, Vitest, Playwright.

Layout:

- `src/routes/+page.svelte` page markup, `+page.server.ts` server load and form actions
- `src/routes/+layout.svelte` and `+layout.server.ts` shared shell and session
- `src/routes/api/<name>/+server.ts` JSON endpoints
- `src/lib/` shared code, imported through the `$lib` alias
- `src/lib/server/` server only modules, never importable from a component
- `src/lib/components/` presentational components
- `src/hooks.server.ts` session handling and route guards
- `src/app.d.ts` App.Locals and App.PageData types

Rule of thumb: `+page.server.ts` runs on the server only, `+page.ts` runs on both, so anything with a secret or a database call belongs in the former.

Entry points: `src/hooks.server.ts`, `src/routes/+layout.server.ts`, `svelte.config.js`.

## Commands

```bash
pnpm install
pnpm dev                     # dev server on :5173
pnpm build                   # production build, must pass before a PR
pnpm preview                 # serve the build locally
pnpm check                   # svelte-check, type checks .svelte files too
pnpm lint                    # eslint and prettier check
pnpm format                  # prettier write
pnpm test                    # vitest run
pnpm test src/lib/pricing    # one file or directory
pnpm test:e2e                # playwright
pnpm exec svelte-kit sync    # regenerate ./$types after route changes
pnpm db:migrate              # apply database migrations
```

If `./$types` imports fail to resolve, run `pnpm exec svelte-kit sync` before assuming a real type error.

Run `pnpm check` and `pnpm build` before returning work.

## Code style

- Svelte 5 runes only: `$state`, `$derived`, `$props`, `$effect`. No `export let`, no `$:` reactive statements, no legacy stores in new code.
- `$effect` is a last resort. Derive values with `$derived` instead of syncing them in an effect.
- Data comes from a `load` function, never from a fetch inside `onMount` for content that should be server rendered.
- Mutations use form actions with progressive enhancement via `use:enhance`. Do not hand roll a fetch POST for a form.
- `load` returns serializable data. Never return a class instance or a database client.
- Import secrets from `$env/static/private` or `$env/dynamic/private`, only inside `src/lib/server/` or a `.server.ts` file.
- Validate every form action payload and every endpoint body with a schema before use.
- Tailwind utilities in markup. Use `<style>` blocks only for something utilities cannot express.
- Components take props and emit callbacks. No component reaches into a global store for data its parent already has.
- Use `$lib` imports, not relative paths that climb directories.

## Boundaries

Do not touch without explicit instruction:

- `.svelte-kit/` and any `./$types` file, both are generated.
- `svelte.config.js` adapter configuration and `vite.config.ts`.
- `pnpm-lock.yaml`. Add dependencies with `pnpm add`.
- `.env`. New variables are documented in `.env.example`.
- Database migration files that have already been applied.
- `.github/workflows/` and hosting configuration.

Needs human review: `src/hooks.server.ts`, anything that changes session or cookie handling, new public API endpoints, and any change that moves code between server only and shared modules.

Never import from `src/lib/server/` in a `.svelte` file. If that seems necessary, the data should come from `load` instead.

## Testing

- `pnpm test` runs Vitest, `pnpm test <path>` runs one file.
- Required tests: every exported function in `src/lib/`, every form action, and every `+server.ts` endpoint.
- `load` functions are tested by calling them with a stubbed event object.
- Component tests only for components with real logic. Do not test markup structure.
- Playwright covers sign in and the primary conversion flow. Keep the e2e suite small.
- A bug fix ships with a test that fails without it.

## Git workflow

- Branch from `main`: `feat/short-description`, `fix/short-description`.
- Conventional commits: `fix(checkout): validate coupon before creating the session`.
- `pnpm build` and `pnpm check` must pass locally before opening a PR, prerender errors only appear at build time.
- PR description states what changed, why, and how it was verified, plus any new environment variable.
- Never commit to `main`.

What each section does

Project

SvelteKit encodes a lot in filenames, and the difference between +page.js and +page.server.js decides whether code runs on the client. Listing the route conventions and where shared code lives makes that split explicit. Naming hooks.server.js as an entry point matters because it holds auth.

Commands

The sync step and the check command are specific to SvelteKit and easy to skip, which leads to phantom type errors. Listing them with dev, build, and test gives the agent a complete verification loop. Database commands belong here when the app owns its schema.

Code style

Svelte 5 runes changed the reactivity model, so rules about state, derived, and effect prevent an agent from writing Svelte 4 patterns. Rules about load functions and form actions keep data flow idiomatic. All of these are visible in a diff.

Boundaries

Server only modules and environment imports are the security boundary in SvelteKit, and a wrong import leaks secrets into the client bundle. Generated types and adapter config should be left alone. Call out what needs review.

Testing

The valuable tests here are on load functions, actions, and pure logic rather than component rendering. Saying so prevents a low value component test suite. Documenting how to run one file keeps iteration fast.

Git workflow

Standard conventions apply, but noting that a build must pass before a PR catches adapter and prerender errors early. Commit scoping keeps history useful. State the branch policy plainly.

Which agents read this file?

Claude Code looks for CLAUDE.md. Most other agents and editors read AGENTS.md. Rather than maintaining both and letting them drift, keep one real file and symlink the other:

ln -s AGENTS.md CLAUDE.md
git add AGENTS.md CLAUDE.md

Git stores the symlink, so it survives cloning on macOS and Linux. On Windows it needs developer mode or a stub file that references the real one. The full comparison is in CLAUDE.md vs AGENTS.md.

Other templates

Reviews

Leave a comment

Your rating (optional)

0/2000