forked from imbytecat/fullstack-starter
将应用特定的构建输出配置下沉至各自 turbo.json,根级 build 任务添加拓扑依赖;AGENTS.md 统一添加 Bun 专用运行时警告;桌面端启用 Linux CEF 渲染器。
6.6 KiB
6.6 KiB
AGENTS.md - AI Coding Agent Guidelines
Guidelines for AI agents working in this Bun monorepo.
Project Overview
⚠️ This project uses Bun exclusively as both the JavaScript runtime and package manager. Do NOT use Node.js / npm / yarn / pnpm. All commands start with
bun— usebun installfor dependencies andbun run/bun <script>for scripts. Never usenpm,npx, ornode.
- Monorepo: Bun workspaces + Turborepo orchestration
- Runtime: Bun (see
mise.tomlfor version) — NOT Node.js - Package Manager: Bun — NOT npm / yarn / pnpm
- Apps:
apps/server- TanStack Start fullstack web app (seeapps/server/AGENTS.md)apps/desktop- Tauri v2 desktop shell, loads server via sidecar (seeapps/desktop/AGENTS.md)
- Packages:
packages/utils,packages/tsconfig(shared configs)
Build / Lint / Test Commands
Root Commands (via Turbo)
bun dev # Start all apps in dev mode
bun build # Build all apps
bun fix # Lint + format (Biome auto-fix)
bun typecheck # TypeScript check across monorepo
Server App (apps/server)
bun dev # Vite dev server (localhost:3000)
bun build # Production build → .output/
bun fix # Biome auto-fix
bun typecheck # TypeScript check
# Database (Drizzle)
bun db:generate # Generate migrations from schema
bun db:migrate # Run migrations
bun db:push # Push schema (dev only)
bun db:studio # Open Drizzle Studio
Desktop App (apps/desktop)
bun dev # Copy sidecar + start Tauri dev
bun build # Copy sidecar + build installer
# Rust (from apps/desktop/src-tauri/)
cargo check # Compile check
cargo clippy # Linter
cargo fmt # Formatter
Testing
No test framework configured yet. When adding tests:
bun test path/to/test.ts # Run single test file
bun test -t "pattern" # Run tests matching pattern
cargo test test_name -- --nocapture # Rust single test with output
Code Style (TypeScript)
Formatting (Biome)
- Indent: 2 spaces
- Line endings: LF
- Quotes: Single
' - Semicolons: Omit (ASI)
- Arrow parentheses: Always
(x) => x
Imports
Biome auto-organizes. Order:
- External packages
- Internal
@/*aliases - Type imports (
import type { ... })
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
import { db } from '@/server/db'
import type { ReactNode } from 'react'
TypeScript Strictness
strict: truenoUncheckedIndexedAccess: true- array/object access returnsT | undefinednoImplicitOverride: trueverbatimModuleSyntax: true- Use
@/*path aliases (maps tosrc/*)
Naming Conventions
| Type | Convention | Example |
|---|---|---|
| Files (utils) | kebab-case | auth-utils.ts |
| Files (components) | PascalCase | UserProfile.tsx |
| Components | PascalCase arrow | const Button = () => {} |
| Functions | camelCase | getUserById |
| Constants | UPPER_SNAKE | MAX_RETRIES |
| Types/Interfaces | PascalCase | UserProfile |
React Patterns
// Components: arrow functions (enforced by Biome)
const MyComponent = ({ title }: { title: string }) => {
return <div>{title}</div>
}
// Routes: TanStack Router file conventions
export const Route = createFileRoute('/')({
component: Home,
})
// Data fetching: TanStack Query
const { data } = useSuspenseQuery(orpc.todo.list.queryOptions())
Error Handling
- Use
try-catchfor async operations - Throw descriptive errors
- ORPC: Use
ORPCErrorwith proper codes (NOT_FOUND,INPUT_VALIDATION_FAILED) - Never use empty catch blocks
Code Style (Rust - Tauri)
- Indent: 4 spaces
- Naming: snake_case (functions), PascalCase (types), SCREAMING_SNAKE (consts)
- Use
expect("中文消息")overunwrap() - Async:
tokioruntime,tauri::async_runtime::spawn - Run
cargo fmtandcargo clippybefore commit
Database (Drizzle ORM)
import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core'
import { sql } from 'drizzle-orm'
export const myTable = pgTable('my_table', {
id: uuid().primaryKey().default(sql`uuidv7()`),
name: text().notNull(),
createdAt: timestamp({ withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp({ withTimezone: true }).notNull().defaultNow().$onUpdateFn(() => new Date()),
})
Environment Variables
- Use
@t3-oss/env-corewith Zod validation insrc/env.ts - Server vars: no prefix
- Client vars:
VITE_prefix required - Never commit
.envfiles
Critical Rules
DO:
- Run
bun fixbefore committing - Use
@/*path aliases (not relative imports) - Let React Compiler handle memoization (no manual
useMemo/useCallback) - Include
createdAt/updatedAton all tables
DON'T:
- Use
npm,npx,node,yarn,pnpm— always usebun/bunx - Edit
src/routeTree.gen.ts(auto-generated) - Use
as any,@ts-ignore,@ts-expect-error - Commit
.envfiles - Use empty catch blocks
catch(e) {} - Use
unwrap()in Rust withoutexpect()
Git Workflow
- Make changes following style guide
bun fix- auto-format and lintbun typecheck- verify typesbun dev- test locally- Commit with descriptive message
Directory Structure
.
├── apps/
│ ├── server/ # TanStack Start fullstack app
│ │ ├── src/
│ │ │ ├── client/ # ORPC client, Query client
│ │ │ ├── components/
│ │ │ ├── routes/ # File-based routing
│ │ │ └── server/ # API layer + database
│ │ │ ├── api/ # ORPC contracts, routers, middlewares
│ │ │ └── db/ # Drizzle schema
│ │ └── AGENTS.md
│ └── desktop/ # Tauri v2 shell (no frontend src)
│ ├── src-tauri/ # Rust Tauri code
│ │ ├── src/ # Rust source
│ │ └── binaries/ # Sidecar binaries
│ └── AGENTS.md
├── packages/
│ ├── tsconfig/ # Shared TS configs
│ └── utils/ # Shared utilities
├── biome.json # Linting/formatting config
├── turbo.json # Turbo task orchestration
└── package.json # Workspace root
See Also
apps/server/AGENTS.md- Detailed TanStack Start / ORPC patternsapps/desktop/AGENTS.md- Rust / Tauri development guide