npm.io
0.0.30 • Published yesterdayCLI

create-muten

Licence
MIT
Version
0.0.30
Deps
2
Size
345 kB
Vulns
0
Weekly
3.7K

ALPHA - STILL ON DEVELOPMENT

Muten is still under active development. We are currently in the alpha stage and are working on training models with Muten. Please keep in mind that improvements are being made gradually, and version 1.0 has not been released yet.

The official scaffolder for Muten: an AI-first frontend framework. One command bootstraps a complete, ready-to-run Muten app, so you never copy boilerplate by hand.

npm create muten@latest

Why this exists

Muten ships as two packages - the same split as vue create-vue:

  • @muten/core: the engine (compiler + runtime + Vite plugin). Your app installs it as a normal dependency and it stays up to date on its own.
  • create-muten (this package) - a tiny, zero-dependency CLI whose only job is to generate a new project already wired to the engine: index.html, the Vite config, a theme.muten, a first page and the right package.json.

You run create-muten once to scaffold; after that you just work inside your project.

Quick start

Every package manager has a create shortcut. create-muten detects which one you used and makes it the default for the rest of the prompts:

npm  create muten@latest        # npm
pnpm create muten               # pnpm
yarn create muten               # yarn
bun  create muten               # bun

Prefer no install step? Run it on demand with npx, optionally naming the folder:

npx create-muten my-app

Or install it globally and reuse the command anywhere:

npm i -g create-muten
create-muten my-app

Then start the app:

cd my-app
npm install        # only if you skipped the auto-install
npm run dev

What it asks

In an interactive terminal it prompts for a few things (defaults in parentheses):

Prompt Options Default
Project name any valid folder name muten-app
Styling CSS / SCSS / Tailwind CSS / DaisyUI (brings Tailwind) CSS
Add Vercel deploy config? Y / n n
Desktop app (Tauri)? Y / n n
Package manager npm / pnpm / yarn / bun the one that launched it
Install deps and start dev now? Y / n Y

Styling is one explicit choice: each is opt-in, nothing is bundled by default: CSS (plain) or SCSS ship no framework; Tailwind CSS adds @tailwindcss/vite + @import "tailwindcss"; DaisyUI adds its component classes on top (and brings Tailwind). You always style via class("…").

Targets are independent opt-ins: web, desktop, both, or neither, from the same .muten source:

  • Vercel writes a vercel.json so muten's real-path routes don't 404 on a hard refresh (SPA fallback to index.html).
  • Tauri adds src-tauri/ (a native desktop app - ships the OS webview, not a browser) + a tauri script: npm run tauri dev / tauri build. Needs the Rust toolchain installed (not auto-installed).

Styling

There is ONE way to style: class("…"). When Tailwind or DaisyUI is added, theme.muten is centralized to match Tailwind's scale, so its emitted CSS vars line up with the utilities you write in class("…"); plain CSS/SCSS keeps the default scale and you read the same vars from src/styles.css. DaisyUI adds component classes (btn, card, modal) usable in class("…") - pure classes; behavior is Muten state + on().

If you accept the last prompt it runs <pm> install followed by <pm> run dev, your app is live in a single step. Choosing SCSS also adds sass and switches the stylesheet to .scss automatically.

Non-interactive (CI / scripts)

Pass the answers as arguments and it skips every prompt (this is also what runs when there is no TTY, e.g. in CI):

create-muten my-app --scss --pm pnpm      # full control
create-muten my-app --css --no-install    # just scaffold, decide later
Flag Effect
<name> the project folder (positional argument)
--css / --scss pick the stylesheet (default: css)
--tailwind add Tailwind CSS v4 on top of CSS (forces --css)
--daisyui add DaisyUI component classes (implies --tailwind)
--vercel add vercel.json (SPA fallback so real-path routes work on Vercel)
--tauri add src-tauri/ - a native desktop app (needs the Rust toolchain)
--pm <npm|pnpm|yarn|bun> package manager to use (default: detected)
--no-install scaffold only - don't install or start the dev server
--help print usage and exit
--version print the version and exit

What you get

A minimal, conventional Muten app:

my-app/
├─ index.html              # entry - loads /src/app.muten through the Vite plugin
├─ vite.config.mjs         # the @muten/core Vite plugin (dev server, HMR, routing)
├─ theme.muten             # your design tokens: spacing, fonts, weights, breakpoints
├─ package.json            # depends on @muten/core + vite
└─ src/
   ├─ app.muten            # the ROOT: routes (+ an optional persistent shell)
   ├─ styles.css           # your look (.scss if you chose SCSS)
   └─ pages/
      └─ home/home.muten   # a page - the folder name is its route

There is no hand-written main.js: the Vite plugin compiles src/app.muten into the app's entry, so the whole app is .muten from the first line.

What you can build

Honest framing first. muten isn't trying to beat React/Vue/Svelte at being general-purpose, they win there. muten wins when an AI builds and maintains the app: the whole language fits in context, a compiler (muten check) catches mistakes in milliseconds without a browser, edits stay tiny, and almost no JS ships. Best fit: the declarative 80% - CRUD, dashboards, catalogs, content, internal tools. For the rest, you don't fight it - you couple in other tech through bounded escapes. Reach for the lowest tier that works:

  • Pure muten: CRUD / SaaS / catalog / dashboard / content: pages, routing (paths are quoted strings: routes { "/" -> home "/404" -> notfound }; Link "label" -> "/path"; guard redirects else "/login"), state/store (with page->store action composition), query over REST, Form (text/number/email/bool/enum/date/password/textarea + validation), DataTable, when/each, SSG + SEO, and the bounded list toolkit: inline objects, patch where/remove where edits, each...where filter, aggregates (sum/count/avg/min/max by), sort/sortDesc by (literal field or a text state for a user-chosen column), take(n) pagination, toggle. use functions callable as statements inside action/effect (side effects: persist, scroll, analytics). on(enter: action) on inputs for Enter-to-submit without Custom. The declarative 80%, zero extra deps.
  • muten + the platform (no framework runtime) - native HTML (<input type="date">, <dialog>) + class(), CSS libs (Tailwind / DaisyUI), vanilla JS via Custom (charts, maps, date-pickers, rich-text, grids), use fmt from "./lib.ts" for any JS logic. Almost every "hard widget" lands here - muten ships zero framework runtime, so there is no React/Svelte escape; foreign UI comes in as a vanilla Custom component.

Deploy, honestly: npm run dev runs both tiers. For production:

  • muten build (CLI SSG) ships zero-JS HTML per route — now fully styled (it inlines the theme + project styles.css) and pre-rendered (it SSRs your store/query data). A no-bundler static export still can't bundle use functions (it warns) or persist store state across full-page navigations. Great for crawlable static/content pages.
  • vite build is the path for any stateful app. It bundles everything - use functions, Custom components, shared cross-page state - and is what most Muten apps ship with.

Most real apps use vite build.

Full reference (every primitive, the tiers, the roadmap): @muten/core.

Status: pre-1.0. The core (language, compiler, CLI, Vite plugin, extension) is solid; the ecosystem is young. Great for real apps, not yet for critical production.

Known limitations

These are honest gaps found during stress-testing. They are tracked; none are design mistakes.

  • muten build ships styled, SSR'd HTML, but a no-bundler static export can't bundle use functions or keep store state across full-page navigations (see Deploy above) — use vite build for a stateful app.
  • DataTable renders raw cell values; no per-column formatting yet (use each + a Part for formatted cells).
  • No standalone Select: a Form auto-generates one for enum fields; outside a Form, build a button group.
  • An Icon name is a static literal; a per-value icon is a match over static Icons, a data-URL icon is an Image.
  • Form renders all entity fields (no conditional fields), enum fields cannot be required. Field types: text/number/email/bool/enum/date/password/textarea (an unknown type is flagged unknown-field-type; drop it to a Custom).
  • query x live (WebSocket) requires the server to send an id per row for keyed diffing.
  • Custom inputs receive a snapshot of state at mount; pass state via @ props for reactivity.

Requirements

  • Node.js 18+
  • One of: npm, pnpm, yarn, bun

Cross-platform

create-muten is a Node CLI (not a shell script), so the exact same command works on Windows, macOS and Linux: npm generates the right launcher on each OS.

Keywords