Project Scaffolding

50 min intermediate Lesson 6

Learning Outcomes

  • Generate complete project directory structures from natural language descriptions
  • Scaffold framework-specific projects (React, Express, Flask, etc.) with best practices
  • Create configuration files (ESLint, Prettier, TypeScript, Docker) with appropriate settings
  • Customize generated scaffolds to match team conventions and preferences
  • Use templates and existing projects as references for consistent scaffolding

Lesson Plan

Segment Duration Topic
Intro 3 min Scaffolding vs manual setup — why use Codex for this
Demo 1 10 min Scaffolding a complete Node.js API from scratch
Demo 2 8 min Framework-specific scaffolding (React + TypeScript)
Explain 5 min Configuration file generation strategies
Demo 3 8 min Docker + CI/CD config generation
Demo 4 8 min Customizing scaffolds with team conventions
Explain 4 min Using existing projects as templates
Wrap-up 4 min Scaffolding workflow best practices

Before You Begin

Pre-work:

Shopping List:

  • Codex CLI installed and configured
  • An empty project directory (we'll build from scratch)
  • Node.js or Python installed (for verifying generated projects)
  • Docker installed (optional, for container-related exercises)

1 Full Project Scaffolding

Codex CLI can generate an entire project structure from a single detailed prompt. The key is being explicit about what you need.

Starting from an empty directory:

mkdir ~/projects/my-new-api && cd ~/projects/my-new-api
git init
codex
mkdir %USERPROFILE%\projects\my-new-api && cd %USERPROFILE%\projects\my-new-api
git init
codex

A comprehensive scaffolding prompt:

> Scaffold a Node.js REST API project with this structure:
>
> - src/
>   - controllers/ (user and product controllers)
>   - models/ (User and Product with Mongoose schemas)
>   - routes/ (user and product routes)
>   - middleware/ (auth, error-handler, rate-limiter)
>   - config/ (database, environment variables)
>   - utils/ (logger, response helpers)
> - tests/ (mirrors src/ structure)
> - package.json (with express, mongoose, dotenv, jest)
> - .env.example
> - .gitignore (Node.js appropriate)
> - README.md (basic project documentation)
>
> Use ES modules (import/export), include JSDoc comments,
> and follow RESTful naming conventions.

Codex will create files one by one. In untrusted policy, you approve each. In on-request policy, they're created automatically.

What makes a good scaffolding prompt:

Include Why
Directory structure Removes ambiguity about file organization
Package names Gets the right dependencies from the start
Module system (ESM/CJS) Prevents inconsistency across files
Naming conventions Ensures consistency (camelCase, kebab-case, etc.)
Language features TypeScript vs JavaScript, Python version, etc.
TIP
Tip
For large scaffolds (20+ files), use full-auto or on-request policy. Approving each file individually in a 25-file project gets tedious. Just make sure you review the final result with git diff.
WARNING
Watch Out
Generated package.json files may reference outdated package versions. After scaffolding, run your package manager to install and check for version conflicts.

2 Framework-Specific Scaffolding

Different frameworks have specific conventions and required configurations. Codex knows these patterns and can generate framework-idiomatic code.

React with TypeScript:

> Scaffold a React project with TypeScript. Don't use create-react-app.
> Set up Vite as the bundler. Include:
> - src/components/ with a Header, Footer, and Layout component
> - src/pages/ with Home and About pages
> - src/hooks/ with a useLocalStorage custom hook
> - src/types/ with shared TypeScript interfaces
> - Vite config with path aliases (@ → src/)
> - tsconfig.json with strict mode
> - ESLint + Prettier configs for React/TS

Flask API:

> Scaffold a Flask REST API with:
> - app/ package with __init__.py (app factory pattern)
> - app/routes/ with auth.py and users.py blueprints
> - app/models/ with User model (SQLAlchemy)
> - app/schemas/ with Marshmallow schemas for validation
> - config.py with environment-based configuration
> - requirements.txt with Flask, SQLAlchemy, Marshmallow
> - tests/ with conftest.py and pytest fixtures
> - Makefile with common commands (run, test, lint)

Express + TypeScript:

> Scaffold an Express.js API in TypeScript with:
> - Strict tsconfig
> - src/routes, controllers, services layers
> - Dependency injection pattern
> - Request validation with Zod
> - Error handling middleware with typed errors
> - Jest config for TypeScript tests
> - nodemon config for development

Key framework patterns Codex handles well:

Framework Patterns Codex Knows
React Hooks, context, component composition, routing
Next.js App router, server components, API routes
Express Middleware chain, router separation, error handling
Flask Blueprints, app factory, extensions
Django Apps, models, views, serializers, URL routing
FastAPI Pydantic models, dependency injection, routers
NOTE
How It Works
Codex has been trained on millions of open-source projects using these frameworks. It generates code that follows community conventions and official documentation patterns.

3 Configuration File Generation

Configuration files are often the most tedious part of project setup. Codex can generate them with appropriate defaults and comments explaining each option.

TypeScript configuration:

> Create a tsconfig.json for a Node.js 20 backend project using
> ES modules. Enable strict mode, path aliases, and generate
> source maps. Target ES2022.
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "sourceMap": true,
    "declaration": true,
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

ESLint + Prettier:

> Create ESLint and Prettier configs that work together for a
> TypeScript React project. Use flat config format for ESLint.
> Enforce consistent semicolons, double quotes, and 2-space indent.

Docker configuration:

> Create a Dockerfile for a Node.js 20 application with:
> - Multi-stage build (builder + production)
> - Non-root user for security
> - .dockerignore file
> - docker-compose.yml with app + PostgreSQL + Redis
> - Health check endpoint configuration

CI/CD configuration:

> Create a GitHub Actions workflow that:
> - Runs on push to main and pull requests
> - Installs Node.js 20
> - Caches node_modules
> - Runs lint, type-check, and tests in parallel
> - Builds the project
> - Only deploys on push to main (not on PRs)

Environment configuration:

> Create a .env.example file with all the environment variables
> this project needs, based on reading the config files. Add
> comments explaining each variable. Don't include actual secrets.
TIP
Tip
Ask Codex to add comments in configuration files explaining WHY each option is set. Future developers (including future you) will appreciate knowing the reasoning.
WARNING
Watch Out
Always verify generated CI/CD configs before committing. A misconfigured workflow might expose secrets or run on the wrong triggers. Review security-sensitive sections manually.

4 Customizing Scaffolds with Conventions

Generic scaffolding is useful, but most teams have specific conventions. You can teach Codex your preferences within a prompt.

Embedding conventions in your prompt:

> Scaffold a new microservice following our team conventions:
>
> Conventions:
> - File naming: kebab-case (user-controller.ts, not userController.ts)
> - Exports: named exports only (no default exports)
> - Error handling: all errors use our AppError class
> - Logging: use structured JSON logging with pino
> - Testing: colocate tests (user.service.ts + user.service.test.ts)
> - No classes: use functions and closures for everything
>
> The microservice handles payment processing with Stripe.

Using an existing file as a template:

> Look at src/services/user.service.ts as a reference for our
> service pattern. Create a new product.service.ts following
> the exact same structure, error handling approach, and
> documentation style.

Using a conventions file:

Create a .codex-conventions or CONVENTIONS.md in your project:

> Read CONVENTIONS.md and then scaffold a new module for
> inventory management following all the rules described there.

Customizing after generation:

> The scaffold looks good, but make these adjustments:
> 1. Rename all controller files from *.controller.ts to *.ctrl.ts
> 2. Add our standard license header to every file
> 3. Use our team's database connection helper instead of direct
>    mongoose.connect calls

Company boilerplate:

> We start every service with this boilerplate structure. Generate
> it for a new "notifications" service:
>
> - health check endpoint at /health
> - metrics endpoint at /metrics
> - graceful shutdown handler
> - structured request logging middleware
> - correlation ID propagation
> - OpenAPI spec file
NOTE
How It Works
Codex can read existing files in your project and mimic their patterns. This is more effective than describing conventions in words — show, don't just tell.
TIP
Tip
If you scaffold new services frequently, keep a SCAFFOLD_TEMPLATE.md in your repo that describes your team's conventions. Reference it every time: 'Read SCAFFOLD_TEMPLATE.md and create a new auth service'.

5 Post-Scaffolding Verification

After scaffolding, you need to verify that the generated project actually works. Codex can help with this too.

Step 1: Check for completeness

> Review the project structure we just created. Are there any
> missing files that would be needed to run this project?
> (Missing imports, undefined references, etc.)

Step 2: Verify imports and dependencies

> Check all import statements across the project. Are there any
> imports that reference files that don't exist or exports that
> aren't defined?

Step 3: Install and test

# For Node.js projects
codex "Run npm install and report any peer dependency warnings"

# For Python projects
codex "Create a virtual environment, install requirements.txt, and verify imports"
# For Node.js projects
codex "Run npm install and report any peer dependency warnings"

# For Python projects
codex "Create a virtual environment, install requirements.txt, and verify imports"

Step 4: Run the linter

> Run the linter we configured and fix any issues it reports.

Step 5: Run initial tests

> Run the test suite. If there are failures from the scaffold
> (missing implementations, etc.), that's expected — but there
> shouldn't be import errors or configuration issues.

Step 6: Commit the scaffold

> Everything looks good. Stage all files and create an initial
> commit with the message "feat: scaffold payment service"

Common post-scaffold issues:

Issue Solution
Missing dependency in package.json Ask Codex to scan imports and update package.json
Circular imports Ask Codex to identify and resolve import cycles
Incorrect path aliases Verify tsconfig paths match actual directory structure
Wrong Node.js version Check engines field in package.json
Test config doesn't match structure Verify jest.config or pytest.ini matches file layout
WARNING
Watch Out
Scaffolds that include dependency installation (npm install, pip install) require network access. You'll need auto-edit or never policy, or approve the install commands manually.
TIP
Tip
After scaffolding, commit immediately before making any manual changes. This gives you a clean snapshot of the generated code that you can reference or revert to.

Questions & Answers

Q: How does Codex scaffolding compare to tools like create-react-app or express-generator?
Framework generators create a fixed, opinionated structure. Codex is flexible — you describe exactly what you want, and it generates a custom structure. Codex is better for non-standard setups, team-specific conventions, or combining multiple tools. Framework generators are faster for standard setups and guarantee compatibility.
Q: Can Codex scaffold projects in languages or frameworks it hasn't seen much of?
Codex works best with popular languages and frameworks (JavaScript, Python, Go, Rust, Java). For niche frameworks or very new tools, the scaffolding quality may be lower. In those cases, provide more detailed instructions or reference existing example projects.
Q: Will the generated code have security vulnerabilities?
Generated code may not follow all security best practices by default. Always review security-sensitive parts (authentication, input validation, secret handling) manually. Ask Codex specifically to "follow OWASP security guidelines" or "add input validation and sanitization" if security is a concern.
Q: How many files can Codex generate in one session?
There's no strict limit, but very large scaffolds (50+ files) may hit context limits or become slow. For large projects, scaffold in phases: core structure first, then add modules one at a time. Each phase should be 10-20 files maximum for best results.

Key Takeaways

  1. Be explicit in scaffolding prompts: Specify directory structure, packages, module system, and naming conventions
  2. Framework patterns work well: Codex knows standard patterns for popular frameworks — leverage that knowledge
  3. Configuration files save the most time: Let Codex generate tsconfig, ESLint, Docker, and CI/CD configs with comments
  4. Reference existing code: Point Codex at existing files as templates for consistent scaffolding
  5. Verify after generating: Check imports, run the linter, install dependencies, and run tests
  6. Commit the scaffold immediately: Keep a clean snapshot before any manual modifications

Next Steps: In Lesson 7 — Testing with Codex, you'll learn how to generate comprehensive test suites and adopt TDD workflows with Codex CLI.