Skip to content

Commit 2a558b5

Browse files
committed
chore: added AGENTS.md support
1 parent 117d671 commit 2a558b5

File tree

2 files changed

+235
-230
lines changed

2 files changed

+235
-230
lines changed

AGENTS.md

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# AGENTS.md
2+
3+
This file provides guidance to AI coding agents when working with code in this repository.
4+
5+
## Monorepo Architecture
6+
7+
This is a pnpm workspace monorepo with two packages:
8+
9+
- **`packages/worker`**: Cloudflare Worker (backend)
10+
- **`packages/web`**: TanStack Start app (frontend)
11+
12+
### Key Architectural Pattern: Worker RPC via Service Bindings
13+
14+
The web package communicates with the worker package through **two mechanisms**:
15+
16+
1. **HTTP API** (traditional): REST endpoints exposed by Hono in `packages/worker/src/index.ts`
17+
2. **RPC calls** (service bindings): Type-safe method calls via `WorkerRpc` class in `packages/worker/src/rpc.ts`
18+
19+
**Critical understanding**: The worker exports TWO things from `src/index.ts`:
20+
21+
- `export default app` - Hono HTTP handler (default export)
22+
- `export { WorkerRpc } from './rpc'` - Named export for RPC entrypoint
23+
24+
The web package's `wrangler.jsonc` configures a service binding:
25+
26+
```jsonc
27+
"services": [{
28+
"binding": "WORKER_RPC",
29+
"service": "fullstack-monorepo-template-worker",
30+
"entrypoint": "WorkerRpc" // References the named export
31+
}]
32+
```
33+
34+
### Type Safety Across Packages
35+
36+
The web package imports types directly from the worker package:
37+
38+
```typescript
39+
// packages/web/env.d.ts
40+
import type { WorkerRpc } from '../worker/src/rpc';
41+
```
42+
43+
This creates a **direct TypeScript dependency** between packages. The monorepo structure enables this cross-package type sharing.
44+
45+
### TanStack Start Server Context
46+
47+
In TanStack Start server functions/loaders, access the RPC binding via:
48+
49+
```typescript
50+
import { getServerContext } from '@tanstack/react-start/server';
51+
52+
const { WORKER_RPC } = getServerContext().cloudflare.env;
53+
const result = await WORKER_RPC.sayHello('World');
54+
```
55+
56+
## Commands
57+
58+
### Development
59+
60+
```bash
61+
# Run both services in separate terminals
62+
pnpm dev:worker # Worker on localhost:8787
63+
pnpm dev:web # Web on localhost:3000
64+
65+
# Or run just one
66+
pnpm --filter @fullstack-monorepo-template/worker dev
67+
pnpm --filter @fullstack-monorepo-template/web dev
68+
```
69+
70+
### Testing
71+
72+
```bash
73+
# Run all tests
74+
pnpm test
75+
76+
# Run tests for specific package
77+
pnpm --filter @fullstack-monorepo-template/worker test
78+
pnpm --filter @fullstack-monorepo-template/web test
79+
80+
# Run tests in watch mode (within package directory)
81+
cd packages/worker && pnpm test --watch
82+
```
83+
84+
### Linting & Formatting
85+
86+
```bash
87+
pnpm lint # Lint all packages + check formatting
88+
pnpm lint:fix # Fix linting issues in all packages
89+
pnpm format # Format all code
90+
pnpm format:check # Check formatting without changes
91+
```
92+
93+
### Deployment
94+
95+
```bash
96+
# Deploy both packages
97+
pnpm deploy
98+
99+
# Deploy individually
100+
pnpm deploy:worker
101+
pnpm deploy:web
102+
103+
# Login to Cloudflare first (one-time)
104+
cd packages/worker && pnpm wrangler login
105+
```
106+
107+
### Working with Workspace Packages
108+
109+
```bash
110+
# Add dependency to specific package
111+
pnpm --filter @fullstack-monorepo-template/worker add <package-name>
112+
pnpm --filter @fullstack-monorepo-template/web add <package-name>
113+
114+
# Add dev dependency
115+
pnpm --filter @fullstack-monorepo-template/worker add -D <package-name>
116+
```
117+
118+
## Adding New RPC Methods
119+
120+
When adding RPC methods that the web package will call:
121+
122+
1. **Add method to `packages/worker/src/rpc.ts`**:
123+
124+
```typescript
125+
export class WorkerRpc extends WorkerEntrypoint {
126+
async myNewMethod(param: string): Promise<Result> {
127+
// implementation
128+
}
129+
}
130+
```
131+
132+
2. **TypeScript will automatically provide types** in the web package because `env.d.ts` imports the `WorkerRpc` type
133+
134+
3. **Call from web package** in any server function:
135+
136+
```typescript
137+
const { WORKER_RPC } = getServerContext().cloudflare.env;
138+
const result = await WORKER_RPC.myNewMethod('value');
139+
```
140+
141+
4. **Optional**: Add helper function in `packages/web/src/lib/worker-rpc.ts` for convenience
142+
143+
## Adding Cloudflare Bindings
144+
145+
To add KV, D1, R2, or other bindings to the worker:
146+
147+
1. Update `packages/worker/wrangler.jsonc`:
148+
149+
```jsonc
150+
{
151+
"kv_namespaces": [
152+
{
153+
"binding": "MY_KV",
154+
"id": "your-namespace-id",
155+
},
156+
],
157+
}
158+
```
159+
160+
2. Update TypeScript types in `packages/worker/src/index.ts` or create a separate `env.ts`:
161+
162+
```typescript
163+
interface Env {
164+
MY_KV: KVNamespace;
165+
}
166+
```
167+
168+
3. Access in RPC methods or HTTP handlers:
169+
170+
```typescript
171+
// In rpc.ts
172+
export class WorkerRpc extends WorkerEntrypoint<Env> {
173+
async getData(key: string) {
174+
return await this.env.MY_KV.get(key);
175+
}
176+
}
177+
```
178+
179+
## Vitest Configuration for Cloudflare Workers
180+
181+
The worker package uses `@cloudflare/vitest-pool-workers` for testing. The config pattern is:
182+
183+
```typescript
184+
// vitest.config.mts
185+
import { defineConfig } from 'vitest/config';
186+
187+
export default defineConfig({
188+
test: {
189+
pool: '@cloudflare/vitest-pool-workers',
190+
poolOptions: {
191+
workers: {
192+
wrangler: { configPath: './wrangler.jsonc' },
193+
},
194+
},
195+
},
196+
});
197+
```
198+
199+
**Do not use** `defineWorkersConfig` from `@cloudflare/vitest-pool-workers/config` - it causes TypeScript module resolution issues.
200+
201+
## pnpm Workspace Configuration
202+
203+
The `pnpm-workspace.yaml` includes `onlyBuiltDependencies` for native dependencies:
204+
205+
```yaml
206+
onlyBuiltDependencies:
207+
- esbuild
208+
- sharp
209+
- workerd
210+
```
211+
212+
This ensures these packages are built correctly in the monorepo context.
213+
214+
## Package Naming Convention
215+
216+
Packages use the `@fullstack-monorepo-template/*` scope:
217+
218+
- `@fullstack-monorepo-template/worker`
219+
- `@fullstack-monorepo-template/web`
220+
221+
When filtering commands, use these exact names: `pnpm --filter @fullstack-monorepo-template/worker <command>`
222+
223+
## ESLint Configuration
224+
225+
The project uses **ESLint v9** with the new flat config format (`eslint.config.js`).
226+
227+
Key points:
228+
229+
- Uses `@typescript-eslint/eslint-plugin` v8+ (compatible with ESLint 9)
230+
- Configured for both TypeScript and TSX/JSX files
231+
- The `no-undef` rule is disabled for TypeScript files (TypeScript handles this)
232+
- Ignores: `node_modules/`, `dist/`, `.wrangler/`, `build/`
233+
234+
Both packages (`worker` and `web`) have `lint` and `lint:fix` scripts that use the shared root config.

0 commit comments

Comments
 (0)