Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.14.0"
node-version: "22.18.0"
registry-url: "https://registry.npmjs.org"

- name: Compute preview metadata
Expand Down Expand Up @@ -201,7 +201,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.14.0"
node-version: "22.18.0"
registry-url: "https://registry.npmjs.org"

- name: Extract version from commit message
Expand Down
181 changes: 34 additions & 147 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,179 +1,66 @@
# create-prisma

Scaffold a new app with Prisma Next already wired up.
Create a Prisma 8 app with Prisma Composer built in.

`create-prisma@next` gives you a project template, Prisma Next setup, database scripts, and a working starting point without making you assemble everything by hand.
## Quick start

## What It Does

- creates a new app from a supported template
- adds Prisma Next dependencies for PostgreSQL or MongoDB
- runs `prisma-next init --no-install` to scaffold `prisma/contract.*`, `prisma-next.config.ts`, `prisma/db.ts`, `prisma-next.md`, and `.env.example`
- writes a template-specific Prisma Next runtime helper
- adds `contract:emit`, `db:init`, `db:update`, `db:verify`, `db:seed`, `migration:plan`, `migrate`, `migration:status`, and `migration:show` scripts
- adds `db:up` / `db:down` and `docker-compose.yml` for default MongoDB projects
- creates or updates `.env` with `DATABASE_URL`
- can install dependencies and run `prisma-next contract emit`

`db:init`, migrations, and seeding are never run automatically. PostgreSQL projects show
`db:init` as a manual follow-up command; MongoDB projects show `db:up` plus the migration
plan/apply path for initial schema setup.

## Quick Start

Use the package runner you already have:
Use your package manager:

```bash
npx create-prisma@next my-app
```

```bash
pnpm dlx create-prisma@next my-app
```

```bash
yarn dlx create-prisma@next my-app
```

```bash
bunx create-prisma@next my-app
```

```bash
deno run -A npm:create-prisma@next my-app
```

If you already have it available locally:

```bash
create-prisma
```

## Common Examples

Create a project interactively:

```bash
create-prisma
```

Create a Minimal project non-interactively:
The CLI initializes Prisma 8 with the aligned `@prisma/cli` prerelease, installs dependencies, emits the contract, and generates a deployable Composer app. PostgreSQL projects use Composer's native Prisma Postgres provider, including migrations and a typed runtime client.

```bash
create-prisma my-script --template minimal --provider postgres
```
The only Composer prompt is:

Create a Hono app non-interactively:

```bash
create-prisma my-api --template hono --provider postgres
```text
Deploy to Prisma now?
```

Create a MongoDB app:
Choose no to deploy later with the generated `deploy` script.

```bash
create-prisma my-api --template hono --provider mongodb
```
## Templates

Scaffold into the current directory:
- `minimal`
- `hono`
- `elysia`
- `nest`
- `next`
- `svelte` (SvelteKit)
- `astro`
- `nuxt`
- `tanstack-start`

```bash
create-prisma . --template hono --provider postgres
```

Use TypeScript contract authoring:
PostgreSQL and MongoDB are supported with PSL or TypeScript contract authoring. npm, pnpm, Yarn, and Bun are supported.

```bash
create-prisma my-app --template next --authoring typescript
```
## Options

Use Prisma Postgres auto-provisioning:
- positional project name or `--name`
- `--template`
- `--provider postgres|postgresql|mongo|mongodb`
- `--authoring psl|typescript`
- `--package-manager npm|pnpm|yarn|bun`
- `--deploy` / `--no-deploy`
- `--yes`
- `--force`
- `--verbose`

```bash
create-prisma my-app --template nest --provider postgres --prisma-postgres
```
This branch intentionally targets Prisma 8 only. It does not generate a Prisma 7 compatibility path.

Target a specific Prisma Next release (useful for regression / bisect work):

```bash
create-prisma my-app --template hono --prisma-next-version 0.10.0
```

Scaffold against an open PR via pkg.pr.new:

```bash
create-prisma my-app --template hono --prisma-next-version pkg-pr-new:bad6795
```

## Supported Templates

- `minimal` - script-first Prisma Next starter with no web framework
- `hono` - lightweight TypeScript API server
- `elysia` - Bun-friendly TypeScript API server
- `nest` - structured Node API with controllers and services
- `next` - full-stack React app with App Router
- `svelte` - full-stack Svelte 5 app with Vite
- `astro` - content-oriented web app with server routes
- `nuxt` - full-stack Vue app with Nitro server routes
- `tanstack-start` - React app with file routes and server functions

## Supported Databases

- `postgres` / `postgresql`
- `mongo` / `mongodb`

## Supported Package Managers

- `npm`
- `pnpm`
- `yarn`
- `bun`
- `deno`

## Useful Flags

- positional project name or `--name` project name / relative path
- `--template` choose the template
- `--provider postgres|postgresql|mongo|mongodb` (default: `postgres`)
- `--authoring psl|typescript` (default: `psl`)
- `--package-manager` choose the package manager/runtime
- `--database-url` set `DATABASE_URL`
- `--yes` accept defaults and skip prompts
- `--no-install` scaffold only
- `--no-emit` skip `prisma-next contract emit`
- `--prisma-postgres` provision Prisma Postgres for PostgreSQL
- `--prisma-next-version <spec>` target a specific Prisma Next release, npm dist-tag, or
pkg.pr.new PR preview. Accepts a published version (`0.10.0`, `0.11.0-dev.9`),
an npm dist-tag (`latest` (default), `dev`, `next`, …), or `pkg-pr-new:<sha|branch|pr-number>`
to install from `https://pkg.pr.new/prisma/prisma-next/<package>@<ref>`.
- `--force` allow scaffolding into a non-empty directory
- `--verbose` print full command output

Generated Node-based Prisma Next projects document Node.js 24 LTS or newer.

## Local Development
## Development

```bash
bun install
bun run test:unit
bun run typecheck
bun run check
bun run build
bun run start
```

Useful repo scripts:

- `bun run dev`
- `bun run typecheck`
- `bun run format`
- `bun run lint`
- `bun run bump`

## Telemetry

Published builds may send anonymous usage telemetry to help improve the CLI. It does not include project names, file paths, or database URLs.

Disable it with any of:

- `DO_NOT_TRACK`
- `CREATE_PRISMA_DISABLE_TELEMETRY`
- `CREATE_PRISMA_TELEMETRY_DISABLED`
Published builds may send anonymous usage telemetry. It never includes project names, file paths, or database URLs. Disable it with `DO_NOT_TRACK`, `CREATE_PRISMA_DISABLE_TELEMETRY`, or `CREATE_PRISMA_TELEMETRY_DISABLED`.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "create-prisma",
"version": "0.4.2",
"private": false,
"description": "Create Prisma Next projects with first-party templates and great DX.",
"description": "Create Prisma 8 projects with first-party templates and great DX.",
"homepage": "https://github.com/prisma/create-prisma",
"bugs": {
"url": "https://github.com/prisma/create-prisma/issues"
Expand Down Expand Up @@ -37,7 +37,7 @@
"dev": "tsdown --watch",
"start": "bun run ./dist/cli.mjs",
"test": "bun run test:unit && bun run test:e2e",
"test:unit": "bun test ./tests/dependencies.test.ts ./tests/install.test.ts ./tests/setup-prisma.test.ts ./tests/telemetry.test.ts",
"test:unit": "bun test ./tests/dependencies.test.ts ./tests/deploy-with-composer.test.ts ./tests/install.test.ts ./tests/node-version.test.ts ./tests/setup-prisma.test.ts ./tests/telemetry.test.ts",
"test:e2e": "bun test --timeout 180000 ./tests/e2e/create-prisma.e2e.test.ts",
"check": "bun run format:check && bun run lint",
"lint": "oxlint . --deny-warnings",
Expand Down Expand Up @@ -73,7 +73,7 @@
},
"engines": {
"bun": ">=1.3.0",
"node": ">=24.0.0"
"node": ">=22.18.0"
},
"packageManager": "bun@1.3.9"
}
10 changes: 9 additions & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import { createCreatePrismaCli } from "./index";

createCreatePrismaCli().run();
createCreatePrismaCli().run({
process: {
exit(code): never {
const commandExitCode =
typeof process.exitCode === "number" && process.exitCode !== 0 ? process.exitCode : code;
process.exit(commandExitCode);
},
},
});
26 changes: 18 additions & 8 deletions src/commands/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
trackCreateFailed,
type CreateTelemetryFailureStage,
} from "../telemetry";
import { scaffoldCreateTemplate } from "../templates/render-create-template";
import { scaffoldCreateFrameworkTemplate } from "../templates/render-create-template";
import { writeCreateTemplateDependencies } from "../tasks/install";
import type { PrismaSetupContext } from "../tasks/setup-prisma";
import { collectPrismaSetupContext, executePrismaSetupContext } from "../tasks/setup-prisma";
Expand All @@ -18,6 +18,7 @@ import {
type CreateTemplate,
} from "../types";
import { getCreatePrismaIntro } from "../ui/branding";
import { getUnsupportedNodeMessage, supportsPrismaNext } from "../utils/node-version";

const DEFAULT_PROJECT_NAME = "my-app";
const DEFAULT_TEMPLATE: CreateTemplate = "minimal";
Expand Down Expand Up @@ -100,7 +101,7 @@ async function promptForCreateTemplate(): Promise<CreateTemplate | undefined> {
{
value: "minimal",
label: "Minimal",
hint: "Script-first Prisma Next starter with no web framework",
hint: "Script-first Prisma 8 starter with no web framework",
},
{
value: "hono",
Expand Down Expand Up @@ -188,6 +189,12 @@ export async function runCreateCommand(rawInput: CreateCommandInput = {}): Promi
try {
input = CreateCommandInputSchema.parse(rawInput);

if (!supportsPrismaNext()) {
cancel(getUnsupportedNodeMessage());
process.exitCode = 1;
return;
}

intro(getCreatePrismaIntro());

failureStage = "collect_context";
Expand All @@ -199,6 +206,7 @@ export async function runCreateCommand(rawInput: CreateCommandInput = {}): Promi
failureStage = "unknown";
const executionResult = await executeCreateContext(context);
if (!executionResult.ok) {
process.exitCode = 1;
if (executionResult.error) {
cancel(
`Create command failed: ${
Expand All @@ -225,6 +233,7 @@ export async function runCreateCommand(rawInput: CreateCommandInput = {}): Promi
durationMs: Date.now() - startedAt,
});
} catch (error) {
process.exitCode = 1;
cancel(`Create command failed: ${error instanceof Error ? error.message : String(error)}`);
await trackCreateFailed({
input,
Expand Down Expand Up @@ -301,14 +310,14 @@ async function executeCreateContext(
context: CreatePromptContext,
): Promise<ExecuteCreateContextResult> {
const createSpinner = context.prismaSetupContext.verbose ? undefined : spinner();
createSpinner?.start("Creating Prisma Next project...");
createSpinner?.start("Creating Prisma 8 project...");

try {
if (context.prismaSetupContext.verbose) {
log.step(`Scaffolding ${context.template} starter.`);
}

await scaffoldCreateTemplate({
await scaffoldCreateFrameworkTemplate({
projectDir: context.targetDirectory,
projectName: context.projectPackageName,
template: context.template,
Expand All @@ -321,7 +330,7 @@ async function executeCreateContext(
log.success("Starter files scaffolded.");
}
} catch (error) {
createSpinner?.stop("Could not create Prisma Next project.");
createSpinner?.stop("Could not create Prisma 8 project.");
return {
ok: false,
stage: "scaffold_template",
Expand All @@ -334,10 +343,9 @@ async function executeCreateContext(
template: context.template,
packageManager: context.prismaSetupContext.packageManager,
projectDir: context.targetDirectory,
prismaNextSpec: context.prismaSetupContext.prismaNextSpec,
});
} catch (error) {
createSpinner?.stop("Could not create Prisma Next project.");
createSpinner?.stop("Could not create Prisma 8 project.");
return {
ok: false,
stage: "scaffold_template",
Expand Down Expand Up @@ -369,6 +377,8 @@ async function executeCreateContext(
const didSetupPrisma = await executePrismaSetupContext(context.prismaSetupContext, {
prependNextSteps: nextSteps,
projectDir: context.targetDirectory,
projectName: context.projectPackageName,
template: context.template,
createdProjectPath: context.targetDirectory,
includeDevNextStep: true,
progressSpinner: createSpinner,
Expand All @@ -381,7 +391,7 @@ async function executeCreateContext(
};
}
} catch (error) {
createSpinner?.stop("Could not create Prisma Next project.");
createSpinner?.stop("Could not create Prisma 8 project.");
return {
ok: false,
stage: "prisma_setup",
Expand Down
Loading
Loading