---
title: "Create a project"
description: "Scaffold a Taman monorepo with pnpm create taman. The generated code is yours; only @vinicunca packages keep receiving updates."
canonical_url: "https://vinicunca.dev/taman/getting-started/create-a-project"
---
# Create a project

> Scaffold a Taman monorepo with pnpm create taman. The generated code is yours; only @vinicunca packages keep receiving updates.

## Requirements

- Node `^22.18.0 || ^24.0.0`
- pnpm 12 (the template's `packageManager` is `pnpm@12.6.0`)
- Docker, for local Postgres

## Scaffold

```bash [pnpm]
pnpm create taman my-app
```

```bash [npm]
npx create-taman my-app
```

The CLI prompts for a **project folder** and an **npm scope** for workspace packages (default: the folder name). Pass `-y` to accept defaults without prompting:

```bash
pnpm create taman my-app --scope acme -y
```

That produces a folder `my-app` whose workspace packages are `@acme/web`, `@acme/api`, `@acme/db-pg`, and so on.

## Options

**folder** (`positional`): Project directory. Must be empty or missing. The folder name becomes the project name (lowercase npm name: letters, digits, -, ., _; max 214 characters).

**--scope** (`string`): npm scope without @ for workspace packages. Accepts acme, @acme, or @acme/. Default: folder name.

**--ref** (`string`): Git ref of vinicunca/taman to generate from. Default: create-taman@<this CLI version> so the snapshot matches the CLI you ran.

**--no-install**: Skip pnpm install after writing files.

**--no-git**: Skip git init and the first commit.

**-y, --yes**: Accept defaults. Still requires a folder argument.

**-h, --help**: Print usage.

`--from <dir>` is a **hidden** flag for local checkouts. It archives `HEAD` of that repo (committed files only) instead of downloading GitHub. Used by the template smoke test.

There are **no optional features**. Every generated project is the same stack.

## What the CLI does

### Refuse a non-empty directory

If `dir` exists and is not empty, generation stops with an error. A directory the CLI created is removed if generation fails later.

### Download the template

By default, [giget](https://github.com/unjs/giget) fetches `github:vinicunca/taman#<ref>`. The default ref is `create-taman@0.1.0` (the published CLI version).

### Apply `template.manifest.ts`

The snapshot's `template.manifest.ts` is loaded and applied:

- **Remove** published packages (`taman-core`, `taman-ui`, `request`, `create-taman`, `internal/**`), GitHub/changeset/docs/tasks, Graphify, example gallery views, and the manifest itself.
- **Workspace** drops `internal/*` entries from `pnpm-workspace.yaml`.
- **Scripts** drop `build:docker`, `check:api-packages`, `publint` from the root `package.json`.
- **Scope** replaces `@taman/` with `@<scope>/` in every text file.
- **Renames** worker name, queue names, Docker container/volume/db, and sample env titles.
- **Published deps** that left the snapshot (`workspace:` on `@vinicunca/taman-core`, etc.) become `catalog:` entries pinned to the snapshot version.

A glob or workspace entry that matches nothing is a **hard error** (manifest drift). Leftover `@taman/` strings are warnings, not failures.

### Copy env files and write README

Every `.env*.example` is copied to the matching `.env` (never overwriting). `README.md` is replaced with a short generated file.

### Git and install

Unless `--no-git`, the CLI runs `git init` and commits `Initial commit from create-taman` (`--no-verify`). If git identity is missing, it uses `create-taman@users.noreply.github.com`. Git failure does **not** discard the project.

Unless `--no-install`, it runs `pnpm install` in the new folder.

## Next steps

The CLI prints:

```bash
cd my-app
docker compose up -d
pnpm db-pg:migrate:dev
pnpm dev:api   # and in another terminal: pnpm dev:web
```

Continue with [Running locally](https://vinicunca.dev/taman/getting-started/running-locally).


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
