Initial commit
This commit is contained in:
711
skills/project-scaffolding/checklists/project-setup-checklist.md
Normal file
711
skills/project-scaffolding/checklists/project-setup-checklist.md
Normal file
@@ -0,0 +1,711 @@
|
||||
# Grey Haven Project Setup Checklist
|
||||
|
||||
Comprehensive checklist for scaffolding new Grey Haven projects with TanStack Start, FastAPI, or both.
|
||||
|
||||
## Pre-Project Planning
|
||||
|
||||
- [ ] **Define project scope** (MVP features, future roadmap)
|
||||
- [ ] **Choose architecture**:
|
||||
- [ ] TanStack Start only (frontend + BFF)
|
||||
- [ ] FastAPI only (backend API)
|
||||
- [ ] Full-stack (TanStack Start + FastAPI)
|
||||
- [ ] Monorepo or separate repos
|
||||
|
||||
- [ ] **Define multi-tenant strategy**:
|
||||
- [ ] Single-tenant (one customer)
|
||||
- [ ] Multi-tenant (multiple customers)
|
||||
- [ ] Tenant isolation: subdomain, custom domain, path-based
|
||||
|
||||
- [ ] **Plan authentication**:
|
||||
- [ ] Better Auth (recommended for Grey Haven)
|
||||
- [ ] OAuth providers (Google, GitHub, etc.)
|
||||
- [ ] Email/password
|
||||
- [ ] Magic links
|
||||
|
||||
- [ ] **Database choice**:
|
||||
- [ ] PostgreSQL (recommended for Grey Haven)
|
||||
- [ ] MySQL
|
||||
- [ ] SQLite (development only)
|
||||
|
||||
- [ ] **Hosting platform**:
|
||||
- [ ] Vercel (TanStack Start)
|
||||
- [ ] Railway (FastAPI)
|
||||
- [ ] AWS (ECS, Lambda)
|
||||
- [ ] Self-hosted
|
||||
|
||||
## Repository Setup
|
||||
|
||||
### Initialize Git
|
||||
|
||||
- [ ] **Create repository** (GitHub, GitLab, Bitbucket)
|
||||
- [ ] **Initialize git**: `git init`
|
||||
- [ ] **Add .gitignore**:
|
||||
```
|
||||
node_modules/
|
||||
.env
|
||||
.env.local
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
dist/
|
||||
.output/
|
||||
.vercel/
|
||||
.DS_Store
|
||||
```
|
||||
|
||||
- [ ] **Initial commit**: `git commit -m "Initial commit"`
|
||||
- [ ] **Create dev branch**: `git checkout -b dev`
|
||||
- [ ] **Set up branch protection** (require PRs for main)
|
||||
|
||||
### Project Structure
|
||||
|
||||
- [ ] **Create standard directories**:
|
||||
```
|
||||
.
|
||||
├── .claude/ # Claude Code config (optional)
|
||||
├── apps/ # Monorepo applications
|
||||
│ ├── web/ # TanStack Start app
|
||||
│ └── api/ # FastAPI app
|
||||
├── packages/ # Shared packages (monorepo)
|
||||
│ ├── shared-types/ # TypeScript types
|
||||
│ ├── ui/ # Shared UI components
|
||||
│ └── utils/ # Shared utilities
|
||||
├── docs/ # Documentation
|
||||
├── scripts/ # Automation scripts
|
||||
└── .github/ # GitHub workflows
|
||||
└── workflows/
|
||||
```
|
||||
|
||||
- [ ] **Add README.md** with:
|
||||
- [ ] Project description
|
||||
- [ ] Tech stack
|
||||
- [ ] Getting started guide
|
||||
- [ ] Environment variables
|
||||
- [ ] Deployment instructions
|
||||
|
||||
## TanStack Start Setup
|
||||
|
||||
### Installation
|
||||
|
||||
- [ ] **Create Vite project**:
|
||||
```bash
|
||||
npm create vite@latest my-app -- --template react-ts
|
||||
cd my-app
|
||||
```
|
||||
|
||||
- [ ] **Install TanStack Start**:
|
||||
```bash
|
||||
npm install @tanstack/react-router @tanstack/react-query
|
||||
npm install -D @tanstack/router-vite-plugin @tanstack/router-devtools
|
||||
```
|
||||
|
||||
- [ ] **Install dependencies**:
|
||||
```bash
|
||||
npm install zod drizzle-orm @better-auth/react
|
||||
npm install -D drizzle-kit tailwindcss postcss autoprefixer
|
||||
```
|
||||
|
||||
### Configure Vite
|
||||
|
||||
- [ ] **Update vite.config.ts**:
|
||||
```typescript
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { TanStackRouterVite } from '@tanstack/router-vite-plugin'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
TanStackRouterVite()
|
||||
],
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8000',
|
||||
changeOrigin: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Configure TailwindCSS
|
||||
|
||||
- [ ] **Initialize Tailwind**:
|
||||
```bash
|
||||
npx tailwindcss init -p
|
||||
```
|
||||
|
||||
- [ ] **Update tailwind.config.js**:
|
||||
```javascript
|
||||
export default {
|
||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Add Tailwind directives** to `src/index.css`:
|
||||
```css
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
```
|
||||
|
||||
### Setup Drizzle (Database)
|
||||
|
||||
- [ ] **Install Drizzle**:
|
||||
```bash
|
||||
npm install drizzle-orm postgres
|
||||
npm install -D drizzle-kit
|
||||
```
|
||||
|
||||
- [ ] **Create drizzle.config.ts**:
|
||||
```typescript
|
||||
import { defineConfig } from 'drizzle-kit'
|
||||
|
||||
export default defineConfig({
|
||||
schema: './src/db/schema.ts',
|
||||
out: './drizzle',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Create schema file** `src/db/schema.ts`:
|
||||
```typescript
|
||||
import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core'
|
||||
|
||||
export const users = pgTable('users', {
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
email: text('email').notNull().unique(),
|
||||
name: text('name').notNull(),
|
||||
tenantId: uuid('tenant_id').notNull(),
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
updatedAt: timestamp('updated_at').defaultNow()
|
||||
})
|
||||
|
||||
export const tenants = pgTable('tenants', {
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
name: text('name').notNull(),
|
||||
slug: text('slug').notNull().unique(),
|
||||
createdAt: timestamp('created_at').defaultNow()
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Create migration**: `npx drizzle-kit generate`
|
||||
- [ ] **Run migration**: `npx drizzle-kit migrate`
|
||||
|
||||
### Setup Better Auth
|
||||
|
||||
- [ ] **Install Better Auth**:
|
||||
```bash
|
||||
npm install better-auth @better-auth/react
|
||||
```
|
||||
|
||||
- [ ] **Create auth config** `src/lib/auth.ts`:
|
||||
```typescript
|
||||
import { betterAuth } from 'better-auth'
|
||||
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: drizzleAdapter(db, {
|
||||
provider: 'pg'
|
||||
}),
|
||||
emailAndPassword: {
|
||||
enabled: true
|
||||
},
|
||||
socialProviders: {
|
||||
google: {
|
||||
clientId: process.env.GOOGLE_CLIENT_ID!,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET!
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Create auth context** for React
|
||||
- [ ] **Add protected route wrapper**
|
||||
|
||||
### Router Setup
|
||||
|
||||
- [ ] **Create routes directory** `src/routes/`
|
||||
- [ ] **Create index route** `src/routes/index.tsx`
|
||||
- [ ] **Create auth routes** (login, register, logout)
|
||||
- [ ] **Create protected routes** (dashboard, settings)
|
||||
- [ ] **Configure router** in `src/main.tsx`
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- [ ] **Create .env.local**:
|
||||
```
|
||||
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
|
||||
BETTER_AUTH_SECRET=generate-with-openssl-rand-base64-32
|
||||
GOOGLE_CLIENT_ID=your-google-client-id
|
||||
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||
VITE_API_URL=http://localhost:8000
|
||||
```
|
||||
|
||||
- [ ] **Create .env.example** (without secrets)
|
||||
- [ ] **Add to .gitignore**: `.env.local`
|
||||
|
||||
## FastAPI Setup
|
||||
|
||||
### Installation
|
||||
|
||||
- [ ] **Create project directory**:
|
||||
```bash
|
||||
mkdir my-api && cd my-api
|
||||
```
|
||||
|
||||
- [ ] **Setup Python virtual environment**:
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
||||
```
|
||||
|
||||
- [ ] **Install FastAPI and dependencies**:
|
||||
```bash
|
||||
pip install fastapi uvicorn sqlmodel psycopg2-binary pydantic python-dotenv
|
||||
pip install pytest pytest-asyncio httpx # Testing
|
||||
```
|
||||
|
||||
- [ ] **Create requirements.txt**:
|
||||
```bash
|
||||
pip freeze > requirements.txt
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
|
||||
- [ ] **Create standard structure**:
|
||||
```
|
||||
my-api/
|
||||
├── app/
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py # FastAPI app
|
||||
│ ├── models/ # SQLModel models
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── user.py
|
||||
│ │ └── tenant.py
|
||||
│ ├── repositories/ # Data access layer
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── base.py
|
||||
│ │ └── user_repository.py
|
||||
│ ├── services/ # Business logic
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── user_service.py
|
||||
│ ├── api/ # API routes
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── deps.py # Dependencies
|
||||
│ │ └── v1/
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── users.py
|
||||
│ │ └── auth.py
|
||||
│ ├── core/ # Config, security
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── config.py
|
||||
│ │ └── security.py
|
||||
│ └── db/ # Database
|
||||
│ ├── __init__.py
|
||||
│ └── session.py
|
||||
├── tests/
|
||||
│ ├── __init__.py
|
||||
│ ├── conftest.py
|
||||
│ └── test_users.py
|
||||
├── alembic/ # Migrations
|
||||
├── .env
|
||||
└── requirements.txt
|
||||
```
|
||||
|
||||
### Database Setup (SQLModel)
|
||||
|
||||
- [ ] **Create SQLModel models** `app/models/user.py`:
|
||||
```python
|
||||
from sqlmodel import SQLModel, Field
|
||||
from uuid import UUID, uuid4
|
||||
from datetime import datetime
|
||||
|
||||
class User(SQLModel, table=True):
|
||||
__tablename__ = "users"
|
||||
|
||||
id: UUID = Field(default_factory=uuid4, primary_key=True)
|
||||
email: str = Field(unique=True, index=True)
|
||||
name: str
|
||||
tenant_id: UUID = Field(foreign_key="tenants.id", index=True)
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
updated_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
```
|
||||
|
||||
- [ ] **Create database session** `app/db/session.py`:
|
||||
```python
|
||||
from sqlmodel import create_engine, Session
|
||||
from app.core.config import settings
|
||||
|
||||
engine = create_engine(settings.DATABASE_URL, echo=True)
|
||||
|
||||
def get_session():
|
||||
with Session(engine) as session:
|
||||
yield session
|
||||
```
|
||||
|
||||
- [ ] **Create tables**: `SQLModel.metadata.create_all(engine)`
|
||||
|
||||
### Repository Pattern
|
||||
|
||||
- [ ] **Create base repository** `app/repositories/base.py`:
|
||||
```python
|
||||
from typing import Generic, TypeVar, Type, Optional, List
|
||||
from sqlmodel import Session, select
|
||||
from uuid import UUID
|
||||
|
||||
ModelType = TypeVar("ModelType", bound=SQLModel)
|
||||
|
||||
class BaseRepository(Generic[ModelType]):
|
||||
def __init__(self, model: Type[ModelType], session: Session):
|
||||
self.model = model
|
||||
self.session = session
|
||||
|
||||
def get(self, id: UUID) -> Optional[ModelType]:
|
||||
return self.session.get(self.model, id)
|
||||
|
||||
def get_all(self, tenant_id: UUID) -> List[ModelType]:
|
||||
statement = select(self.model).where(
|
||||
self.model.tenant_id == tenant_id
|
||||
)
|
||||
return self.session.exec(statement).all()
|
||||
|
||||
def create(self, obj: ModelType) -> ModelType:
|
||||
self.session.add(obj)
|
||||
self.session.commit()
|
||||
self.session.refresh(obj)
|
||||
return obj
|
||||
```
|
||||
|
||||
- [ ] **Create specific repositories** (UserRepository, TenantRepository)
|
||||
|
||||
### API Routes
|
||||
|
||||
- [ ] **Create main app** `app/main.py`:
|
||||
```python
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from app.api.v1 import users, auth
|
||||
|
||||
app = FastAPI(title="My API", version="1.0.0")
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["http://localhost:3000"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
app.include_router(auth.router, prefix="/api/v1/auth", tags=["auth"])
|
||||
app.include_router(users.router, prefix="/api/v1/users", tags=["users"])
|
||||
|
||||
@app.get("/health")
|
||||
def health_check():
|
||||
return {"status": "healthy"}
|
||||
```
|
||||
|
||||
- [ ] **Create route handlers** `app/api/v1/users.py`
|
||||
- [ ] **Add dependency injection** for tenant_id, user auth
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- [ ] **Create .env**:
|
||||
```
|
||||
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
|
||||
SECRET_KEY=generate-with-openssl-rand-hex-32
|
||||
ALGORITHM=HS256
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||
CORS_ORIGINS=http://localhost:3000
|
||||
```
|
||||
|
||||
- [ ] **Create config** `app/core/config.py`:
|
||||
```python
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
class Settings(BaseSettings):
|
||||
DATABASE_URL: str
|
||||
SECRET_KEY: str
|
||||
ALGORITHM: str = "HS256"
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
|
||||
settings = Settings()
|
||||
```
|
||||
|
||||
## Testing Setup
|
||||
|
||||
### TypeScript/Vitest (Frontend)
|
||||
|
||||
- [ ] **Install Vitest**:
|
||||
```bash
|
||||
npm install -D vitest @vitest/ui @testing-library/react @testing-library/jest-dom
|
||||
```
|
||||
|
||||
- [ ] **Create vitest.config.ts**:
|
||||
```typescript
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: './src/test/setup.ts'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Add test script** to package.json: `"test": "vitest"`
|
||||
- [ ] **Create sample test** `src/test/example.test.ts`
|
||||
|
||||
### Pytest (Backend)
|
||||
|
||||
- [ ] **Create conftest.py** with test fixtures:
|
||||
```python
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlmodel import Session, create_engine, SQLModel
|
||||
from app.main import app
|
||||
from app.db.session import get_session
|
||||
|
||||
@pytest.fixture(name="session")
|
||||
def session_fixture():
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
SQLModel.metadata.create_all(engine)
|
||||
with Session(engine) as session:
|
||||
yield session
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def client_fixture(session: Session):
|
||||
def get_session_override():
|
||||
return session
|
||||
app.dependency_overrides[get_session] = get_session_override
|
||||
client = TestClient(app)
|
||||
yield client
|
||||
app.dependency_overrides.clear()
|
||||
```
|
||||
|
||||
- [ ] **Add test script**: `pytest tests/ -v`
|
||||
- [ ] **Create sample test** `tests/test_users.py`
|
||||
|
||||
## Linting & Formatting
|
||||
|
||||
### TypeScript (ESLint + Prettier)
|
||||
|
||||
- [ ] **Install ESLint**:
|
||||
```bash
|
||||
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
||||
```
|
||||
|
||||
- [ ] **Install Prettier**:
|
||||
```bash
|
||||
npm install -D prettier eslint-config-prettier
|
||||
```
|
||||
|
||||
- [ ] **Create .eslintrc.json**
|
||||
- [ ] **Create .prettierrc**
|
||||
- [ ] **Add scripts** to package.json:
|
||||
```json
|
||||
"lint": "eslint src --ext ts,tsx",
|
||||
"format": "prettier --write src"
|
||||
```
|
||||
|
||||
### Python (Ruff + Black)
|
||||
|
||||
- [ ] **Install Ruff and Black**:
|
||||
```bash
|
||||
pip install ruff black
|
||||
```
|
||||
|
||||
- [ ] **Create pyproject.toml**:
|
||||
```toml
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
select = ["E", "F", "I"]
|
||||
```
|
||||
|
||||
- [ ] **Add to requirements.txt** (dev dependencies)
|
||||
|
||||
## CI/CD Setup
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
- [ ] **Create workflow** `.github/workflows/ci.yml`:
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev]
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
|
||||
jobs:
|
||||
test-frontend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20'
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm test
|
||||
- run: npm run build
|
||||
|
||||
test-backend:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- run: pip install -r requirements.txt
|
||||
- run: pytest tests/ -v
|
||||
```
|
||||
|
||||
- [ ] **Add deployment workflow** (Vercel, Railway, AWS)
|
||||
|
||||
## Database Migrations
|
||||
|
||||
- [ ] **Setup Drizzle migrations** (TanStack Start):
|
||||
- [ ] `npx drizzle-kit generate` to create migrations
|
||||
- [ ] `npx drizzle-kit migrate` to apply migrations
|
||||
|
||||
- [ ] **Setup Alembic** (FastAPI):
|
||||
```bash
|
||||
pip install alembic
|
||||
alembic init alembic
|
||||
```
|
||||
- [ ] Configure alembic.ini with DATABASE_URL
|
||||
- [ ] Create migration: `alembic revision --autogenerate -m "message"`
|
||||
- [ ] Apply migration: `alembic upgrade head`
|
||||
|
||||
## Secrets Management
|
||||
|
||||
- [ ] **Choose secrets manager**:
|
||||
- [ ] Doppler (recommended for Grey Haven)
|
||||
- [ ] AWS Secrets Manager
|
||||
- [ ] Environment variables (for local dev only)
|
||||
|
||||
- [ ] **Install Doppler CLI** (if using Doppler):
|
||||
```bash
|
||||
# Install: https://docs.doppler.com/docs/install-cli
|
||||
doppler login
|
||||
doppler setup
|
||||
```
|
||||
|
||||
- [ ] **Never commit secrets** to git
|
||||
- [ ] **Use .env.example** for documentation
|
||||
|
||||
## Deployment
|
||||
|
||||
### Vercel (TanStack Start)
|
||||
|
||||
- [ ] **Install Vercel CLI**: `npm i -g vercel`
|
||||
- [ ] **Connect to Vercel**: `vercel link`
|
||||
- [ ] **Configure environment variables** in Vercel dashboard
|
||||
- [ ] **Deploy**: `vercel --prod`
|
||||
- [ ] **Setup custom domain** (if needed)
|
||||
|
||||
### Railway (FastAPI)
|
||||
|
||||
- [ ] **Install Railway CLI**: `npm i -g @railway/cli`
|
||||
- [ ] **Login**: `railway login`
|
||||
- [ ] **Initialize**: `railway init`
|
||||
- [ ] **Add environment variables**: `railway variables`
|
||||
- [ ] **Deploy**: `railway up`
|
||||
|
||||
## Multi-Tenant Configuration
|
||||
|
||||
- [ ] **Add tenant_id** to all relevant tables
|
||||
- [ ] **Create RLS policies** (if using PostgreSQL RLS)
|
||||
- [ ] **Repository pattern** enforces tenant filtering
|
||||
- [ ] **Subdomain routing** (if applicable):
|
||||
- [ ] tenant1.myapp.com → tenant_id = uuid1
|
||||
- [ ] tenant2.myapp.com → tenant_id = uuid2
|
||||
|
||||
- [ ] **Tenant signup flow**:
|
||||
- [ ] Create tenant record
|
||||
- [ ] Create owner user
|
||||
- [ ] Associate user with tenant
|
||||
- [ ] Generate invitation links
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
- [ ] **Setup error tracking** (Sentry, Datadog)
|
||||
- [ ] **Add structured logging** (Pino for Node, structlog for Python)
|
||||
- [ ] **Setup metrics** (Prometheus, Datadog)
|
||||
- [ ] **Create health check endpoint** (`/health`)
|
||||
- [ ] **Setup uptime monitoring** (Pingdom, UptimeRobot)
|
||||
|
||||
## Documentation
|
||||
|
||||
- [ ] **README.md** with setup instructions
|
||||
- [ ] **API documentation** (auto-generated with FastAPI `/docs`)
|
||||
- [ ] **Architecture diagram** (optional, but recommended)
|
||||
- [ ] **Environment variables** documented in .env.example
|
||||
- [ ] **Contributing guide** (if open-source or team project)
|
||||
|
||||
## Scoring
|
||||
|
||||
- **80+ items checked**: Excellent - Production-ready setup ✅
|
||||
- **60-79 items**: Good - Most setup complete ⚠️
|
||||
- **40-59 items**: Fair - Missing important pieces 🔴
|
||||
- **<40 items**: Poor - Not ready for development ❌
|
||||
|
||||
## Priority Items
|
||||
|
||||
Complete these first:
|
||||
1. **Repository setup** - Git, structure, README
|
||||
2. **Database schema** - Models, migrations
|
||||
3. **Authentication** - Better Auth, protected routes
|
||||
4. **Testing setup** - Vitest, pytest
|
||||
5. **CI/CD** - GitHub Actions, deployment
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
❌ **Don't:**
|
||||
- Commit .env files (use .env.example instead)
|
||||
- Skip testing setup (add it from day one)
|
||||
- Ignore linting (consistent code quality matters)
|
||||
- Deploy without health checks
|
||||
- Skip multi-tenant isolation (add tenant_id early)
|
||||
|
||||
✅ **Do:**
|
||||
- Use repository pattern for data access
|
||||
- Set up CI/CD early (automate testing)
|
||||
- Document environment variables
|
||||
- Test authentication thoroughly
|
||||
- Plan for scale (database indexes, caching)
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [TanStack Start Documentation](https://tanstack.com/start)
|
||||
- [FastAPI Documentation](https://fastapi.tiangolo.com)
|
||||
- [Better Auth Documentation](https://better-auth.com)
|
||||
- [Drizzle ORM Documentation](https://orm.drizzle.team)
|
||||
- [project-scaffolding skill](../SKILL.md)
|
||||
|
||||
---
|
||||
|
||||
**Total Items**: 130+ setup checks
|
||||
**Critical Items**: Repository, Database, Auth, Testing, Deployment
|
||||
**Coverage**: TanStack Start, FastAPI, Multi-tenant, Testing, CI/CD
|
||||
**Last Updated**: 2025-11-10
|
||||
Reference in New Issue
Block a user