Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:29:15 +08:00
commit be476a3fea
76 changed files with 12812 additions and 0 deletions

View File

@@ -0,0 +1,327 @@
---
name: grey-haven-project-structure
description: Organize Grey Haven projects following standard structures for TanStack Start (frontend) and FastAPI (backend). Use when creating new projects, organizing files, or refactoring project layout.
---
# Grey Haven Project Structure
Follow Grey Haven Studio's standardized project structures for **TypeScript/React** (TanStack Start) and **Python/FastAPI** projects.
## Frontend Structure (TanStack Start + React 19)
Based on `cvi-template` - TanStack Start, React 19, Drizzle, Better-auth.
### Directory Layout
```
project-root/
├── .claude/ # Claude Code configuration
├── .github/workflows/ # GitHub Actions (CI/CD)
├── public/ # Static assets
├── src/
│ ├── routes/ # TanStack Router file-based routes
│ │ ├── __root.tsx # Root layout
│ │ ├── index.tsx # Homepage
│ │ ├── _authenticated/ # Protected routes group
│ │ │ ├── _layout.tsx # Auth layout wrapper
│ │ │ ├── dashboard.tsx # /dashboard
│ │ │ └── profile.tsx # /profile
│ │ └── auth/ # Auth routes
│ │ ├── login.tsx # /auth/login
│ │ └── signup.tsx # /auth/signup
│ ├── lib/
│ │ ├── components/ # React components
│ │ │ ├── ui/ # Shadcn UI (PascalCase)
│ │ │ ├── auth/ # Auth components
│ │ │ ├── layout/ # Layout components
│ │ │ └── shared/ # Shared components
│ │ ├── server/ # Server-side code
│ │ │ ├── schema/ # Drizzle schema (snake_case)
│ │ │ ├── functions/ # Server functions
│ │ │ ├── auth.ts # Better-auth config
│ │ │ └── db.ts # Database connections
│ │ ├── config/ # Configuration
│ │ │ ├── env.ts # Environment validation
│ │ │ └── auth.ts # Auth configuration
│ │ ├── middleware/ # Route middleware
│ │ ├── hooks/ # Custom React hooks (use-*)
│ │ ├── utils/ # Utility functions
│ │ └── types/ # TypeScript types
│ └── tests/
│ ├── unit/ # Vitest unit tests
│ ├── integration/ # Vitest integration tests
│ └── e2e/ # Playwright E2E tests
├── migrations/ # Drizzle migrations
├── .env.example # Example environment variables
├── .prettierrc # Prettier (90 chars, double quotes)
├── .eslintrc # ESLint (any allowed, strict off)
├── tsconfig.json # TypeScript (~/* path alias)
├── commitlint.config.cjs # Commitlint (100 char header)
├── drizzle.config.ts # Drizzle ORM config
├── vite.config.ts # Vite configuration
├── vitest.config.ts # Vitest test configuration
├── package.json # Dependencies (use bun!)
└── README.md # Project documentation
```
### Key Frontend Patterns
#### Path Imports - Always Use ~/* Alias
```typescript
// ✅ Correct - Use ~/* path alias
import { Button } from "~/lib/components/ui/button";
import { getUserById } from "~/lib/server/functions/users";
import { env } from "~/lib/config/env";
import { useAuth } from "~/lib/hooks/use-auth";
// ❌ Wrong - Relative paths
import { Button } from "../../lib/components/ui/button";
```
#### File Naming Conventions
- **Components**: PascalCase (`UserProfile.tsx`, `LoginForm.tsx`)
- **Routes**: lowercase with hyphens (`user-profile.tsx`, `auth/login.tsx`)
- **Utilities**: camelCase or kebab-case (`formatDate.ts`, `use-auth.ts`)
- **Server functions**: camelCase (`auth.ts`, `users.ts`)
- **Schema files**: plural lowercase (`users.ts`, `organizations.ts`)
#### Component Structure Order
```typescript
import { useState } from "react"; // 1. External imports
import { useQuery } from "@tanstack/react-query";
import { Button } from "~/lib/components/ui/button"; // 2. Internal imports
import { getUserById } from "~/lib/server/functions/users";
interface UserProfileProps { // 3. Types/Interfaces
userId: string;
}
export default function UserProfile({ userId }: UserProfileProps) { // 4. Component
const [editing, setEditing] = useState(false); // 5. State hooks
const { data: user } = useQuery({ // 6. Queries/Mutations
queryKey: ["user", userId],
queryFn: () => getUserById(userId),
staleTime: 60000,
});
const handleSave = () => { // 7. Event handlers
// ...
};
return ( // 8. JSX
<div>
<h1>{user?.full_name}</h1>
<Button onClick={handleSave}>Save</Button>
</div>
);
}
```
## Backend Structure (FastAPI + Python)
Based on `cvi-backend-template` - FastAPI, SQLModel, Alembic.
### Directory Layout
```
project-root/
├── .github/workflows/ # GitHub Actions
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app entry point
│ ├── routers/ # API routers (endpoints)
│ │ ├── __init__.py
│ │ ├── auth.py # /auth routes
│ │ ├── users.py # /users routes
│ │ └── health.py # /health routes
│ ├── services/ # Business logic layer
│ │ ├── __init__.py
│ │ ├── user_service.py
│ │ ├── auth_service.py
│ │ └── billing_service.py
│ ├── db/ # Database layer
│ │ ├── __init__.py
│ │ ├── models/ # SQLModel models (snake_case)
│ │ │ ├── __init__.py
│ │ │ ├── user.py
│ │ │ ├── tenant.py
│ │ │ └── organization.py
│ │ ├── repositories/ # Data access layer
│ │ │ ├── __init__.py
│ │ │ ├── base.py # Base repository
│ │ │ └── user_repository.py
│ │ └── session.py # Database sessions
│ ├── schemas/ # Pydantic schemas
│ │ ├── __init__.py
│ │ ├── user.py # UserCreate, UserResponse
│ │ ├── auth.py # AuthRequest, AuthResponse
│ │ └── common.py # Shared schemas
│ ├── middleware/ # FastAPI middleware
│ │ ├── __init__.py
│ │ ├── auth.py # JWT verification
│ │ └── tenant.py # Tenant context
│ ├── core/ # Core configuration
│ │ ├── __init__.py
│ │ ├── config.py # Settings (Doppler)
│ │ ├── security.py # Password hashing, JWT
│ │ └── deps.py # FastAPI dependencies
│ └── utils/ # Utility functions
│ ├── __init__.py
│ └── format.py
├── tests/ # Pytest tests
│ ├── __init__.py
│ ├── unit/ # @pytest.mark.unit
│ ├── integration/ # @pytest.mark.integration
│ └── e2e/ # @pytest.mark.e2e
├── alembic/ # Alembic migrations
│ ├── versions/
│ └── env.py
├── .env.example # Example environment variables
├── .env # Local environment (gitignored)
├── pyproject.toml # Ruff, mypy, pytest config
├── alembic.ini # Alembic configuration
├── Taskfile.yml # Task runner commands
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Development dependencies
└── README.md # Project documentation
```
### Key Backend Patterns
#### Import Organization (Automatic with Ruff)
```python
"""Module docstring describing purpose."""
# 1. Standard library imports
import os
from datetime import datetime
from typing import Optional
from uuid import UUID
# 2. Third-party imports
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import select
# 3. Local imports
from app.db.models.user import User
from app.db.repositories.user_repository import UserRepository
from app.schemas.user import UserCreate, UserResponse
```
#### File Naming Conventions
- **Modules**: snake_case (`user_service.py`, `auth_middleware.py`)
- **Models**: PascalCase class, snake_case file (`User` in `user.py`)
- **Tests**: `test_` prefix (`test_user_service.py`)
#### Repository Pattern (with Tenant Isolation)
```python
# app/db/repositories/base.py
from typing import Generic, TypeVar, Optional
from uuid import UUID
from sqlmodel import select
from sqlalchemy.ext.asyncio import AsyncSession
T = TypeVar("T")
class BaseRepository(Generic[T]):
"""Base repository with CRUD and tenant isolation."""
def __init__(self, session: AsyncSession, model: type[T]):
self.session = session
self.model = model
async def get_by_id(self, id: UUID, tenant_id: UUID) -> Optional[T]:
"""Get by ID with automatic tenant filtering."""
result = await self.session.execute(
select(self.model)
.where(self.model.id == id)
.where(self.model.tenant_id == tenant_id)
)
return result.scalar_one_or_none()
```
#### Service Layer Pattern
```python
# app/services/user_service.py
from uuid import UUID
from app.db.repositories.user_repository import UserRepository
from app.schemas.user import UserCreate, UserResponse
class UserService:
"""User business logic."""
def __init__(self, user_repo: UserRepository):
self.user_repo = user_repo
async def create_user(self, data: UserCreate, tenant_id: UUID) -> UserResponse:
"""Create new user with validation."""
existing = await self.user_repo.get_by_email(data.email_address, tenant_id)
if existing:
raise ValueError("Email already registered")
user = await self.user_repo.create(data, tenant_id)
return UserResponse.model_validate(user)
```
## Supporting Documentation
All supporting files are under 500 lines per Anthropic best practices:
- **[examples/](examples/)** - Complete project examples
- [frontend-directory-structure.md](examples/frontend-directory-structure.md) - Full TanStack Start structure
- [backend-directory-structure.md](examples/backend-directory-structure.md) - Full FastAPI structure
- [component-structure.md](examples/component-structure.md) - React component patterns
- [repository-pattern.md](examples/repository-pattern.md) - Repository with tenant isolation
- [service-pattern.md](examples/service-pattern.md) - Service layer examples
- [INDEX.md](examples/INDEX.md) - Examples navigation
- **[reference/](reference/)** - Structure references
- [file-naming.md](reference/file-naming.md) - Naming conventions
- [import-organization.md](reference/import-organization.md) - Import ordering rules
- [path-aliases.md](reference/path-aliases.md) - Path alias configuration
- [INDEX.md](reference/INDEX.md) - Reference navigation
- **[templates/](templates/)** - Copy-paste ready templates
- [tanstack-start-project/](templates/tanstack-start-project/) - Frontend scaffold
- [fastapi-project/](templates/fastapi-project/) - Backend scaffold
- **[checklists/](checklists/)** - Structure checklists
- [project-setup-checklist.md](checklists/project-setup-checklist.md) - New project setup
- [refactoring-checklist.md](checklists/refactoring-checklist.md) - Structure refactoring
## When to Apply This Skill
Use this skill when:
- Creating new Grey Haven projects
- Organizing files in existing projects
- Refactoring project layout
- Setting up directory structure
- Deciding where to place new files
- Onboarding new team members to project structure
## Template Reference
These patterns are from Grey Haven's production templates:
- **Frontend**: cvi-template (TanStack Start + React 19)
- **Backend**: cvi-backend-template (FastAPI + Python)
## Critical Reminders
1. **Path aliases**: Always use ~/* for TypeScript imports
2. **File naming**: Components PascalCase, modules snake_case
3. **Import order**: External → Internal → Local
4. **Component structure**: Imports → Types → Component → Hooks → Handlers → JSX
5. **Tenant isolation**: Repository pattern includes tenant_id filtering
6. **Database fields**: snake_case in schema files (NOT camelCase)
7. **Test organization**: unit/, integration/, e2e/ directories
8. **Configuration**: Doppler for all environment variables
9. **Routes**: TanStack file-based routing in src/routes/
10. **Backend layers**: Routers → Services → Repositories → Models

View File

@@ -0,0 +1,165 @@
# Project Setup Checklist
**Use when creating new Grey Haven projects.**
## Initial Setup
### Choose Template
- [ ] Frontend: Use cvi-template (TanStack Start + React 19)
- [ ] Backend: Use cvi-backend-template (FastAPI + Python)
- [ ] Clone from Grey Haven GitHub organization
- [ ] Remove .git directory and re-initialize
### Environment Configuration
- [ ] Copy .env.example to .env
- [ ] Set up Doppler project (dev, test, staging, production)
- [ ] Add required secrets to Doppler
- [ ] Test Doppler access: `doppler run --config dev -- echo "Working"`
- [ ] Add .env to .gitignore (verify)
## Frontend Setup (TanStack Start)
### Directory Structure
- [ ] Verify src/routes/ structure (file-based routing)
- [ ] Verify src/lib/ organization (components, server, config, etc.)
- [ ] Verify public/ for static assets
- [ ] Verify migrations/ for Drizzle migrations
### Configuration Files
- [ ] Update tsconfig.json (verify ~/* path alias)
- [ ] Update package.json (project name, description)
- [ ] Verify .prettierrc (90 char line length, double quotes)
- [ ] Verify .eslintrc (any allowed, strict off)
- [ ] Update commitlint.config.cjs (100 char header)
- [ ] Update vite.config.ts (project-specific settings)
- [ ] Update vitest.config.ts (coverage thresholds >80%)
### Dependencies
- [ ] Run `bun install` (NOT npm!)
- [ ] Verify Drizzle ORM installed
- [ ] Verify better-auth installed
- [ ] Verify TanStack Start/Query/Router installed
- [ ] Verify Shadcn UI components
### Database Setup
- [ ] Create PostgreSQL database (PlanetScale)
- [ ] Add DATABASE_URL to Doppler
- [ ] Add DATABASE_URL_ADMIN to Doppler
- [ ] Generate initial migration: `bun run db:generate`
- [ ] Apply migration: `doppler run --config dev -- bun run db:migrate`
### Authentication
- [ ] Configure better-auth in src/lib/server/auth.ts
- [ ] Add BETTER_AUTH_SECRET to Doppler
- [ ] Add BETTER_AUTH_URL to Doppler
- [ ] Set up OAuth providers (if needed)
- [ ] Test auth flow locally
## Backend Setup (FastAPI)
### Directory Structure
- [ ] Verify app/ structure (routers, services, db, etc.)
- [ ] Verify tests/ organization (unit, integration, e2e)
- [ ] Verify alembic/ for migrations
### Configuration Files
- [ ] Update pyproject.toml (project name, dependencies)
- [ ] Verify Ruff configuration (130 char line length)
- [ ] Verify mypy configuration (strict type checking)
- [ ] Verify pytest configuration (markers, coverage >80%)
- [ ] Update alembic.ini (database URL from Doppler)
- [ ] Create Taskfile.yml (common commands)
### Dependencies
- [ ] Create virtual environment: `python -m venv venv`
- [ ] Activate venv: `source venv/bin/activate`
- [ ] Install deps: `pip install -r requirements.txt`
- [ ] Install dev deps: `pip install -r requirements-dev.txt`
- [ ] Verify SQLModel installed
- [ ] Verify FastAPI installed
- [ ] Verify Alembic installed
### Database Setup
- [ ] Create PostgreSQL database (PlanetScale)
- [ ] Add DATABASE_URL to Doppler
- [ ] Add DATABASE_URL_ADMIN to Doppler
- [ ] Generate initial migration: `alembic revision --autogenerate -m "Initial"`
- [ ] Apply migration: `doppler run --config dev -- alembic upgrade head`
## GitHub Setup
### Repository
- [ ] Create GitHub repository
- [ ] Push initial commit
- [ ] Set up branch protection rules (main branch)
- [ ] Require PR before merging
- [ ] Require 1 approval
- [ ] Require status checks to pass
### GitHub Actions
- [ ] Add DOPPLER_TOKEN to repository secrets
- [ ] Add CLOUDFLARE_API_TOKEN to repository secrets (if deploying)
- [ ] Verify .github/workflows/ci.yml
- [ ] Verify .github/workflows/deploy.yml
- [ ] Test CI/CD pipeline
## Testing
### Frontend Testing
- [ ] Run unit tests: `bun test`
- [ ] Run integration tests: `bun test:integration`
- [ ] Run E2E tests: `bun test:e2e`
- [ ] Verify coverage >80%
### Backend Testing
- [ ] Run unit tests: `pytest -m unit`
- [ ] Run integration tests: `pytest -m integration`
- [ ] Run E2E tests: `pytest -m e2e`
- [ ] Verify coverage >80%
## Documentation
### README.md
- [ ] Update project name and description
- [ ] Document getting started steps
- [ ] Document Doppler setup
- [ ] Document database setup
- [ ] Document testing commands
- [ ] Document deployment process
### Additional Docs
- [ ] Create API documentation (if applicable)
- [ ] Document architecture decisions
- [ ] Document multi-tenant setup
- [ ] Create onboarding guide
## Deployment
### Cloudflare Workers (Frontend)
- [ ] Create wrangler.toml files (dev, staging, production)
- [ ] Create KV namespaces
- [ ] Create R2 buckets (if needed)
- [ ] Configure custom domains
- [ ] Test deployment to staging
### Production Readiness
- [ ] Set up monitoring (Sentry, Axiom)
- [ ] Configure error tracking
- [ ] Set up performance monitoring
- [ ] Configure rate limiting
- [ ] Set up backup strategy
- [ ] Document rollback procedure
## Post-Setup
### Team Onboarding
- [ ] Share Doppler access with team
- [ ] Share repository access
- [ ] Document local setup process
- [ ] Schedule team walkthrough
### Maintenance
- [ ] Set up dependency update schedule
- [ ] Set up security scanning
- [ ] Schedule regular code reviews
- [ ] Document support procedures

View File

@@ -0,0 +1,48 @@
# Project Structure Examples
Complete project structure examples for Grey Haven applications.
## Available Examples
### [frontend-directory-structure.md](frontend-directory-structure.md)
Full TanStack Start project structure.
- Complete directory tree with annotations
- File-based routing examples
- Component organization patterns
- Server functions structure
### [backend-directory-structure.md](backend-directory-structure.md)
Full FastAPI project structure.
- Complete directory tree with annotations
- Routers, services, repositories layers
- Database models and migrations
- Testing organization
### [component-structure.md](component-structure.md)
React component organization patterns.
- Import ordering
- Hook usage patterns
- Event handler organization
- JSX structure
### [repository-pattern.md](repository-pattern.md)
Repository pattern with tenant isolation.
- Base repository implementation
- Specific repository examples
- Tenant filtering patterns
- Async/await patterns
### [service-pattern.md](service-pattern.md)
Service layer examples.
- Business logic organization
- Service dependencies
- Error handling
- Validation patterns
## Quick Reference
**Need frontend structure?** → [frontend-directory-structure.md](frontend-directory-structure.md)
**Need backend structure?** → [backend-directory-structure.md](backend-directory-structure.md)
**Need component patterns?** → [component-structure.md](component-structure.md)
**Need repository patterns?** → [repository-pattern.md](repository-pattern.md)
**Need service patterns?** → [service-pattern.md](service-pattern.md)

View File

@@ -0,0 +1,32 @@
# Project Structure Reference
Configuration references and naming conventions for Grey Haven projects.
## Available References
### [file-naming.md](file-naming.md)
File naming conventions for both stacks.
- TypeScript/React conventions
- Python/FastAPI conventions
- Test file naming
- Configuration file naming
### [import-organization.md](import-organization.md)
Import ordering and organization rules.
- TypeScript import order
- Python import order (PEP 8)
- Ruff automatic sorting
- ESLint import rules
### [path-aliases.md](path-aliases.md)
Path alias configuration and usage.
- tsconfig.json setup (~/* alias)
- Vite configuration
- Import examples
- Common pitfalls
## Quick Reference
**Need naming rules?** → [file-naming.md](file-naming.md)
**Need import order?** → [import-organization.md](import-organization.md)
**Need path aliases?** → [path-aliases.md](path-aliases.md)