This document provides essential information for AI agents working on this Nuxt 4 web application.
Technology Stack:
- Framework: Nuxt 4 (with Vue 3)
- Language: TypeScript (strict mode)
- Package Manager: pnpm (v10) - NEVER use npm or npx, always use pnpm/pnpx
- Runtime: Node.js 24
- Database: SQLite (via Nitro experimental database feature)
- Styling: Tailwind CSS 4 + Nuxt UI
- Code Quality: Biome (linting, formatting, import organization)
Architecture:
This is a full-stack Nuxt application with:
- Server-side API routes and database access
- Client-side Vue components and composables
- Type-safe SQLite database with migration system
- Shared code between client and server
pnpm install # Install dependencies
pnpm dev # Start development serverREQUIRED after ANY code change:
pnpm typecheck # MUST pass - verify TypeScript typesAdditional quality checks:
pnpm build # Verify production build works
pnpx biome check . # Check linting and formatting
pnpx biome check . --write # Auto-fix issues- Run
pnpm typecheck- must have zero errors - Run
pnpm build- must complete successfully - Verify Biome linting passes
- Test affected functionality manually
Before making significant changes:
When planning to implement a large or complex feature that involves multiple files or substantial refactoring, always ask the user if they want to work on a dedicated branch before proceeding, unless you're already on a feature branch.
Examples of changes that warrant a separate branch:
- Major refactoring across multiple files
- New feature implementations with multiple components
- Database schema changes with migrations
- Architecture changes or significant structural modifications
This helps keep the main branch stable and allows for easier code review and rollback if needed.
app/- Client-side application codeapp/components/- Vue componentsapp/composables/- Vue composables for reusable logicapp/layouts/- Page layout componentsapp/pages/- File-based routing (e.g.,pages/index.vue->/)app/assets/- CSS, images, and other assetsapp.vue- Root application component
server/- Server-side code (API routes, database, plugins)server/api/v1/- API routes (if required). Docsserver/database/- Database-related codeserver/database/migrations/- TypeScript migration filesserver/database/migrations.ts- Migration runner and typesserver/database/types.ts- Database type definitions
server/plugins/- Nitro plugins (e.g., database initialization)
shared/- Code shared between client and server. Docs
public/- Static files served as-is (e.g.,favicon.svg).nuxt/- Auto-generated Nuxt build files (gitignored).output/- Production build output (gitignored).data/- Local SQLite database files (gitignored)
Migrations are TypeScript files in server/database/migrations/ that define schema changes. Each migration must:
- Export a
migrationobject conforming to theMigrationinterface - Have a unique name (e.g.,
001_create_users_table) - Be added to the
migrationsarray inserver/database/migrations.ts
Migration Example:
// filename: server/database/migrations/001_create_caves_table.ts
// biome-ignore lint/suspicious/noTsIgnore: Nitro experimental database feature, type works at runtime
// @ts-ignore
import { useDatabase } from "#imports";
import type { Migration } from "../migrations.js";
/**
* Creates the caves table with all required columns and indexes.
*/
export const migration: Migration = {
name: "001_create_caves_table",
async up() {
const db = useDatabase();
await db.sql`
CREATE TABLE IF NOT EXISTS caves (
id TEXT PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
)
`;
await db.sql`
CREATE INDEX IF NOT EXISTS idx_caves_github_username
ON caves(github_username)
`;
await db.sql`
CREATE INDEX IF NOT EXISTS idx_caves_status
ON caves(status)
`;
},
};Migration Guidelines:
- Name migrations sequentially:
001_,002_,003_, etc. - Always use
CREATE TABLE IF NOT EXISTSfor idempotency - Add indexes for frequently queried columns
- Include descriptive JSDoc comments
- Use the
// @ts-ignorecomment foruseDatabase()imports
Access the database in server-side code using:
// biome-ignore lint/suspicious/noTsIgnore: Nitro experimental database feature
// @ts-ignore
import { useDatabase } from "#imports";
const db = useDatabase();
const result = await db.sql`SELECT * FROM users WHERE id = ${userId}`;Strict Type Safety:
- NO
anytypes - Biome will error on explicitany - Use Zod schemas for runtime validation
- Leverage Nuxt's auto-imports for type inference
- Required
@ts-ignorefor experimental Nitro database features (see migration examples)
Import Patterns:
- Use
#importsfor Nuxt auto-imports - Use
@/or~/for project root imports (both work in Nuxt 4) - Relative imports for local files
Code Style:
- Indentation: 2 spaces
- Line width: 100 characters
- Quotes: Double quotes
- Semicolons: Always required
- Import organization: Enabled (auto-sorts imports)
Linting Rules:
noExplicitAny: Error (never useany)noNonNullAssertion: Warning (avoid!operator)useConst: Error (preferconstoverlet)useTemplate: Error (use template literals, not concatenation)
Running Biome:
pnpx biome check . # Check for issues
pnpx biome check . --write # Auto-fix issues
pnpx biome format . --write # Format code- Use
<script setup>syntax for composition API - Define props with TypeScript interfaces
- Use Nuxt auto-imports (no need to import
ref,computed, etc.) - Follow Vue 3 best practices
Auto-Imports:
Nuxt auto-imports many utilities, so you don't need explicit imports for:
- Vue APIs:
ref,computed,watch,onMounted, etc. - Nuxt composables:
useRoute,useRouter,useFetch,useState, etc. - Custom composables from
app/composables/
Server vs. Client:
- Code in
server/only runs on the server - Code in
app/can run on both server (SSR) and client - Use
import.meta.serverorimport.meta.clientto conditionally execute code - Database access is server-only
File-Based Routing:
- Files in
app/pages/automatically create routes pages/index.vue->/pages/about.vue->/aboutpages/users/[id].vue->/users/:id(dynamic route)
Experimental Feature:
The Nitro database feature is experimental. Always use the @ts-ignore pattern shown in migration examples.
SQL Tagged Templates:
Use tagged template literals for SQL queries:
// Correct - parameterized, safe from SQL injection
await db.sql`SELECT * FROM users WHERE id = ${userId}`;
// Wrong - string concatenation, vulnerable to SQL injection
await db.sql`SELECT * FROM users WHERE id = '${userId}'`;Type Safety:
Define Zod schemas in server/database/types.ts for runtime validation of query results.
Always run after changes:
pnpm typecheckThis uses Nuxt's built-in TypeScript checking and must pass before committing code.
Verify production builds work:
pnpm buildThis ensures:
- All TypeScript types are valid
- All imports resolve correctly
- No runtime errors during build
- Nuxt can generate the production bundle
pnpm dev # Start dev server on http://localhost:3000- Node.js: 24.x
- pnpm: 10.x
nuxt.config.ts- Nuxt configuration (modules, app settings, Nitro config)tsconfig.json- TypeScript configuration (references Nuxt's generated configs)biome.jsonc- Biome linting and formatting rules.gitignore- Ignores.nuxt/,.output/,.data/,node_modules/
- Store secrets in
.env(gitignored) - Use
process.env.VARIABLE_NAMEin server code - Use runtime config for client-side env vars (see Nuxt docs)
Deployment is automated via GitHub Actions on push to main:
- Installs dependencies with pnpm
- Builds the application (
pnpm build) with Cloudflare environment variables - Deploys to Cloudflare Workers using the Wrangler GitHub Action
- Database migrations run automatically when the Worker starts
See .github/workflows/deploy.yaml for details and README.md for initial Cloudflare setup instructions.
- Always run
pnpm typecheckafter any code change - this is the primary success criterion - Use Biome for code quality - follow the configured rules strictly
- Respect the Nuxt auto-import system - don't add unnecessary imports
- Use the
@ts-ignorepattern for experimental database features - Follow the migration pattern exactly when creating database changes
- Test both development (
pnpm dev) and production (pnpm build) builds - Never commit files in
.nuxt/,.output/, or.data/ - Always use parameterized queries for database access (SQL tagged templates)