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.
Resources
3Install
npx skillscat add greyhaven-ai/claude-code-config/grey-haven-project-structure Install via the SkillsCat registry.
This skill enforces Grey Haven Studio's standardized project structures for TanStack Start frontend and FastAPI backend applications. It defines directory layouts, naming conventions, and file organization patterns for routes, components, server code, and database schemas. Agents and developers should use it when initializing new projects, restructuring existing codebases, or ensuring consistency across Grey Haven projects.
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 documentationKey Frontend Patterns
Path Imports - Always Use ~/* Alias
// โ
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
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 documentationKey Backend Patterns
Import Organization (Automatic with Ruff)
"""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, UserResponseFile Naming Conventions
- Modules: snake_case (
user_service.py,auth_middleware.py) - Models: PascalCase class, snake_case file (
Userinuser.py) - Tests:
test_prefix (test_user_service.py)
Repository Pattern (with Tenant Isolation)
# 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
# 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/ - Complete project examples
- frontend-directory-structure.md - Full TanStack Start structure
- backend-directory-structure.md - Full FastAPI structure
- component-structure.md - React component patterns
- repository-pattern.md - Repository with tenant isolation
- service-pattern.md - Service layer examples
- INDEX.md - Examples navigation
reference/ - Structure references
- file-naming.md - Naming conventions
- import-organization.md - Import ordering rules
- path-aliases.md - Path alias configuration
- INDEX.md - Reference navigation
templates/ - Copy-paste ready templates
- tanstack-start-project/ - Frontend scaffold
- fastapi-project/ - Backend scaffold
checklists/ - Structure checklists
- project-setup-checklist.md - New project setup
- 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
- Path aliases: Always use ~/* for TypeScript imports
- File naming: Components PascalCase, modules snake_case
- Import order: External โ Internal โ Local
- Component structure: Imports โ Types โ Component โ Hooks โ Handlers โ JSX
- Tenant isolation: Repository pattern includes tenant_id filtering
- Database fields: snake_case in schema files (NOT camelCase)
- Test organization: unit/, integration/, e2e/ directories
- Configuration: Doppler for all environment variables
- Routes: TanStack file-based routing in src/routes/
- Backend layers: Routers โ Services โ Repositories โ Models