CLI Scaffolder
Generate a production-ready Nexa-connected school app with one command.
create-nexaed-app scaffolds a complete Next.js school app with routing, auth, a results dashboard, and payment support already wired up. It's the fastest way to go from zero to a working integration.
Info
Prefer a visual interface? Try the Stack Builder → — click to select your auth provider, features, email tier, and package manager, then copy the generated command.
Commands
Info
No npm/npx on your machine? Every command in this page also works with pnpm dlx create-nexaed-app <args> in place of npx create-nexaed-app <args>.
Warning
pnpm 11 ships a 24-hour supply-chain gate (minimumReleaseAge, default
1440 minutes) that hides any release published in the last day from
@latest resolution. So a freshly published scaffolder is invisible to an
unpinned pnpm create nexaed-app for a day — this is pnpm's default, not a
cache and not your config. From 0.3.0-beta.8 the CLI works around it for
you: it checks the registry before generating anything and silently
re-runs your command against the newest release (exact versions bypass the
gate). Only a copy older than that release is stuck, and it stops being stuck
once the newest guard passes 24 hours. To force a specific version now:
pnpm dlx [email protected] my-school, or --pin 1.2.3 inside a
project that already has a newer copy. NEXAED_SKIP_UPDATE_CHECK=1 opts out
of the hand-off entirely.
Run the scaffolder
That's the whole command. Everything it doesn't ask you about has a default, and every question you skip with a flag is one it would have asked interactively — so the shortest command and the fully-flagged one produce the same app.
Interactive prompts
The CLI asks only what your command didn't already say:
| Prompt | Options |
|---|---|
| School name | Used as directory name and package.json#name |
| Auth provider | WorkOS · Clerk · NextAuth · None |
| Features | File processing, Payments, Convex integration, Student email provisioning |
| UI library | None (plain Tailwind) · shadcn/ui |
| Initialize git? | Yes (default) · No |
| Email tier + domain | Only when student email provisioning is selected |
| Nexa API key | Optional — can be added to .env.local later |
Non-interactive / CI mode
All prompts can be bypassed with flags. Use this in CI pipelines, Dockerfiles, or shell scripts:
| Flag | Description |
|---|---|
--auth | workos · clerk · nextauth · none |
--features | Comma-separated: fileProcessing, payments, convex, emailProvisioning |
--ui | none (default) · shadcn |
--email-tier | tier-1-nexa · tier-2-stalwart · tier-3-google |
--email-domain | Your school domain (required for tier 2/3) |
--api-key | Pre-fill the Nexa API key in .env.local |
--pm | pnpm · npm · yarn · bun |
--no-install | Skip dependency installation |
--git | Initialize a git repository and create an initial commit |
--no-git | Skip git initialization |
--pin <version> | Keep this exact scaffolder version instead of handing off to the newest release |
When stdin is not a TTY, the non-interactive fast path activates automatically — no flags needed in most CI environments.
Environment variables
Every flag has an env-var equivalent, which is handy in Dockerfiles and CI YAML where a long command line is awkward. Flags win over env vars, and anything left unset falls back to the interactive prompt (or its default in CI):
| Env var | Flag |
|---|---|
NEXAED_PROJECT_NAME | project name argument |
NEXAED_AUTH | --auth |
NEXAED_UI | --ui |
NEXAED_FEATURES | --features |
NEXAED_EMAIL_TIER | --email-tier |
NEXAED_EMAIL_DOMAIN | --email-domain |
NEXAED_API_KEY | --api-key |
NEXAED_PM | --pm |
NEXAED_GIT | --git / --no-git (1 / 0) |
NEXAED_NO_INSTALL | --no-install |
NEXAED_SKIP_UPDATE_CHECK | opt out of the automatic hand-off to the newest release |
Mistakes don't abort the run
A typo'd value (--auth wokos, --features paymetns) prints what it didn't recognise, keeps the
values it did, and continues with defaults — it never deletes or overwrites a non-empty project
folder, and if the name you gave is taken it asks for a new one.
doctor — validate an existing app
Run doctor inside an existing Nexa-powered school app to check for common setup issues:
Runs 5 checks:
| Check | What it verifies |
|---|---|
| Env vars | NEXA_API_KEY and NEXA_WEBHOOK_SECRET present in .env.local |
| Packages | Required @nexa-ed/* packages listed in package.json |
| Route | Catch-all app/api/nexa/[...nexaed]/route.ts exists |
| SDK version | Your installed version vs latest on npm |
| API key | Live request to the Nexa platform confirms the key is valid |
upgrade — update SDK packages
Updates all @nexa-ed/* dependencies in the current project to @latest:
The package manager is detected automatically from your lockfile.
skill — teach Claude Code the SDK
Every app scaffolded with init already gets this installed at .claude/skills/nexa-ed-sdk. If you're adding Nexa-Ed to an existing app instead of scaffolding a new one, install it explicitly:
This drops a Claude Code skill into .claude/skills/nexa-ed-sdk/ — a SKILL.md plus reference files covering createNexa/createRouteHandler setup, every NexaClient module's real method signatures, the verified @nexa-ed/react component/hook list, and webhook/error handling. Claude Code picks it up automatically the next time you ask it to work with the SDK in that project — no MCP server or extra config required. It's kept in sync with the SDK source (not just the docs), and calls out a few places where these docs pages currently lag the source.
What gets generated
The generated lib/nexa.ts varies by auth provider:
After scaffolding
Follow these steps to get the app running:
1. Install dependencies
2. Fill in environment variables
Open .env.local and set:
Both come from Nexa dashboard → API key — Nexa signs webhooks with your API key, so NEXA_WEBHOOK_SECRET is just a second copy of it. Update both whenever you rotate the key.
3. Connect Convex (only if you chose the convex feature)
This logs you in, creates or attaches a deployment, and generates
convex/_generated/api from the mounts in convex/nexa.ts. Until it has run
once, api.nexa.* does not exist and pnpm check-types will fail — the CLI
cannot do this step for you because it needs your Convex account.
4. Register webhook URLs
In the Nexa dashboard, add:
| Event | URL |
|---|---|
file.completed | https://your-domain.com/api/nexa/webhook |
payment.completed | https://your-domain.com/api/nexa/payments/forward |
If you provision student emails, email.* events need a route you write yourself (there's no built-in path for them) — see Webhooks → Email events.
Use ngrok to expose localhost:3000 while developing.
5. Start the dev server
Open http://localhost:3000/dashboard — your results viewer is live.
What's next
- Quickstart — understand what each generated file does
- File Processing — submit PDFs and stream OCR progress
- Payments — collect enrollment fees
- Student Emails — provision student email accounts across all three tiers
- Domain Setup — verify your domain to unlock Tier 2/3 email and your live key
- React Components — customise the pre-built UI