Stacks & DNA DARE¶
DARE generates greenfield projects from a catalog of 11 stacks — 7 backend and 4 MCP servers. Each generator (StackScaffold) is registered lazily in the registry (packages/cli/src/stacks/registry.ts): the module is only loaded when you choose that stack, keeping dare --help cold and fast.
Regardless of the stack, every generator delivers the same invariant set of 7 artifacts — the DNA DARE — validated in a test (dna.spec.ts).
The 11 stacks¶
Backend (7)¶
| Stack | Status | Framework | Main libs |
|---|---|---|---|
ruby-rails-8 |
stable | Rails 8 | rswag (OpenAPI), Action Cable (WS), RFC 7807 Problem Details, ActiveRecord, rake dare:metrics |
node-nestjs |
stable | NestJS 10 | Prisma + Postgres, JWT auth, Swagger at /openapi.json, Throttler (rate limit), class-validator + class-transformer, Pino |
python-fastapi |
stable | FastAPI | Pydantic v2, SQLAlchemy 2.0 + Alembic, slowapi (rate limit), uvicorn[standard] |
php-laravel |
stable | Laravel 11 | Sanctum + FormRequest, Eloquent, Reverb (WS) + Pail, ThrottleRequests, l5-swagger, LlmProvider (Dummy + OpenAI), Pest |
rust-axum |
stable | Axum 0.7 | Tokio, tower-http (CORS/trace) + tower-governor (rate limit), utoipa (OpenAPI), sqlx + Postgres, axum::extract::ws |
go-gin |
stable | Gin | sqlc + pgx, golang-jwt + bcrypt, gorilla/websocket, golang.org/x/time/rate, swag (OpenAPI) |
go-stdlib |
stable | net/http 1.22 ServeMux | pgx + sqlc-compatible schema, golang-jwt + bcrypt, golang.org/x/time/rate, github.com/coder/websocket (minimal-deps philosophy) |
MCP — Model Context Protocol (4)¶
| Stack | Status | SDK / Runtime | Transports |
|---|---|---|---|
mcp-node-ts |
stable | @modelcontextprotocol/sdk (TypeScript) |
stdio · sse · http (Streamable HTTP) |
mcp-python |
stable | mcp[cli] (FastMCP, Python 3.11+) |
stdio · sse · http (via uvicorn) |
mcp-rust |
beta | rmcp (official Rust SDK) |
stdio · sse · http (via axum) |
mcp-go |
beta | github.com/mark3labs/mcp-go (community SDK) |
stdio · sse · http |
MCP transport
All three transports come together in every MCP generator. The effective transport is chosen at runtime by the --transport flag or the MCP_TRANSPORT env; the generator pre-selects the user's default (opts.mcp.transport) so that start "just works".
Registry ordering
list() sorts by category (backend before mcp) and then by id, deterministically. resolve(id) does the lazy import and memoizes it; an invalid id raises UnknownStackError with the list of available ids.
The DNA DARE — 7 invariant artifacts¶
Every StackScaffold calls emitDefaults() early in generate() to satisfy the DNA contract and then overrides each artifact with the stack-specific version. The DareDnaArtifact type and the DARE_DNA constant (in stacks/types.ts) list the 7; the dna.spec.ts test fails if any is missing.
| # | Artifact (DareDnaArtifact) |
What it is | How it is guaranteed |
|---|---|---|---|
| 1 | Layered Design | Separation into layers (handlers/controllers → services → repositories → models) | Structure emitted by each generator (common to all 11 stacks). |
| 2 | llms.txt |
Manifest for AI agents (setup, commands, endpoints) | emit('llms-txt') → llms.txt. |
| 3 | OpenAPI | HTTP contract (openapi.json / /openapi.json at runtime) |
emit('openapi') → openapi.json (3.1.0 skeleton; generator overrides). |
| 4 | --json |
JSON output flag in the generated CLI | Declarative: the generator declares it via dnaEmitted; validated by a structural grep over the generated source. |
| 5 | Rate limit | Per-minute limit middleware, driven by env (RATE_LIMIT_PER_MIN) |
Declarative: same as --json; validated by grep. |
| 6 | .env.example without secrets |
Environment example without real credentials | emit('env-example') validates each value against SECRET_PATTERNS (base64 ≥40, hex ≥32, PEM, sk-…, AKIA…) and throws EnvSecretError if it matches. |
| 7 | .dare/skills.yml |
Registry of the stack skill for the IDE | emit('skills-yml') maps stack → skill (e.g.: skill-nestjs-api, skill-fastapi-api; all MCP → skill-mcp-server). |
| — | .github/workflows/dare-ci.yml |
CI (audit + lint + test) | emit('github-ci') → workflow with audit/lint/test jobs (per-ecosystem placeholders). |
Declarative vs. emitted
Five artifacts are emitted to disk (llms-txt, openapi, env-example, skills-yml, github-ci). Two — cli-json-flag (the --json flag) and rate-limit — are declarative: the generator returns that it satisfied them in dnaEmitted, and dna.spec.ts confirms via grep over the generated code. emitDefaults() returns the complete DARE_DNA set (all 7).
Secret protection in .env.example¶
validateEnvExample() walks the file line by line, ignores comments/empty lines, and rejects any value that matches a secret pattern:
export const SECRET_PATTERNS: ReadonlyArray<RegExp> = [
/[A-Za-z0-9+/]{40,}={0,2}/, // base64 ≥40 chars (provável chave)
/[a-f0-9]{32,}/, // hex ≥32 chars (hash / chave)
/-----BEGIN [A-Z ]+ PRIVATE KEY-----/, // bloco PEM
/sk-[A-Za-z0-9]{40,}/, // chave estilo OpenAI
/AKIA[0-9A-Z]{16}/, // AWS access key
];
Placeholder values (replace-me-in-prod, postgresql://user:pass@localhost...) pass; real secrets make the build fail with EnvSecretError pointing to the line.
Toolchain (auto / native / docker)¶
Every generator receives a ScaffoldOpts.toolchain of type ToolchainMode:
| Mode | Behavior |
|---|---|
native |
Uses the tools installed locally (Node, Python, Rust, Go, etc.). |
docker |
Packages the toolchain in a container — without depending on what is on the machine. |
auto |
Decides between native and docker according to the environment. |
Each generate() also receives: dir (target directory, already created and empty), projectName (kebab-case slug), features (subset of DARE_DNA, default = the 7), optional llm (providers), optional realtime (ws/sse), mcp (transport — required for the mcp category) and isMonorepo. It returns ScaffoldResult: filesWritten, postInstallSteps (commands to run next), warnings and dnaEmitted (the satisfied DNA artifacts — checked by dna.spec.ts).
flowchart TD
G[generate(opts)] --> E[emitDefaults()<br/>7 DNA artifacts]
E --> O[stack-specific overlay<br/>real OpenAPI, llms.txt, etc.]
O --> R[ScaffoldResult<br/>filesWritten · postInstallSteps · dnaEmitted]
R --> V[dna.spec.ts validates the 7]