Kosmesis
Guide

Getting Started

Install the Kosmesis CLI and add your first component.

Prerequisites

Kosmesis expects a create-praxisjs-scaffolded project (the minimal, full, or router template all work) using Vite. If you don't have one yet:

npm create praxisjs@latest my-projectcd my-project
pnpm create praxisjs my-projectcd my-project
yarn create praxisjs my-projectcd my-project
bun create praxisjs my-projectcd my-project

Setup

Run init

From the root of your PraxisJS project:

npx kosmesis init
pnpm dlx kosmesis init
yarn dlx kosmesis init
bunx kosmesis init

This will:

  • Write a components.json config file.
  • Add @import "tailwindcss"; plus Kosmesis's theme tokens (--background, --foreground, --primary, ...) to your global stylesheet.
  • Wire the @tailwindcss/vite plugin into your vite.config.ts.
  • Create src/lib/utils.ts exporting a cn() helper (clsx + tailwind-merge).

Add a component

npx kosmesis add button
pnpm dlx kosmesis add button
yarn dlx kosmesis add button
bunx kosmesis add button

This copies button.tsx into src/components/ui/button.tsx. If the component wraps a Morphos primitive, its package (e.g. @morphos/inputs) is installed automatically.

Use it

import { Button } from "@/components/ui/button";

@Component()
class MyPage extends StatefulComponent {
  render() {
    return <Button variant="outline">Click me</Button>;
  }
}

@/components/ui/... assumes a @/* → ./src/* path alias in tsconfig.json. Add one if your create-praxisjs template doesn't already have it, or adjust the aliases in components.json to use relative imports instead.

Non-interactive setup

Every init question has a flag. With --yes (or --defaults) nothing is asked: each choice you don't pass takes its default. Handy for scripts, CI and other CLIs.

npx kosmesis init --yes --style-system praxisjs-css --icon-library none
FlagAnswersDefault with --yes
--style-system <tailwind|praxisjs-css>Which styling system to usetailwind
--icon-library <lucide|none>Which icon library to wirelucide
--css <path>Global stylesheet (Tailwind) or theme module (@praxisjs/css)src/style.css / src/lib/kosmesis-theme.ts
--root-component <path>Root component that gets @Themed(...) / @IconProvider(...)src/app.tsx
--erase / --no-eraseErase what the stylesheet or theme module already has, instead of keeping it below Kosmesis's tokens (with Tailwind, inside @layer base)keep it
--overwrite / --no-overwriteReplace an existing components.jsonstop
--forceContinue in a project without @praxisjs/corestop
-y, --yes, -d, --defaultsDon't prompt

With --yes, nothing is erased or overwritten unless its flag says so. When a run needs an answer only --overwrite or --force can give, it stops with exit code 1 and names the flag. Without --yes, flags still answer their question and init asks only the rest. kosmesis init --help prints the list.

New PraxisJS projects can start with Kosmesis already set up: create-praxisjs asks for it (or takes --kosmesis), and praxisjs add kosmesis adds it to a project you already have. Both run kosmesis init with these flags. See the PraxisJS quickstart.

Fetching from another registry

Every component so far came from components.json's default registry field (https://kosmesis.praxisjs.org/r). There are two ways to pull from somewhere else:

One-off, for a single add:

npx kosmesis add button --registry ./packages/registry/dist/r

Persistent, addressed by name: register a namespace once, then reference it directly whenever you add a component — no flag needed, and it works alongside the default registry in the same add call.

npx kosmesis registry add acme https://ui.acme.internal/r
npx kosmesis add @acme/button
npx kosmesis add @acme/button badge   # mixes a namespaced and a default-registry component
CommandWhat it does
kosmesis registry add <namespace> <url>Saves <url> under @<namespace> in components.json, so @<namespace>/<component> resolves there from now on.
kosmesis registry listPrints the default registry and every configured namespace.
kosmesis registry remove <namespace>Forgets a namespace.

<url> (for both --registry and kosmesis registry add) can be a local directory (handy while developing components) or an http(s):// base serving the same <styleSystem>/<name>.json shape.

Whichever registry resolves a component is trusted at install time: its files are written to disk as-is and its dependencies are installed automatically. Only add a namespace, or pass --registry, for a registry you trust — the same way you'd only add an npm registry mirror you trust.

Want to serve your own components this way? See Custom Registry.

Updating a component

kosmesis add records each component's version, and a hash of every file it wrote, in components.lock.json (commit it). When a registry publishes a newer version:

npx kosmesis outdated          # what has an update, and which of your copies you edited
npx kosmesis update button     # shows the diff and asks before writing anything

Files you edited are never replaced without asking. See Updating Components.

On this page