# create-raredays-app

Scaffold a new RareDays Next.js app. Runs as an interactive TUI or non-interactively with flags.

## Usage

```sh
# interactive mode (prompts for everything)
pnpm create raredays-app

# non-interactive with a preset
pnpm create raredays-app my-app --preset courseware --id-strategy uuidv7

# non-interactive with explicit options
pnpm create raredays-app my-app --template full-stack --id-strategy uuidv7 --modules billing,jobs

# from a checkout of this repo
node workspaces/app/cli/create-raredays-app/bin/index.js my-app --id-strategy uuidv7
```

## Presets

Pre-configured app types offered in interactive mode and via `--preset`:

- **courseware** -- Full course platform (full-stack template + billing module, violet brand).
- **internal-tool** -- Admin dashboard (full-stack template + jobs module, slate brand).
- **demo** -- Lightweight demo (static template, no modules, emerald brand).

Presets set the template, modules, and brand color. You can still customise display name and git settings.

## Templates

- **full-stack** -- Next.js + Drizzle + the full module system. Supports identity, billing, jobs, notifications, email, telemetry. Composition root at `app/lib/runtime.ts`.
- **client** -- Next.js BFF + SPA, proxies to an external backend. Supports modules but no database layer.
- **static** -- Truly static, deployable to CDN/edge. Core + design system only, no SSR or API routes.

## Options

- `--template <name>` -- `full-stack` (default), `client`, or `static`.
- `--id-strategy <name>` -- `uuidv7`, `uuidv4`, or `text`: how user and organization ids are generated and stored (framework ADR-0028). Required for the `full-stack` and `client` templates, with no default; written to `idStrategy` in `site.spec.ts`. Interactive mode asks for it.
- `--preset <name>` -- `courseware`, `internal-tool`, or `demo`. **Overrides** `--template`, `--modules`, and `--vendors` (it does not extend them).
- `--modules <list>` -- comma-separated modules to wire. Discovered dynamically from `scaffold-fragments/`: `billing`, `cms`, `email`, `feature-flags`, `i18n`, `identity`, `jobs`, `notifications`, `organizations`, `telemetry`. Modules apply to `full-stack` and `client` templates only.
- `--vendors <list>` -- comma-separated **`module:vendor` pairs**, e.g. `billing:stripe,cms:hygraph,email:resend,identity:better-auth`. A bare vendor name (`stripe`) is not a valid pair and is skipped with a warning.
- `--harness <name>` -- wire `@raredays/mcp` into an MCP-aware IDE: `claude-code`, `cursor`, `windsurf`, or `none` (default). Adds `@raredays/mcp` to devDependencies and writes the IDE config (`.mcp.json` at root for Claude Code; `.cursor/mcp.json` / `.windsurf/mcp.json` otherwise).
- `--deploy <target>` -- scaffold deploy config: `vercel` or `none` (default). Writes `vercel.json`, `.env.example`, and `docs/DEPLOY.md`.
- `--remote-url <url>` -- set git remote origin after scaffolding.
- `--no-git` -- skip `git init`.
- `--no-install` -- skip `pnpm install`.
- `--dev` -- rewrite every `@raredays/*` dependency to `workspace:*` (for in-repo dogfooding).
- `--agents-only` -- put the template's project conventions in `AGENTS.md` and write no root `CLAUDE.md`. The template's `## Skillex` section is renamed `## Skillex commands`, so it does not clash with the `## Skillex` block that `skillex refresh` adds. Also sets `AgentBridges: false` in `skillex.json`; skillex ignores that field today, so `skillex refresh` still writes `.claude/CLAUDE.md`.
- `-h`, `--help` -- show usage.

## What it does

1. Copies `templates/<name>/` into the target directory.
2. Renames stub files (`_gitignore` -> `.gitignore`, `_npmrc` -> `.npmrc`, `_claude` -> `.claude`, `_github` -> `.github`).
3. Sets `package.json:name` to the project slug.
4. Substitutes `__SLUG__` in `site.spec.ts` and applies display name, domain, and brand color.
5. Loads scaffold fragments for selected modules (imports, config, ports, file overlays) and applies vendor overlays for each `module:vendor` pair.
6. Composes `app/lib/runtime.ts` with module wiring and `mocks/handlers.ts` with vendor mocks (skipped for the `static` template, which has no composition root).
7. Merges fragment + vendor dependencies (and fragment devDependencies and scripts) into `package.json`.
8. Applies `--harness` (MCP config) and `--deploy` (deploy config) when requested.
9. Writes `.env.example` **only** if any vendor or deploy env vars are needed.
10. Optionally runs `git init` and `pnpm install`.

## Scaffold fragments

The `scaffold-fragments/` directory contains per-module overlays (10 total):

- `billing/` -- billing integration; vendor: `stripe`
- `cms/` -- CMS integration; vendor: `hygraph`
- `email/` -- transactional email plus `@raredays/email-templates` (`emails/`, `pnpm email:dev`, template-backed senders in `app/lib/email.ts`); vendor: `resend`
- `feature-flags/` -- feature-flag wiring
- `i18n/` -- internationalisation
- `identity/` -- auth/sessions/roles; vendor: `better-auth`
- `jobs/` -- background job processing
- `notifications/` -- multi-channel notification delivery
- `organizations/` -- multi-tenant organizations
- `telemetry/` -- telemetry; vendors: `sentry`, `axiom`

Each fragment has a `module.json` manifest, runtime slot injections, and optional per-vendor file overlays.

## Keeping template pins current

Every template and fragment pins `@raredays/*` deps and `MCP_VERSION`. These are
the framework's public surface — a non-`--dev` scaffold installs exactly what
they pin — and do not move automatically when the workspace releases. Run
`pnpm --filter create-raredays-app sync-versions` (also run as `prepublishOnly`)
to refresh them to `^<current workspace version>`. The guard test
`test/template-workspace-pins.test.ts` fails in CI when a change drifts a pin out
of range. Drift that a release left on `main` before the sync bot re-pins is
already at the change's merge base, so it does not fail unrelated PRs; it does
fail while a pending changeset releases `create-raredays-app`.

On `main` the pins are usually EXACT: the repo-level
`scripts/sync-scaffold-versions.mjs` bot writes exact versions so it opens a
review PR on every release. That is an intermediate, not what ships:
`prepublishOnly` converts every pin to caret, as ADR-0017 requires, and
`test/publish-caret-pins.test.ts` packs the package and fails if an exact pin
would reach the tarball.

## How it fits in the ecosystem

`create-raredays-app` is the primary entry point for new RareDays projects. It produces a fully configured Next.js app that depends on `@raredays/core`, `@raredays/style`, `@raredays/lint`, and `@raredays/typescript`, plus any domain modules the user selects. The generated app follows the same hexagonal architecture used internally: port contracts from `@raredays/core`, in-memory dev providers, and vendor adapters swapped in for production.

## Development

```sh
# run the scaffolder interactively in a sandbox
pnpm --filter create-raredays-app dev

# clean the sandbox
pnpm --filter create-raredays-app clean

# lint
pnpm --filter create-raredays-app lint
```
