Scaffold a New Project
You create the full directory structure and configuration files for a new project.
Process
Step 1: Gather Project Details
If $ARGUMENTS provides a project name, use it. Otherwise ask:
- "What should the project be called?" (used for directory name and package.json)
- "Where should I create it?" (default: current directory)
Read ${CLAUDE_SKILL_DIR}/../../imp_doc/getting-started/setup.md for detailed setup instructions and best practices.
Step 2: Create Directory Structure
<project-name>/
├── trigger/ — Trigger.dev task definitions
├── src/
│ ├── clients/ — API clients with rate limiting
│ ├── db/
│ │ └── schema/ — Drizzle ORM table definitions
│ └── lib/ — Utilities (rate-limiter, dedup, config)
├── scripts/ — Manual trigger and utility scripts
├── server/ — Data viewer server (optional)
├── tests/
│ ├── unit/ — Unit tests
│ └── integration/ — Integration tests
├── docs/ — Architecture docs and learnings
└── baml_src/ — BAML schema definitions (if using LLM calls)
Step 3: Generate package.json
Create package.json with:
{
"name": "<project-name>",
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "npx trigger.dev@4.3.3 dev",
"deploy": "npx trigger.dev@4.3.3 deploy --env prod",
"test": "vitest run",
"test:watch": "vitest",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:push": "NODE_TLS_REJECT_UNAUTHORIZED=0 drizzle-kit push",
"db:studio": "NODE_TLS_REJECT_UNAUTHORIZED=0 drizzle-kit studio",
"server": "tsx server/index.ts",
"server:dev": "tsx --watch server/index.ts"
},
"dependencies": {
"@trigger.dev/sdk": "4.3.3",
"drizzle-orm": "^0.39.0",
"pg": "^8.13.0",
"zod": "^3.24.0",
"hono": "^4.6.0"
},
"devDependencies": {
"@trigger.dev/build": "4.3.3",
"drizzle-kit": "^0.30.0",
"tsx": "^4.19.0",
"typescript": "^5.7.0",
"vitest": "^3.0.0",
"@types/pg": "^8.11.0",
"@types/node": "^22.0.0"
}
}
Step 4: Generate TypeScript Config
Create tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src/**/*", "trigger/**/*", "server/**/*", "scripts/**/*"],
"exclude": ["node_modules", "dist"]
}
Step 5: Copy Template Files
Copy from ${CLAUDE_SKILL_DIR}/../../templates/:
| Template | Destination | Purpose |
|---|---|---|
drizzle-schema.ts |
src/db/schema/index.ts |
Base table definitions |
pipeline-config.ts |
src/lib/pipeline-config.ts |
Rate limits, batch sizes, convergence |
trigger-config.ts |
trigger.config.ts |
Trigger.dev project configuration |
base-api-client.ts |
src/clients/base-client.ts |
API client with rate limiting and retry |
After copying, replace <PROJECT_ID> placeholders in trigger.config.ts with the project name.
Step 6: Generate .env.example
# Database (PostgreSQL)
DATABASE_URL=postgresql://<USER>:<PASSWORD>@<HOST>:<PORT>/<DATABASE>?sslmode=require
# Trigger.dev
TRIGGER_SECRET_KEY=<YOUR_TRIGGER_SECRET_KEY>
TRIGGER_API_URL=https://api.trigger.dev
# Observability (optional — Axiom)
AXIOM_API_TOKEN=<YOUR_AXIOM_API_TOKEN>
AXIOM_DATASET=<YOUR_DATASET_NAME>
# Add API keys for your data sources below:
# RAPIDAPI_KEY=<YOUR_RAPIDAPI_KEY>
# LLM_API_KEY=<YOUR_LLM_API_KEY>
Step 7: Generate drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: "./src/db/schema/index.ts",
out: "./drizzle",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
ssl: { rejectUnauthorized: false },
},
});
Step 8: Initialize Git
git init
Create .gitignore:
node_modules/
dist/
.env
*.log
drizzle/
.trigger/
Step 9: Report
Project "<project-name>" scaffolded:
src/db/schema/index.ts — Drizzle schema (base tables)
src/lib/pipeline-config.ts — Rate limits, batch sizes, config
src/clients/base-client.ts — API client template
trigger.config.ts — Trigger.dev configuration
tsconfig.json — TypeScript config
package.json — Dependencies
drizzle.config.ts — Drizzle Kit config
.env.example — Environment variables template
.gitignore — Git ignore rules
Next steps:
1. cp .env.example .env — fill in your secrets
2. npm install — install dependencies
3. /scaffold-client <api> — add your first API client
4. /scaffold-task <task> — add your first background task
Step 10: Record Learnings
Reflect on the scaffolding process. If you encountered any of the following, record them to .outbound-builder-plugin-memory.json:
- Errors or workarounds (e.g., dependency conflicts, config issues)
- Non-obvious behaviors (e.g., a template needed unexpected modifications)
- API quirks or platform-specific gotchas
- Schema decisions that differed from the template defaults
For each learning:
- Determine the category:
error-fix,api-quirk,schema-pattern,config-gotcha,build-pattern, ordomain-insight - Generate a deterministic ID:
mem-+ first 8 chars of MD5 hash ofcategory:title(use python3) - Read
.outbound-builder-plugin-memory.json(create with{"version":1,"entries":[],"proven_patterns":[]}if missing) - Dedup by ID -- if the same ID exists, increment
success_countand updatedate - Otherwise append a new entry with
success_count: 1,source: "scaffold", andcontext.stage: "scaffold-project" - Rebuild
proven_patternsfrom entries withsuccess_count >= 2 - Write the file
Skip this step if nothing noteworthy happened during scaffolding.
Rules
- Never include real secrets — use
<YOUR_*>placeholders in .env.example - Pin Trigger.dev CLI and SDK versions to match (4.3.3)
- Always set
ssl: { rejectUnauthorized: false }for cloud-hosted PostgreSQL - Template files should be copied, not symlinked
- The project must work with
npm install && npm run devafter filling in .env