Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:29:07 +08:00
commit 8b4a1b1a99
75 changed files with 18583 additions and 0 deletions

View 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

View File

@@ -0,0 +1,272 @@
# Scaffold Quality Checklist
Comprehensive checklist for validating generated scaffolds before delivery.
---
## Configuration Files
### TypeScript Projects
- [ ] **package.json** present with correct project name
- [ ] **tsconfig.json** with strict mode enabled
- [ ] **Scripts** configured (dev, build, test, deploy)
- [ ] **Dependencies** at correct versions
- [ ] **devDependencies** include linting/testing tools
### Python Projects
- [ ] **pyproject.toml** present with project metadata
- [ ] **Dependencies** specified with version ranges
- [ ] **Dev dependencies** include pytest, ruff, mypy
- [ ] **Tool configurations** (ruff, mypy, pytest) configured
### All Projects
- [ ] **.gitignore** includes node_modules, .env, build artifacts
- [ ] **.env.example** provided for environment variables
- [ ] **README.md** with setup instructions
- [ ] **License file** (if applicable)
---
## Source Code Structure
### Directory Organization
- [ ] **src/** directory exists
- [ ] **routes/** for API endpoints or pages
- [ ] **components/** for UI components (frontend)
- [ ] **services/** for business logic
- [ ] **utils/** for helper functions
- [ ] **types/** for TypeScript definitions
### Entry Points
- [ ] **Main file** exists (index.ts, main.py, App.tsx)
- [ ] **Exports** correctly configured
- [ ] **Health check endpoint** implemented
- [ ] **Error handling** middleware included
---
## Code Quality
### TypeScript
- [ ] **Strict mode** enabled in tsconfig.json
- [ ] **Type annotations** on all functions
- [ ] **Interfaces** defined for props/config
- [ ] **ESLint** configuration present
- [ ] **Prettier** configuration present
- [ ] **No `any` types** (except explicit)
### Python
- [ ] **Type hints** on all functions
- [ ] **Pydantic models** for validation
- [ ] **Async/await** used correctly
- [ ] **Docstrings** on public functions
- [ ] **Ruff configuration** present
- [ ] **mypy strict mode** enabled
### All Languages
- [ ] **Consistent naming** (camelCase, snake_case)
- [ ] **No hard-coded secrets** or API keys
- [ ] **Environment variables** used correctly
- [ ] **Error handling** implemented
- [ ] **Logging** configured
---
## Testing
### Test Files
- [ ] **tests/** directory exists
- [ ] **Test files** mirror src/ structure
- [ ] **Test fixtures** configured (conftest.py, setup.ts)
- [ ] **Coverage** configuration present
### Test Quality
- [ ] **Sample tests** included
- [ ] **Tests pass** out of the box
- [ ] **Health check test** present
- [ ] **Test commands** in package.json/pyproject.toml
---
## Deployment
### Cloudflare Workers
- [ ] **wrangler.toml** configured
- [ ] **Database bindings** defined (if D1)
- [ ] **Environment** sections (production, staging)
- [ ] **Secrets** documented in README
### Cloudflare Pages
- [ ] **Build command** configured
- [ ] **Output directory** specified
- [ ] **Environment variables** documented
### Python
- [ ] **Dockerfile** (if containerized)
- [ ] **Requirements** frozen
- [ ] **Database migrations** configured (Alembic)
---
## Documentation
### README.md
- [ ] **Project description** clear
- [ ] **Quick start** instructions
- [ ] **Setup steps** documented
- [ ] **Development** commands listed
- [ ] **Deployment** instructions
- [ ] **Environment variables** documented
- [ ] **API endpoints** listed (if API)
### Additional Docs
- [ ] **Architecture** diagram/description (full-stack)
- [ ] **API documentation** (FastAPI auto-docs, etc.)
- [ ] **Contributing** guidelines (if open source)
---
## Security
### Secrets Management
- [ ] **No secrets** committed to git
- [ ] **.env** in .gitignore
- [ ] **.env.example** provided
- [ ] **Secret management** documented
### Authentication
- [ ] **Auth middleware** included (if applicable)
- [ ] **JWT handling** implemented correctly
- [ ] **CORS** configured properly
### Input Validation
- [ ] **Zod/Pydantic** validation on inputs
- [ ] **SQL injection** prevention (parameterized queries)
- [ ] **XSS prevention** (sanitized outputs)
---
## Dependencies
### Version Management
- [ ] **Package versions** pinned or ranged appropriately
- [ ] **No deprecated** packages
- [ ] **Security** vulnerabilities checked
- [ ] **License** compatibility verified
### Peer Dependencies
- [ ] **React version** compatible (if React)
- [ ] **Node version** specified (engines field)
- [ ] **Python version** specified (requires-python)
---
## CI/CD
### GitHub Actions
- [ ] **.github/workflows/** directory exists
- [ ] **Test workflow** configured
- [ ] **Deploy workflow** configured
- [ ] **Lint workflow** configured
### Workflow Quality
- [ ] **Tests run** on PR
- [ ] **Deployment** on main branch
- [ ] **Secrets** properly configured
- [ ] **Environment variables** set
---
## User Experience
### Developer Experience
- [ ] **Setup time** < 5 minutes
- [ ] **All commands work** (dev, test, build)
- [ ] **Hot reload** functional
- [ ] **Error messages** helpful
### Production Readiness
- [ ] **Health endpoint** returns 200
- [ ] **Error handling** doesn't expose internals
- [ ] **Logging** configured
- [ ] **Monitoring** hooks present
---
## Checklist Summary
### Must Have (Critical)
- ✅ Configuration files present and correct
- ✅ Source code structure follows Grey Haven conventions
- ✅ Tests included and passing
- ✅ README with setup instructions
- ✅ No secrets committed
### Should Have (Important)
- ✅ Type safety (TypeScript strict, Python type hints)
- ✅ Linting and formatting configured
- ✅ CI/CD pipeline included
- ✅ Health check endpoint
- ✅ Error handling
### Nice to Have (Optional)
- ✅ Architecture documentation
- ✅ API documentation
- ✅ Storybook (components)
- ✅ Database migrations
- ✅ Monitoring setup
---
## Quick Validation Script
```bash
#!/bin/bash
# Quick scaffold validation
echo "Checking scaffold quality..."
# Check files exist
test -f package.json && echo "✅ package.json" || echo "❌ package.json"
test -f README.md && echo "✅ README.md" || echo "✅ README.md"
test -d src && echo "✅ src/" || echo "❌ src/"
test -d tests && echo "✅ tests/" || echo "❌ tests/"
# Check no secrets
! grep -r "api[_-]key" . && echo "✅ No API keys" || echo "⚠️ API key found"
# Install and test
npm install && npm test && echo "✅ Tests pass" || echo "❌ Tests fail"
```
---
**Version**: 1.0
**Last Updated**: 2024-01-15