Imported from zekkv/tanstack-start-template (
AGENTS.md). Install upstream withnpx skills add zekkv/tanstack-start-template. Copyright stays with the author.
AGENTS.md
This file provides guidance to AI agents when working with code in this repository.
Where things are documented
Read these instead of re-deriving; do not duplicate their content here.
docs/ARCHITECTURE.md— stack, directory map, data flow, auth flows, observability config.docs/DEVELOPMENT.md— local setup, environment variables, scripts, database workflows, testing, and tooling.docs/CONTRIBUTING.md— branch names, Conventional Commits, dependency and env-var rules.README.md— overview, quickstart, local services.
Running a single test
package.json only exposes whole-suite scripts; target a single test by passing the path through:
bun run vitest run tests/unit/auth-session.test.ts # one file
bun run vitest run tests/unit/auth-session.test.ts -t "returns null" # one case
bun run playwright test tests/e2e/landing.test.ts # one E2E file
Test layout gotchas
test:unitruns the Vitestunitproject (vitest run --project unit), targetingtests/unit/withjsdomenvironment.test:integrationruns the Vitestintegrationproject (vitest run --project integration), targetingtests/integration/withnodeenvironment.- Unit tests must not start a database container; keep them to pure logic. Testcontainers belongs in integration/E2E only.
- Coverage is
enabled: trueinvitest.config.ts, so test runs rewritecoverage/.
File naming inside src/features/
- Server functions exported via
createServerFnand consumed by routes are compiled for the client environment. TanStack Start strips.handler(...)bodies but preserves all otherexportdeclarations. - Never statically import runtime built-ins or server-only dependencies (
#/db,"bun") at module level if any exported helper references them (e.g. via default parameters likedatabase = db). This anchors the dependency in the AST and prevents Dead Code Elimination, leaking server built-ins into client bundles. - Instead, reach server dependencies dynamically inside
.handler()viaawait import("#/db"), import server types withimport type, and require injected dependencies in exported helpers (e.g.database: Database). - Do not name either kind
<feature>.server.ts.@tanstack/start-plugin-core's import-protection plugin denies**/*.server.*in the client environment, so the first route that imports it failsbun run build— and onlybuild, nottype:checkand not the test suites. That suffix is only for modules nothing client-reachable imports. - No
-modelsuffix, and no entity-name stutter (notes/notes-fns.ts). A helper with only one caller lives in that caller's file — even if a unit test also imports and tests it (export it from the caller's file for the test). Only extract a helper into its own file when it has two or more application callers. - Server-function validation lives in the Zod schema, parsed with
safeParserethrowingissues[0].message— never let a rawZodErrorreach a route.
Imports
#/... is the only alias for src/. It is declared in three places that must stay in sync — tsconfig.json paths, package.json imports, and the alias block in vitest.config.ts — so adding another alias means touching all three or it will typecheck and then fail under test. components.json already generates #/, so shadcn output needs no rewriting.
Adding an environment variable
Three places, all required: src/env.ts, a commented entry in .env.example, and README.md if it changes setup steps.
Database schemas and migrations
- Whenever touching or modifying database schemas (
src/db/schema.ts,src/db/auth-schema.ts, or any schema definition file), always runbun run db:generateto generate the corresponding migration SQL files insrc/db/drizzle/. - Never handwrite SQL migrations. All migrations must be generated by Drizzle Kit from schema definitions to maintain consistency and prevent schema drift.
- Review generated migration files in
src/db/drizzle/to verify that the generated DDL statements accurately reflect the schema changes. - To apply pending migrations to the database, run
bun run db:migrate(orbun run db:pushfor local rapid prototyping).
