The official CLI for creating and managing Qwik projects.
# Create a new project
pnpm create qwik
# Add an integration
pnpm qwik add tailwind
# Scaffold a component or route
pnpm qwik new component my-button- Node.js >= 24.0.0
graph LR
CQ["create-qwik"] --> Scaffold["Scaffold App"]
Q["qwik"] --> Router
Router -->|lazy import| Commands
Commands --> Stubs["stubs/"]
Scaffold --> Stubs
All commands extend a shared Program base class with a consistent lifecycle: configure → parse → interact/validate → execute. Integrations in stubs/ are auto-discovered — no registration needed.
pnpm install
pnpm build # Build CLI (vp pack)
pnpm test # Integration tests (Japa)
pnpm test:unit # Unit tests (Vitest)
pnpm lint # Lint
pnpm format # Formatbin/ # CLI entry points
src/
commands/ # CLI commands (add, new, build, migrate, etc.)
integrations/ # Loading and applying stubs to user projects
create-qwik/ # create-qwik scaffolding logic
core.ts # Program base class (all commands extend this)
router.ts # Command routing with lazy imports
stubs/
adapters/ # Server deployment targets (cloudflare, vercel, netlify, etc.)
features/ # Optional integrations (tailwind, vitest, drizzle, etc.)
apps/ # Starter templates for create-qwik
templates/ # File generators for `qwik new`
migrations/
v2/ # v1 → v2 migration pipeline
Stubs are the most common contribution. They live in stubs/adapters/ and stubs/features/ and are auto-discovered — no registration needed. Drop a folder with a package.json and it shows up in qwik add.
- Adapter (
stubs/adapters/): A deployment target. Provides a server entry point and build config. Examples: cloudflare-pages, vercel-edge, node-server. - Feature (
stubs/features/): An optional integration. Adds tooling, styling, testing, etc. Examples: tailwind, vitest, drizzle.
Every stub is a directory with a package.json containing a __qwik__ key. All other files get copied into the user's project when they run qwik add <id>.
stubs/features/my-feature/
package.json # Required: metadata + dependencies
src/global.css # Optional: files copied to user's project
prettier.config.js # Optional: any config files
The directory name becomes the stub ID (what users type in qwik add <id>).
A stub's package.json has two jobs:
- Standard npm fields (
dependencies,devDependencies,scripts) — these get merged into the user's project. __qwik__metadata — tells the CLI how to present and apply the integration.
Minimal example (a feature that just adds a dependency):
{
"description": "Drizzle ORM",
"devDependencies": {
"drizzle-orm": "^0.30.0"
},
"__qwik__": {
"displayName": "Integration: Drizzle ORM"
}
}That's all you need. displayName is what appears in the qwik add menu. Priority is derived automatically from the directory — adapters sort above features. You only need to set priority if you want to control ordering within the group.
With Vite plugin injection (the CLI auto-modifies the user's vite.config.ts):
{
"__qwik__": {
"displayName": "Integration: Tailwind v4 (styling)",
"viteConfig": {
"imports": [{ "defaultImport": "tailwindcss", "importPath": "@tailwindcss/vite" }],
"vitePlugins": ["tailwindcss()"]
}
}
}With post-install messaging:
{
"__qwik__": {
"displayName": "Adapter: Cloudflare Pages",
"priority": 40,
"docs": ["https://qwik.dev/deployments/cloudflare-pages/"],
"nextSteps": {
"title": "Next Steps",
"lines": ["Run `pnpm run build` then `pnpm run deploy`"]
}
}
}| Field | Required | Description |
|---|---|---|
displayName |
✅ | Label in the qwik add selection menu |
priority |
Override sort order within group. Default: 20 (adapters), -10 (features) | |
viteConfig |
Auto-adds imports and plugins to vite.config.ts |
|
docs |
Documentation URLs shown after install | |
nextSteps |
Instructions shown after install |
Adapters typically include:
stubs/adapters/my-adapter/
package.json
adapters/my-adapter/vite.config.ts # Build config
src/entry.my-adapter.tsx # Server entry point
gitignore # Merged into .gitignore (no dot prefix)
The scripts in an adapter's package.json get merged into the user's package.json:
{
"scripts": {
"build.server": "vite build -c adapters/my-adapter/vite.config.ts",
"deploy": "my-platform deploy ./dist",
"serve": "my-platform dev ./dist"
}
}Build the CLI and test against a real project:
pnpm build
node ./dist/bin/qwik.mjs add my-featureOr run the existing integration tests:
pnpm testMIT