---
name: "Consuming create-raredays-app"
description: How to scaffold new apps — presets, interactive prompts sequence, CLI flags (including --preset/--harness/--deploy), three templates (full-stack/client/static) with output files, ten available modules with vendor options, --dev flag for monorepo dogfooding.
topics: [scaffolding, consuming]
tags: [scaffolding, cli, consuming]
---

# Consuming create-raredays-app

## Interactive Mode

```sh
pnpm create raredays-app
```

Prompts in roughly this order:

1. **What are you building?** — pick a preset (courseware / internal-tool / demo) or "custom"
2. **Project name** — directory name and package slug (kebab-case, 1–64 chars)
3. **Template** — `full-stack`, `client`, or `static` (skipped when a preset is chosen)
4. **Id strategy**: `uuidv7`, `uuidv4` or `text`, for every template but `static` (framework ADR-0028; no default)
5. **Display name** — human-readable (defaults to project name)
6. **Canonical domain** — optional, hostname only (e.g., `example.com`)
7. **Brand primary color** — hex value (defaults to `#10b981`)
8. **Modules** — multiselect (not shown for `static` or when a preset is chosen)
9. **Vendors** — multiselect for selected modules
10. **Deploy target** — optional (`vercel` / none)
11. **Git remote URL** — optional
12. **Initialize git? / Run pnpm install?** — default yes

`--harness` (MCP/IDE wiring) is flag-only today; it is not offered interactively.

## Non-Interactive Mode

```sh
pnpm create raredays-app my-app \
  --template full-stack \
  --id-strategy uuidv7 \
  --modules billing,email,telemetry \
  --vendors billing:stripe,email:resend,telemetry:sentry,telemetry:axiom
```

## CLI Flags

| Flag            | Description                                                                         |
| --------------- | ----------------------------------------------------------------------------------- |
| `--template`    | `full-stack` (default), `client`, or `static`                                       |
| `--id-strategy` | `uuidv7`, `uuidv4` or `text`; required for `full-stack` and `client` (ADR-0028)     |
| `--preset`      | `courseware`, `internal-tool`, `demo` — **overrides** template/modules/vendors      |
| `--modules`     | Comma-separated module keys (ignored when `--preset` is given)                      |
| `--vendors`     | Comma-separated `MODULE:VENDOR` selectors (a bare vendor is skipped with a warning) |
| `--harness`     | `claude-code` / `cursor` / `windsurf` / none — wire `@raredays/mcp` into the IDE    |
| `--deploy`      | `vercel` / none — scaffold deploy config (`vercel.json`, `docs/DEPLOY.md`)          |
| `--remote-url`  | Git remote origin URL                                                               |
| `--no-git`      | Skip git initialization                                                             |
| `--no-install`  | Skip `pnpm install`                                                                 |
| `--dev`         | Rewrite all `@raredays/*` deps to `workspace:*` (monorepo dogfooding)               |

## Templates

### full-stack

Complete Next.js + Drizzle ORM + PostgreSQL + framework modules.

Key output files:

- `app/lib/runtime.ts` — composition root with module ports wired
- `db/schema.ts` + `db/index.ts` — Drizzle schema and client
- `drizzle.config.ts` — Drizzle Kit configuration
- `mocks/handlers.ts` — MSW handlers composed from vendor mocks
- `site.spec.ts` — SiteSpec with your branding choices
- `app/api/widgets/route.ts` — demo API endpoint
- `instrumentation.ts` — telemetry instrumentation hook

Every module fragment is available. Scripts include `db:generate`, `db:migrate`, `db:studio`.

### client

Next.js BFF + SPA that proxies to an external backend.

Key output files:

- `app/lib/runtime.ts` — composition root (identity + mocks)
- `app/api/backend/[...path]/route.ts` — backend proxy
- `app/api/dev/login|logout/route.ts` — dev auth routes
- `mocks/handlers.ts` — MSW handlers

Only telemetry module available. No database.

### static

CDN/edge-deployable static site. No modules, no database, no API routes.

Key output files:

- `site.spec.ts` — SiteSpec configuration
- `next.config.ts` — static export config

## Available Modules

Ten fragments live under `scaffold-fragments/`. Each declares which templates it
supports (`module.json:templates`); a module incompatible with the chosen
template is skipped with a warning.

| Module          | Label                       | Templates          | Vendor Options |
| --------------- | --------------------------- | ------------------ | -------------- |
| `billing`       | Subscriptions + webhooks    | full-stack         | Stripe         |
| `cms`           | Headless CMS + rich text    | full-stack, client | Hygraph        |
| `email`         | Transactional email         | full-stack         | Resend         |
| `feature-flags` | Feature-flag wiring         | full-stack, client | —              |
| `i18n`          | Internationalisation        | full-stack, client | —              |
| `identity`      | Auth, sessions, orgs, roles | full-stack, client | Better Auth    |
| `jobs`          | Background jobs             | full-stack         | — (in-memory)  |
| `notifications` | Multi-channel notifications | full-stack         | — (in-memory)  |
| `organizations` | Multi-tenant organizations  | full-stack         | — (in-memory)  |
| `telemetry`     | Logging, errors, metrics    | full-stack, client | Sentry, Axiom  |

Identity is always wired with an in-memory dev provider (the template hard-codes
`createInMemoryProvider` so `pnpm dev` works out of the box). Selecting
`--modules identity --vendors identity:better-auth` adds the production adapter
package, env vars, mock handlers, and a Next.js auth route stub — you then
manually replace the in-memory provider in `app/lib/runtime.ts` with
`createBetterAuthProvider({ auth, idStrategy: siteSpec.idStrategy })`.

The id strategy (framework ADR-0028) is a per-project choice with no default:
the scaffold asks for it (`--id-strategy` in non-interactive mode, required for
`full-stack` and `client`) and writes it to `idStrategy` in `site.spec.ts`. The
scaffolded `app/lib/auth.ts` passes it to Better Auth through
`generateIdFor(siteSpec.idStrategy)`. The full-stack template's `db/schema.ts`
builds the substrate tables with `createPostgresSchema(siteSpec.idStrategy)`,
and its `db/index.ts` passes that barrel to the driver, types the PGlite dev
tables' `organization_id` from the strategy and calls
`assertIdColumns(siteSpec.idStrategy, appSchema)`, so the database starts
under every strategy and refuses to start when a `user_id` or
`organization_id` column disagrees with it. After `auth generate`, run
the auth schema through `typeAuthIdColumns` (`@raredays/identity-better-auth`
`docs/setup.md`).

The `email` module also scaffolds `@raredays/email-templates`: an `emails/`
folder previewed with `pnpm email:dev` (port 3030) and `app/lib/email.ts`, which
holds the email provider and template-backed `sendResetPasswordEmail` /
`sendVerificationEmail` senders for Better Auth. See the `preview-email` skill.

### Vendor Environment Variables

When vendors are selected, `.env.example` is generated:

```sh
# billing (stripe)
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=

# cms (hygraph)
HYGRAPH_ENDPOINT=
HYGRAPH_TOKEN=

# email (resend)
RESEND_API_KEY=

# identity (better-auth)
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=

# telemetry (sentry)
SENTRY_DSN=

# telemetry (axiom)
AXIOM_TOKEN=
AXIOM_DATASET=
```

## What You Get

A fully configured project with:

- `site.spec.ts` — SiteSpec with your name, domain, and brand color substituted
- `app/lib/runtime.ts` — composition root with selected modules wired via slot injection
- `app/theme.override.css` — build-time `@theme` overrides from branding config
- `next.config.ts` — wraps `withRaredays()`
- `postcss.config.mjs` — re-exports from `@raredays/style/postcss`
- `mocks/` — MSW setup with vendor-specific handlers (client/full-stack)
- `.env.example` — written only when a selected vendor or `--deploy` target needs env vars
- `.claude/settings.json` and `.claude/hooks/env-file-guard.sh`: agent permissions plus a PreToolUse hook (a port of Course-Studio/baseplate's) that denies any Bash command naming an env file or a credential store (in any letter case), sweeping a directory that holds one, or running a CLI that prints a credential (`op`, `security`, `gh auth token`, `printenv`), whatever program or launcher runs it, and fails closed; it needs `bash`, `jq` and `python3`, and its cases run with `sh .claude/hooks/env-file-guard.test.sh`; pnpm scripts and searches scoped to a directory with no env file run unprompted
- With `--harness`: `.mcp.json` (Claude Code, at root) / `.cursor/mcp.json` / `.windsurf/mcp.json` + `@raredays/mcp` devDep
- With `--deploy vercel`: `vercel.json` + `docs/DEPLOY.md`

## After Scaffolding

```sh
cd my-app
pnpm install                    # if --no-install was used
cp .env.example .env.local      # if modules with env vars
pnpm dev                        # standard dev server
pnpm dev:mocks                  # dev with MSW intercepting API calls
```
