// 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.
| 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. |
Follow Grey Haven Studio's standardized project structures for TypeScript/React (TanStack Start) and Python/FastAPI projects.
Based on cvi-template - TanStack Start, React 19, Drizzle, Better-auth.
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
// โ
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";
UserProfile.tsx, LoginForm.tsx)user-profile.tsx, auth/login.tsx)formatDate.ts, use-auth.ts)auth.ts, users.ts)users.ts, organizations.ts)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>
);
}
Based on cvi-backend-template - FastAPI, SQLModel, Alembic.
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
"""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
user_service.py, auth_middleware.py)User in user.py)test_ prefix (test_user_service.py)# 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()
# 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)
All supporting files are under 500 lines per Anthropic best practices:
examples/ - Complete project examples
reference/ - Structure references
templates/ - Copy-paste ready templates
checklists/ - Structure checklists
Use this skill when:
These patterns are from Grey Haven's production templates: