Ramonda

create-ramonda

create-ramonda starts a project: it asks a few questions, writes a project that builds, and installs it. It needs Node 24 or newer, and stops with a message on anything older.

npm create ramonda@latest my-app

my-app is the folder it writes into. Leave it out and it asks, offering ramonda-app.

What it asks, and the flag for each

Every question has a flag. A question a flag answers is not asked.

QuestionFlagDefault
Where should the app go?the folder, as the first argumentramonda-app
How should it render?--mode spa or --mode ssrspa
Add packages and tooling?--add <list>, comma-separated, or --add nonecss,devtools
Initialise a git repository?--git or --no-gityes
Install dependencies?--install or --no-installyes, with the package manager that ran it
The folder is not empty — write into it?--overwriteno

--yes (or -y) takes the default for every question no flag answers. It never writes into a folder that is not empty: that takes --overwrite, always. --help prints all of this; --version prints the version.

With npm, the flags go after --, which tells npm they are for the scaffolder:

npm create ramonda@latest my-app -- --yes
npm create ramonda@latest my-app -- --mode ssr --add css,query,testing --no-git

With no terminal

A script, a CI job or an agent has no terminal to answer a question in. There, every question must be answered by a flag or by --yes. If one is not, the scaffolder writes nothing, names the flags that are missing, and exits with code 1.

How it renders

spa — the app runs in the browser. Vite serves it in development and builds it for production.

ssr — a small Node server renders each page to HTML, and the browser takes it over. Each route says how it renders: baked to a file at build time, cached and refreshed, or rendered per request. Server rendering is built on the router, so an ssr project always has it. Server rendering

The add-ons

The word in the first column is what --add takes.

--addAddsFor
css@ramonda/cssStyle blocks: the page written in blocks, a few tokens, and a strict ramonda.css.ts
router@ramonda/routerRouting: routes and links. Always there with ssr
query@ramonda/queryAsync data, cached and race-free
form@ramonda/formForms with typed fields and schema validation
lens@ramonda/lensImmutable updates to nested state
testingvitest, @ramonda/testing-library and jsdomTesting, with one test to start from
devtools@ramonda/devtoolsThe panel, in development only. A tab for each of query and form you also chose
biome@biomejs/biomeLint and format

Whatever you choose, every project also gets @ramonda/core, @ramonda/build and @ramonda/check. An ssr project also gets @ramonda/server and @ramonda/router.

A package you did not add at the start installs like any other later. The packages lists them all.

The scripts

ScriptWhat it runsThere when
devThe development server, with hot reloadalways
buildramonda-check, then typecheck, then the production build — and with ssr the pages baked at build time — then ramonda-check-bundle over what it emittedalways
build:bundlesThe production build alone, which build runs in the middlessr
typechecktsc --noEmit — or, with css, ramonda-css, which is the same check reading style blocks tooalways
checklint and test, where the project has them, then build — the one to run before a commitalways
testThe tests, oncetesting
test:watchThe tests, again on every changetesting
lint, formatbiome — and with css, ramonda-css lint src and ramonda-css format src for the files biome cannot readbiome
previewThe production build, served locallyspa
startThe production serverssr

ramonda-check proves what a running page cannot, such as a context consumer with no provider above it, from the source. ramonda-check-bundle reads what the build emitted, and fails on code a browser could not parse — decorators a bundler left untransformed. ramonda-css is described in Tooling.

The files

Both modes:

FileWhat it is
src/App.tsxThe app. With css, its page is written in style blocks
vite.config.tsVite, with ramonda() from @ramonda/build
tsconfig.json, index.html, README.md, .gitignoreWhat they are anywhere
pnpm-workspace.yamlFor pnpm only: it lets esbuild run its install script. npm and yarn ignore it, and it does not make the project a workspace

spa adds src/main.tsx, which mounts the app, src/style.css, and src/vite-env.d.ts for Vite's types. ssr adds:

FileWhat it is
src/entry-client.tsxTakes over the server-rendered page in the browser
src/entry-server.tsxSays how each route renders
server.mjsThe server, for dev and for start
scripts/build.mjs, scripts/prerender.mjsThe production build, and the pages baked at build time
global.d.tsTypes for import.meta.env

And per add-on: ramonda.css.ts and css-system/ with css; vitest.config.ts and src/App.test.tsx with testing; biome.json with biome. With devtools, the entry imports the panel inside if (import.meta.env.DEV), so a production build leaves it out.

Next