Scaffold a project
create-daloy is the official project generator. It scaffolds a working DaloyJS app in seconds, no copy-pasting from the docs.
Package link: create-daloy on npm. The generated apps install the framework from @daloyjs/core on npm.
Quick start
The CLI is interactive when arguments are missing. It will ask for a project name, a template, a package manager (skipped for deno-basic), whether to install dependencies, whether to initialize a git repository, and whether to add the GitHub security bundle. The dependency-install prompt defaults to no for pnpm projects so you can review the generated .npmrc and pnpm-workspace.yaml guardrails before the first install. Other package managers default to yes.
- 01Project namemy-api
- 02Templatenode-basic, vercel, ...
- 03Package managerpnpm, npm, yarn, bun
- 04Install deps?--install / --no-install
- 05Init git?--git / --no-git
- 06GitHub security bundle?--with-ci
Non-interactive usage
Flags
--template <name>:node-basic(default),vercel,cloudflare-worker,bun-basic, ordeno-basic.--package-manager <pm>(alias--pm):pnpm,npm,yarn, orbun. Defaults to the package manager that launched the CLI (sonpm create daloypicksnpm), and topnpmwhen it cannot tell.--list-templates: print available templates with descriptions.--install/--no-install: install dependencies after scaffolding. The prompt defaults tonofor pnpm projects andyesfor npm, Yarn, and Bun projects. With--yes(or without a TTY) nothing is installed unless you pass--install.--git/--no-git: initialize a git repository. The prompt defaults toyes. With--yes(or without a TTY) no repository is created unless you pass--git.--minimal: strip the bookstore demo and the auto-mounted/docs+/openapi.jsonAPI docs routes so the scaffold only ships the framework bootstrap and a health route. Useful when you want to start from the smallest possible app.--with-ci/--no-ci: add hardened GitHub Actions, Dependabot, CODEOWNERS,SECURITY.md, and lockfile-source verification. Defaults toyes.--with-deploy/--no-deploy: add or skip the manual-only starter.github/workflows/deploy.yml. Defaults to the same value as--with-ci.--code-owner <owner>: replace the CODEOWNERS placeholder when--with-ciis used, for example@acme/security.--force: overwrite an existing non-empty directory.--yes: accept all defaults. Never prompt.
Missing-tool hints
Before printing the completion summary, the CLI checks whether the runtime and package manager your selections actually need are on your PATH. If something is missing, it prints an official install link next to the next steps instead of leaving you to hit a command not found on your first command. For example, scaffolding the bun-basic template on a machine without Bun surfaces a https://bun.sh link, and choosing pnpm without pnpm installed surfaces https://pnpm.io/installation. Node-flavored templates (node-basic, vercel, cloudflare-worker) point at https://nodejs.org when Node.js is absent. The probe only reads PATH (it never executes the binary), and if you asked to install dependencies but the chosen package manager is missing, the CLI skips the doomed install and shows the link instead. When every required tool is present, no hint is printed.
The CLI also checks versions. npm create daloy and npx will run the scaffolder on an old Node.js because engines are only advisory there, so the CLI verifies it itself: if you are on a Node.js older than 24, it stops before scaffolding with a clear message, the nodejs.org link, and a nudge toward a version manager (nvm, fnm, Volta) rather than generating a project your runtime cannot run. And when you pick npm, it detects an npm older than 12 up front, tells you to run npm install -g npm@latest, and skips the automatic install so you get a readable explanation instead of npm's raw EBADENGINE error partway through.
Templates
Run create-daloy --list-templates to inspect the available starters without creating a project.
node-basic
A production-ready Node.js HTTP server using @daloyjs/core with secureHeaders, requestId, rateLimit, hardened install settings (pnpm-workspace.yaml plus an .npmrc mirror), a sample GET /healthz route, a contract-first GET /books/:id route with Zod validation, and Hey API codegen wired to pnpm gen.
Like FastAPI, every scaffolded project also exposes API documentation out of the box in development: /docs serves a Scalar API reference UI and /openapi.json serves the live OpenAPI 3.1 spec generated from your route definitions. Templates set docs: "auto", so a production deploy does not publish them unless you set docs: true. The dev server logs both URLs at startup. Pass docs: { ui: "swagger" } on the App constructor to switch to Swagger UI instead (the object form also stays off in production unless you add enabled: true).
cloudflare-worker
A minimal Cloudflare Worker using @daloyjs/core/cloudflare with wrangler.toml ready to deploy, secureHeaders + requestId + a per-isolate rateLimit enabled by default, a smaller edge-friendly body limit (256 KiB versus 1 MiB in the Node starter), and a Zod-validated route exposed as fetch.
vercel
A Vercel API on the Node.js runtime (Vercel's recommended runtime for standalone functions) using @daloyjs/core/vercel with a single api/index.ts function exporting toFetchHandler(app) (plus a vercel.json rewrite so DaloyJS routes at the site root), a dev script that serves the same app locally with node --watch src/dev.ts, a deploy script that runs vercel deploy, secureHeaders + requestId + a per-instance rateLimit enabled by default, a smaller serverless-friendly body limit (256 KiB), and the same health and bookstore examples as the Node starter.
The Vercel template also ships /docs (Scalar API reference) and /openapi.json wired to the same app with docs: "auto", so they are served locally but not on a production deployment (the app sets production from NODE_ENV). Set docs: true to publish them on the deployed URL.
bun-basic
A Bun runtime starter using@daloyjs/core/bun. Ships bun --hot for instant reloads, bun test for the test runner, the same starter security middleware as the Node template (secureHeaders / requestId / rateLimit), the bookstore demo route, and Hey API codegen wired through bun run gen:openapi +bun run gen:client.
deno-basic
A Deno runtime starter using@daloyjs/core/deno. Ships a deno.json with deno task dev, deno task start, deno task test, deno task contract, and deno task gen:openapi tasks, maps @daloyjs/core to the JSR package jsr:@daloyjs/daloy and Zod to an npm: specifier in the import map, and runs the server with only --allow-net and an --allow-env scoped to PORT, DENO_ENV, TRUST_PROXY_HOPS, and PUBLIC_URL. The CLI skips Node-style installs for this template, there is no package.json to patch.
Minimal scaffolds
Pass --minimal to drop the bookstore demo route and the built-in /docs + /openapi.json API docs routes from any template that supports them. The scaffolded app is left with the framework bootstrap and a single /healthz route, which is the smallest realistic starting point for teams that already know exactly what they want to build:
Sentinel comments (// daloy-minimal:strip-start <tag> /// daloy-minimal:strip-end <tag>) survive a default scaffold so you can re-run the generator with --minimal later, or delete the marked blocks by hand.
Hardened CI/security bundle
The bundle is on by default (the prompt defaults to yes; pass --no-ci to skip it, or --with-ci to choose it non-interactively). It gives the new project GitHub-side supply-chain guardrails as well as runtime defaults. Node-style templates get CI, a manual-only deploy starter, CodeQL, OpenSSF Scorecard, zizmor, Dependabot, CODEOWNERS, SECURITY.md, and a lockfile-source verification script. The Deno template gets the same governance and scanning files with a Deno-native CI workflow. No template gets an npm publish workflow, because create-daloy scaffolds REST API services rather than reusable libraries.
The generated workflows use top-level permissions: {}, pinned third-party actions, harden-runner, persist-credentials: false, disabled install scripts, and no package-manager cache. Replace the CODEOWNERS placeholder if you did not pass --code-owner, then enable branch protection, required status checks, secret scanning, and push protection in GitHub settings. Use --with-ci --no-deploy when you want governance without deployment scaffolding, or --with-deploy --no-ci when you only want the deployment starter.
Editor MCP integration
Every scaffold ships a .vscode/mcp.json that wires VS Code (and other MCP-aware editors) to the DaloyJS documentation MCP server at https://daloyjs.dev/mcp over HTTP. With it, AI assistants in your editor can pull current DaloyJS docs while you work, with no manual setup. The file is authored as _vscode/mcp.json in the template and renamed to .vscode/mcp.json on copy so it survives npm packing.
Delete the file or remove the server entry if you do not want the integration. It is editor configuration only and the framework does not depend on it at runtime.
Which template should I choose?
- Choose
node-basicfor a traditional REST API on Node, Docker, Fly.io, Railway, Render, or any VM/container host. - Choose
vercelwhen Vercel is your deployment target and you want a catch-all Vercel Functions API route (Node.js runtime) from the first commit. - Choose
cloudflare-workeronly when your deployment target is Cloudflare Workers. The template supports that runtime. Cloudflare is optional. - Choose
bun-basicwhen your team already runs on Bun and wantsbun --hot+bun testin the box. - Choose
deno-basicwhen you want a runtime-native Deno project withdeno taskscripts, an import map, and Deno's permission flags.
Why a generator?
DaloyJS is a backend framework, so the first ten minutes matter. The scaffolder gives every project the same guardrail-first posture, the same TypeScript baseline, and the same scripts so an AI coding agent or a new teammate can navigate it without a tour. Every starter includes secureHeaders, requestId, and rateLimit. The Vercel and Cloudflare starters also set a tighter body limit.
The CLI itself ships with zero runtime dependencies: only Node built-ins, so the supply-chain story stays clean. Templates are copied verbatim from the package's templates/ directory and never run scripts during scaffolding. When you choose pnpm, the generated app keeps the hardened .npmrc and pnpm-workspace.yaml, and the CLI adds a pnpm >= 11 floor to engines (pnpm always enforces engines.pnpm). older pnpm silently ignores minimumReleaseAge, which would disable the 24h supply-chain cooldown. The CLI also warns up front if the installed pnpm is older. When you choose npm, the CLI adds an npm >= 12 floor to engines and swaps in an npm-native .npmrc with engine-strict=true (so that floor is a hard install-time failure rather than a warning), ignore-scripts=true, and min-release-age=1 (one day). Yarn and Bun scaffolds drop the pnpm-specific config so installs stay warning-free and get their own equivalents instead: Yarn gets .yarnrc.yml and .yarnrc (see the table below), and Bun gets a bunfig.toml with a 24-hour minimumReleaseAge. When you choose --with-ci, it also adds the GitHub-side security files that a company repo normally has to assemble by hand.
Install hardening per package manager (1.5.4)
From 1.5.4 every package manager gets lifecycle scripts off and a release-age cooldown where the tool supports one:
| Package manager | File | What it sets |
|---|---|---|
| pnpm | pnpm-workspace.yaml (pnpm 11 reads it; .npmrc mirror for older tooling) | ignoreScripts: true, minimumReleaseAge: 1440, blockExoticSubdeps: true, store verification |
| npm | .npmrc | ignore-scripts=true, min-release-age=1 (days), engine-strict=true |
| Yarn | .yarnrc.yml (Yarn 2+), .yarnrc (Yarn 1) | enableScripts: false and npmMinimalAgeGate: "1d"; Yarn 1 gets ignore-scripts true (it has no release-age setting) |
| Bun | bunfig.toml | minimumReleaseAge = 86400 (seconds, Bun 1.3+) |
Template Dockerfiles also pin their base images by digest, so a retagged base image cannot change what your container build pulls; update the digest deliberately (Dependabot can do it with the --with-ci bundle).
Blocking lifecycle scripts stops install-script payloads, not a payload that runs when your code imports a package. The cooldown helps only against bad versions that are caught within the window. See Supply-chain security for what each control covers.
Next
After scaffolding, jump straight to Getting started for the route walkthrough, or Security for the guardrails and middleware the scaffold installed.