Skip to content

Project Setup & Initialization

It is Monday morning. Your product manager just described a new microservice: “We need a REST API that handles user preferences, stores them in PostgreSQL, with authentication, rate limiting, and structured logging.” The traditional answer is a day of wiring boilerplate before you write a line of business logic. With Claude Code you describe the service, it scaffolds, and you spend your time verifying instead of typing.

The trick is not the generation — any tool can emit a folder tree. The trick is guiding the first prompt so you get production scaffolding, then running a tight loop of “build, verify it works, course-correct” so you catch the gaps before they compound.

  • A repeatable bootstrap loop: describe, generate, verify, course-correct
  • A tight CLAUDE.md that survives across sessions without getting ignored
  • Copy-paste prompts for a Node/Express API, a TypeScript migration, and CI/CD setup
  • A real prototyping flow using --dangerously-skip-permissions instead of made-up “modes”

The bootstrap that works is not “type one wish and walk away.” It is four moves: describe with specifics, let Claude scaffold, then immediately make it prove the scaffold runs.

  1. Create the project directory and start Claude Code

    Terminal window
    mkdir user-preferences-api && cd user-preferences-api
    git init
    claude

    git init first matters: Claude Code is git-aware and commits at logical checkpoints, so you can rewind if a scaffolding step goes sideways.

  2. Describe the service with enough specificity to avoid a generic template

  3. Make Claude prove the scaffold runs before you build on it

    This is the step that separates a real workflow from a brochure. Do not trust the tree dump — run it.

    Start Postgres with docker compose, run the migrations, then start the
    dev server and confirm /health returns 200. Run the linter and the test
    suite. Paste any errors and fix them until everything is green.

    Claude is at its best with a real error in front of it. When a dependency version conflicts or a migration fails, the actual stderr is what lets it course-correct precisely instead of guessing.

  4. Course-correct one real gap

    Generated scaffolds almost always miss something specific to how you work. Name it explicitly rather than re-describing the whole project:

    The CRUD handlers call Drizzle directly. Extract a preferences service
    layer between the routes and the DB so business logic is testable in
    isolation, and move the Zod schemas into src/schemas/.

Within a few minutes you have a codebase you have actually run: a service layer, validated routes, migrations that applied, a passing test suite, and a Docker setup you watched start — not a tree you are hoping compiles.

Context is what makes Claude Code effective across sessions. CLAUDE.md is your project’s persistent memory — it survives when the conversation does not.

Run /init inside Claude Code. It reads your package.json, walks the directory structure, detects the test framework, and writes a starter CLAUDE.md. The output is a starting point, not the finished file — the best CLAUDE.md files are pruned hard and refined over time.

# User Preferences API
## Tech Stack
- Node.js 22.x, Express, TypeScript strict
- PostgreSQL 17 via Drizzle ORM
- Redis for rate-limit counters
## Commands
- npm run dev # start dev server on :3000
- npm test # vitest
- npm run migrate # drizzle migrations
- docker compose up
## Conventions
- Service layer between routes and DB; routes stay thin
- Zod validates every request body; never trust client input
- Named exports only; colocate Button.tsx / Button.test.tsx
## Gotchas
- IMPORTANT: never commit .env. Use .env.example.
- Migrations are append-only; use the generator, never hand-edit

You inherit a legacy Express app and need it on TypeScript without a risky big-bang rewrite. The workflow is the same describe-generate-verify loop, applied one phase at a time so the app stays deployable at every step.

  1. Get a phased plan, not a diff

    Analyze this Express app and propose a phased migration to TypeScript
    strict that keeps the service deployable after each phase. Start with
    tsconfig + build wiring and the leaf modules with no internal imports.
  2. Execute phase one and confirm the build still ships

    Implement phase 1: add the TypeScript config and convert the leaf
    modules. Then run the build and the existing test suite and confirm
    both pass before we touch anything else.
  3. Iterate, verifying each phase

    Tests pass. Convert the next layer (the route handlers), add types for
    the external deps they use, and run the suite again. Stop if anything
    breaks.

The discipline is the verify step between phases. Skipping it is how a “gradual” migration quietly accumulates a hundred type errors you discover all at once.

You are in a hackathon. You want to validate an idea in hours, and the permission prompts on every file write are slowing you down. There is no “YOLO mode” in Claude Code — the real mechanism is the --dangerously-skip-permissions flag (or the bypassPermissions permission mode), which skips the approval prompts for the session.

Terminal window
claude --dangerously-skip-permissions

Then give it a scope-limited build prompt:

Bootstrapping a project is one of the few workflows that looks meaningfully different in each tool, so reach for the one that matches how you work.

Open the empty folder, switch the Agent to a strong model (Claude Opus 4.8 for most scaffolds; Claude Fable 5 when building from scratch is the priority and budget is less of a concern), and paste the same scaffold prompt in Agent mode. Cursor proposes the file tree as a diff you accept or reject per file, and its checkpoints let you roll back a bad scaffolding step from the sidebar instead of git reset.

A scaffold that emits config files is not done — you want config that fails loudly on a bad value, and you want to see it fail. Ask for environment-aware config with startup validation, then test the validation by feeding it something broken.

The “then prove it” half is the point. Config validation you have never seen reject anything is config validation you do not actually have.

Two extras cut real time off setup, and both work across Cursor, Claude Code, and Codex:

  • The Postgres MCP server lets Claude introspect your live schema instead of guessing column names while it writes migrations and queries. Add it in Claude Code with claude mcp add --transport stdio postgres -- npx -y @modelcontextprotocol/server-postgres "$DATABASE_URL". The same server config drops into Cursor and Codex.
  • The GitHub MCP server (@modelcontextprotocol/server-github) lets the same session create the repo, push the scaffold, and open the first PR without you leaving the terminal.
  • For one-shot augmentation rather than a persistent connection, an Agent Skill is lighter weight. Browse skills.sh and install with the universal CLI — npx skills add <owner/repo> — which works across Claude Code, Cursor, and Codex. Reach for a skill when you want a single reusable capability (a code-review pass, a deploy recipe); reach for an MCP server when you want a live, stateful tool connection.

Claude emits a generic template instead of what you described. Your prompt was too vague. Add framework versions, the exact directory layout, and your conventions. The specificity you front-load is the course-correcting you avoid later.

The generated project has dependency conflicts. Claude sometimes pulls incompatible versions. This is exactly why the verify step is non-negotiable — “run the dev server and fix any errors” puts the real stderr in front of Claude, and it resolves conflicts well when it can see the actual failure.

/init misses your team’s conventions. It reads code structure, not unwritten rules. Always supplement its output with the things that live only in people’s heads: branch naming, the PR process, deployment steps. Then validate by asking a question only a well-configured CLAUDE.md could answer (“How do I run just the auth unit tests?”).

The scaffold drifts from your prompt over a long session. As context fills, Claude can forget an early instruction (named exports only, no default exports). Re-state the rule in CLAUDE.md so it persists, rather than repeating it in chat each time.

CLAUDE.md gets ignored in later sessions. The file is too long or too vague. Cut it under ~50 lines and make every line specific and actionable. “Write clean code” earns nothing; “Service layer between routes and DB; routes stay thin” earns its place.

You can go from zero to a service you have actually run. Next, learn how Claude Code navigates code you did not write.