Scaffold a new project with standard directory structure, config files, CI, and quality tooling
Create a complete, standards-compliant project from scratch with all quality tooling configured.
Arguments from command: $ARGUMENTS
Parse the arguments:
python, typescript, or both. Default: pythonIf no argument is provided, ask the user for the project name and stack.
<project-name>/my_api)MyApi~/.cursor/templates/:
pyproject-python.toml (for Python stack)biome.json (for TypeScript stack)tsconfig-strict.json (for TypeScript stack)CONVENTIONS.md (template to customize)cursor-rules-project.mdc (template for project rules)gitlab-ci-snippets.md (for CI reference)<project-name>/
├── src/
│ └── <import_name>/
│ ├── __init__.py
│ ├── py.typed
│ ├── core.py
│ ├── config.py
│ └── exceptions.py
├── tests/
│ ├── __init__.py
│ └── conftest.py
├── pyproject.toml
├── .cursor/
│ └── rules/
│ └── project.mdc
├── CONVENTIONS.md
└── .gitlab-ci.yml
src/<import_name>/__init__.py
"""<project-name> -- <ask user for one-line description>."""
__all__: list[str] = []
src/<import_name>/py.typed — Empty file (PEP 561 marker)
src/<import_name>/core.py
"""Core module for <project-name>."""
src/<import_name>/config.py
"""Configuration models for <project-name>."""
from pydantic import BaseModel
class <PascalName>Config(BaseModel, frozen=True):
"""Configuration for <project-name>.
Attributes:
enabled: Whether the component is enabled.
"""
enabled: bool = True
src/<import_name>/exceptions.py
"""Exception hierarchy for <project-name>."""
class <PascalName>Error(Exception):
"""Base exception for <project-name>."""
tests/__init__.py — Empty file
tests/conftest.py
"""Shared test fixtures for <project-name>."""
pyproject.toml — Use the golden template from ~/.cursor/templates/pyproject-python.toml, replacing:
<package-name> with the project name<package_name> with the import name<description> with the user-provided description.gitlab-ci.yml — Use the library-python-pyright snippet from ~/.cursor/templates/gitlab-ci-snippets.md, replacing <package_name> with the import name
.cursor/rules/project.mdc — Use the template from ~/.cursor/templates/cursor-rules-project.mdc, replacing placeholders
CONVENTIONS.md — Copy from ~/.cursor/templates/CONVENTIONS.md, set the base exception name to <PascalName>Error
<project-name>/
├── src/
│ └── index.ts
├── tests/
│ └── index.test.ts
├── package.json
├── tsconfig.json
├── biome.json
├── .cursor/
│ └── rules/
│ └── project.mdc
├── CONVENTIONS.md
└── .gitlab-ci.yml
src/index.ts
// <project-name> -- <description>
export {}
tests/index.test.ts
import { describe, it, expect } from 'vitest'
describe('<project-name>', () => {
it('should be true', () => {
expect(true).toBe(true)
})
})
package.json — Standard package.json with:
typescript, @biomejs/biome, vitest, @vitest/coverage-v8, knip as devDependenciescheck, typecheck, test, test:coveragetsconfig.json — Copy from ~/.cursor/templates/tsconfig-strict.json
biome.json — Copy from ~/.cursor/templates/biome.json
.cursor/rules/project.mdc — Adapted from template with TypeScript commands
CONVENTIONS.md — Copy from template with TypeScript rules uncommented, Python rules commented out
<project-name>/
├── backend/
│ └── (python structure above)
├── frontend/
│ └── (typescript structure above)
├── .cursor/
│ └── rules/
│ └── project.mdc
└── CONVENTIONS.md
For monorepo, create a root .cursor/rules/project.mdc that references both sub-projects.
After creating all files:
cd <project-name> && uv sync to validate setupuv run ruff check . to verify lint passesuv run pyright src/ to verify type checking passescd <project-name> && npm install to install dependenciesnpx biome check . to verify lint passesnpx tsc --noEmit to verify type checking passesReport success with a summary of created files and any post-scaffold instructions.
/prd for that separatelyCommit the scaffolded project:
chorescaffoldchore(scaffold): create project structure for <project-name>