Scaffolders
Project-local Bun scripts that scaffold incremental additions to an existing Remix v3 project. The official cli does bootstrap + audit + inspect; these handle the day-to-day "add one route", "add one resource", "add one migration" operations.
Each script:
- Reads
app/routes.tsandapp/router.tsfrom the working directory - Refuses to overwrite existing files (exit 2)
- Prints exactly what it changed
- Validates inputs (camelCase identifiers, escaped patterns, etc.)
Available scaffolders
| Script | What it does |
|---|---|
init-project.ts |
Alternative to remix new — scaffolds the whole project layout |
create-route.ts |
Add a single route + handler + router.map() wiring |
create-resource.ts |
Add a resources(...) block + 7-action controller |
create-controller.ts |
Stub a controller for an existing RouteMap entry |
create-migration.ts |
Drop a timestamped migration file under db/migrations/ |
add-middleware.ts |
Insert a built-in middleware in canonical position |
All live under scripts/ in this plugin.
Usage
# Bootstrap (alternative to `remix new`)
bun run scripts/init-project.ts --name my-app --app-name "My App"
# Incremental additions
bun run scripts/create-route.ts --name about --pattern //about
bun run scripts/create-resource.ts --name reviews --param reviewId
bun run scripts/create-resource.ts --name books --param bookId --only index,show
bun run scripts/create-controller.ts --route admin.books
bun run scripts/create-migration.ts --name add_reviews_table
bun run scripts/add-middleware.ts --name session
bun run scripts/add-middleware.ts --name csrf
bun run scripts/add-middleware.ts --name cors
When to use which
| Goal | Use |
|---|---|
| Brand new project | remix new (cli) — official, canonical |
| Brand new project, no network / no CLI access | init-project.ts (this plugin) |
| One new route | create-route.ts |
| Full REST surface for a resource | create-resource.ts |
Existing route in routes.ts, missing controller file |
create-controller.ts |
| New migration | create-migration.ts |
| Add session, csrf, logger, etc. to router.ts | add-middleware.ts |
| Auto-fix small layout drift | remix doctor --fix (cli) |
Why these and not the CLI
remix doctor --fix is repair-oriented (rename mis-cased files, restore missing-but-defaultable fields, etc.). It doesn't add new entities.
These scaffolders are add-oriented:
create-routeknows how to updateroutes.tsAND wirerouter.tsAND stub the handler — three coordinated edits.create-resourcegenerates the right 7-action mirror thatController<typeof routes.X>expects.add-middlewaresorts entries by canonical stack order (socsrf()lands betweensession()andasyncContext(), not at the bottom).create-migrationproduces the correct filename timestamp +createMigration({up, down})skeleton.
Argument quoting on Git Bash (Windows)
Bun on Git Bash inherits the MSYS path-mangling quirk: a leading / in an argument gets expanded to a Windows path. Use // to escape:
bun run scripts/create-route.ts --name about --pattern //about
# Without the double slash, `/about` becomes `C:/Program Files/Git/about`
The scaffolder detects this and exits with a helpful error if it sees a Windows-path-looking pattern.
Running under Node instead of Bun
node --experimental-strip-types scripts/init-project.ts --name my-app
Node ≥ 22.6.0 with the flag works. Node ≥ 23 has it on by default.
Verification
Every scaffolder is smoke-tested by bun run scripts/verify.ts against the real Remix package. If a scaffolder regresses, the pre-commit hook blocks the commit. See scripts/README.md for the full harness.
Further reading
references/local-scaffolders.md— full per-script reference (flags, edge cases, idempotency contract)- See also: cli (official CLI), migrations, middlewares