Installation
One command writes a working project. The scaffolder asks up to four questions, installs dependencies, creates a local database and leaves you with a dev server and an admin waiting for its first passkey.
Overview
Section titled “Overview”create-plumix-app assembles a project rather than copying a fixed template. It reads the runtime you pick and the plugins you tick, then splices their imports, their config slots and their registrations into one plumix.config.ts. Choosing the media or the OG plugin is what puts storage: r2({ binding: "MEDIA" }) in the config and an r2_buckets entry in wrangler.jsonc. Both declare a storage requirement, and it is fulfilled once however many of them you tick. Choosing neither leaves both out.
You need one of npm, pnpm, yarn or bun. No published Plumix package declares an engines range, so no Node version is enforced at install time. The repository is developed and tested on Node 24, which is what its .nvmrc pins.
The scaffolder does not work out which package manager invoked it. detectPackageManager takes the npm_config_user_agent string, but the binary calls it with nothing, so it always falls through to npm and the post-scaffold install runs npm install inside your new project. Pass --pm pnpm, --pm yarn or --pm bun to get the manager you actually use.
The target directory must not exist, or must be empty, and its parent must exist. Its last path segment becomes the project name, so it has to match npm’s package grammar: lowercase letters, digits, and -, _ or ., up to 214 characters. The name is spliced into package.json, into wrangler.jsonc and into the passkey relying-party name, so the scaffolder rejects an out-of-grammar name up front rather than emitting a project that will not build.
Quickstart
Section titled “Quickstart”Run the scaffolder with whichever package manager you use:
pnpm create plumix-app my-sitenpm create plumix-app my-siteyarn create plumix-app my-sitebun create plumix-app my-siteThen work through the rest:
-
Answer the wizard. It asks only for what the command line did not already supply, so the command above, which names the directory, gets three questions rather than four. Those are which runtime to target, which plugins to include, and which sign-in methods to add. Run
pnpm create plumix-appwith no directory and it asks where to create the project first. Node is the default runtime, running as a plain process against a local SQLite file; pass--runtime cloudflarefor a Worker against D1 instead. Passkeys are always on, so the sign-in question is about what to layer beside them. The plugin question opens with SEO and Feeds ticked, so a new site serves head meta,robots.txt, a sitemap and feeds from the first request; nothing else is preselected. Untick either and the generated project has no import and no registration for it. One pairing is worth knowing before you do:ogdeclares SEO as a peer and needs it registered to reachog:image, so unticking SEO while keeping OG installs the package without wiring it up. -
Let the post-scaffold steps run. The scaffolder installs dependencies, runs
plumix migrate generateandplumix migrate apply --local, then initializes a git repository and makes one commit. Each step is skippable with a flag, and none of them throws, so a failure never leaves you without a project.The three do not report failure equally. A failed install and a failed database setup are both named in the output, and the printed next steps then carry the commands to finish by hand. The migration steps run the installed
plumixbinary, so they are skipped whenever the install did not succeed, with no message saying they were skipped. Git reports nothing either way. A failedgit init, or a commit rejected for want of a configured git identity, prints no warning and no recovery step, andgit initis skipped outright when the target directory is already inside a repository. -
Start the dev server. On the default Node runtime, the scaffolded config pins the passkey origin to port 3000:
Terminal window cd my-sitepnpm dev -- --port 3000Vite serves the site at
http://localhost:3000, against a local SQLite file. On--runtime cloudflare, run plainpnpm devinstead — it serves athttp://localhost:5173, against a local D1 database in.wrangler. -
Claim the admin account. Open
http://localhost:3000/_plumix/admin(:5173on Cloudflare). With no users in the database, the admin sends you to “Create admin account”. Enter an email and an optional name, submit, and the browser runs the WebAuthn ceremony. The account you create this way is an admin. The role is decided inside the insert statement itself, so two people submitting the form at the same moment cannot both be elected. -
Confirm the public site renders. Open
http://localhost:3000(:5173on Cloudflare). The scaffolded theme greets you and links back to the admin.
Registration closes after the first account
Section titled “Registration closes after the first account”The passkey registration endpoint counts the users table before it issues a challenge. Zero rows means bootstrap, and the request is allowed without a session. One row or more means registration is closed, and an unauthenticated request is refused with registration_closed. An already-signed-in user hitting the same endpoint is adding a device instead, and the email in the request has to match their own.
So the first person to reach a fresh deploy owns it. Deploy and claim the account in the same sitting, or gate the deploy until you have.
Scaffolding without the wizard
Section titled “Scaffolding without the wizard”Every prompt has a flag, and --yes accepts the defaults for whatever you did not pass. That combination is what makes the scaffolder usable from a script or a CI job, where there is no terminal to prompt into. The wizard only runs on a real TTY and never under CI.
pnpm create plumix-app my-site --plugins blog,pages,media,seo,feeds --auth oauth --pm pnpm --yesThe flags are:
--runtime <id>picks the runtime,nodeorcloudflare. Defaults tonode.-p, --plugins <ids>takes a comma-separated list. The ids areblog,pages,menu,comments,media,audit-log,og,seoandfeeds. Leave the flag off and you getseoandfeeds. The flag replaces that pair rather than adding to it, so--plugins blogscaffolds blog alone, and--plugins=scaffolds none.--auth <ids>adds sign-in methods to passkeys, as a comma-separated list:oauthfor GitHub,magic-link, andcfAccessfor Cloudflare Access on thecloudflareruntime. Leave it off and you get passkeys alone. An unknown id exits with the list of methods the runtime offers.--pm <name>picksnpm,pnpm,yarnorbun. Without it you getnpm. An unrecognised name exits with an error rather than falling back.--no-installskips the dependency install.--no-dbskips generating and applying the local migration.--no-gitskipsgit initand the first commit.-y, --yesaccepts defaults for everything not flagged.
Skipping a step is not skipping the work. A project whose migration never ran fails on the first request with a missing-table error, so run them yourself:
cd my-sitepnpm installpnpm exec plumix migrate generatepnpm exec plumix migrate apply --localplumix migrate generate writes the resolved schema to .plumix/schema.ts and hands it to drizzle-kit, which emits SQL into drizzle/. The tables come from core plus whatever tables your plugins declare, so adding a plugin that carries its own tables means generating again. plumix migrate apply --local runs those files against the local D1 database.
Adding a sign-in method later
Section titled “Adding a sign-in method later”The wizard’s sign-in question saves you an edit. It locks nothing in. Picking GitHub OAuth adds a github(...) provider to the auth block and writes GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET into .dev.vars. Picking magic links adds a magicLink block and sets mailer: consoleMailer(), which logs the sign-in link to the terminal instead of sending mail. Both are edits to plumix.config.ts you can make by hand afterwards.
Cloudflare Access appears in the same list when the runtime is Cloudflare. It replaces the request authenticator rather than adding a login form, so the identity provider in front of the worker decides who the user is.
Related
Section titled “Related”Project Structure is the file-by-file account of what the scaffolder just wrote. Configuration is the reference for the config file it assembled. Passkeys covers the WebAuthn ceremony, the relying-party id and adding a second device. Secrets covers .dev.vars, EnvInput and production secrets. Plugins covers installing and configuring the nine official plugins.
Next steps
Section titled “Next steps”Read Project Structure next, then model something. Content Modelling shows how a local plugin registers an entry type, a taxonomy and a meta box, and it is the page every later section assumes you have read. When the model is settled, Deploy Your Site takes the project to a live URL.