# Scaffold Project

> Initialize a new project from scratch. Creates directory structure, package.json, TypeScript config, Drizzle schema, Trigger.dev config, and .env.example. Use this to bootstrap a new project.

- Skill: `ankit4479/scaffold-project` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ankit4479/scaffold-project`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ankit4479/scaffold-project/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: ankit4479 (https://skillmd.com/u/ankit4479)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ankit4479/scaffold-project

---


# 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:

```json
{
  "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`:

```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

```env
# 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

```typescript
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

```bash
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:
1. Determine the category: `error-fix`, `api-quirk`, `schema-pattern`, `config-gotcha`, `build-pattern`, or `domain-insight`
2. Generate a deterministic ID: `mem-` + first 8 chars of MD5 hash of `category:title` (use python3)
3. Read `.outbound-builder-plugin-memory.json` (create with `{"version":1,"entries":[],"proven_patterns":[]}` if missing)
4. Dedup by ID -- if the same ID exists, increment `success_count` and update `date`
5. Otherwise append a new entry with `success_count: 1`, `source: "scaffold"`, and `context.stage: "scaffold-project"`
6. Rebuild `proven_patterns` from entries with `success_count >= 2`
7. 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 dev` after filling in .env

