Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.9 KiB
CLAUDE.md
Project Overview
ZPan v2 is an open-source, S3-native file hosting platform written in TypeScript. Cloudflare Workers is the primary deployment target, Node.js (Docker) is backup.
Core architecture: clients upload directly to S3-compatible storage via presigned URLs, bypassing server bandwidth.
Key Context
- Single package:
server/(Hono API),src/(React SPA),shared/(types/schemas) - CF Workers:
workers/bootstrap.ts(CF Workers + D1) andserver/entry-node.ts(Node + SQLite) - Tests are co-located:
*.test.ts(Node),*.cf-test.ts(CF Workers) - Migrations: drizzle-kit generates SQL → wrangler manages D1 state
Docs Index
- CONTRIBUTING.md — setup, commands, quality gates, migration workflow, deployment
- docs/architecture.md — system architecture, tech decisions, platform abstraction
- V2_ROADMAP.md — product positioning, release plan (v2.0–v2.9)
- docs/roadmap/ — per-version technical specs (v2.0.md–v2.9.md)
CONTRIBUTING.md Compliance
All processes defined in CONTRIBUTING.md are mandatory. Every PR must follow them exactly — including preview verification before merge. No exceptions.
Full-Stack Thinking
This is a full-stack project. When implementing a feature or fixing a bug, think end-to-end across frontend and backend. Don't limit yourself to only changing the frontend or only changing the backend — do what's correct for the problem. If the backend API is wrong, fix the backend. If the frontend approach is wrong, fix the frontend. If a feature needs both, change both. Always consider the full request lifecycle: URL → route → API → service → DB → response → UI.
Commit Convention
Conventional Commits (feat:, fix:, docs:, etc.). PRs target master.
Pre-commit Hooks
Husky runs npm run typecheck + lint-staged (biome auto-fix) on every git commit. Never bypass with --no-verify. Never run npm install --ignore-scripts — the prepare script must run so hooks are installed. If a hook fails, fix the underlying issue and re-commit.
API Client (Hono RPC)
The frontend must use Hono RPC client for all API calls. Never use raw fetch() with hardcoded URL strings.
// ✅ Correct — type-safe, compile-time path validation
import { hc } from 'hono/client'
import type { AppType } from '@server/app'
const client = hc<AppType>('/')
const res = await client.api.admin.storages.$get()
// ❌ Wrong — hardcoded path, no type safety
const res = await fetch('/api/admin/storages')
Exception: uploadToS3() calls external S3 presigned URLs, not our API — raw fetch is OK there.
Types
All shared types live in shared/. Never create duplicate type definitions in src/ or server/. Import from @shared/types and @shared/constants.