Creating a Project
sigx create scaffolds a new SignalX project. Run it without installing anything:
pnpm create @sigx@latestor, if the CLI is already available, npx sigx create. With no flags you get an interactive wizard; with flags it runs headlessly and never touches the network or your git config unless you ask it to.
A project is composed from your choices rather than copied from a fixed template folder: a kind, a render mode and deploy target for server-rendered apps, a styling preset, and any extras are layered together into the file tree. Every combination is generated from the same set of layers, so a router-plus-i18n SSR app on Cloudflare is as first-class as the plain SPA.
The wizard
pnpm create @sigx@latestThe prompts, in order:
- Project name — validated as you type: no path separators, and the directory must not already exist.
- How do you want to start?
- Quick start — web app (SPA) + Tailwind + router + tests. A good default.
- Mobile app — an iOS and Android app with Lynx and daisyUI components (
--kind lynx --styling daisyui). Skips to the package manager question. - Customize — the questions below.
- What are you building? — the kind.
- Rendering and Deploy target — SSR only. Picking
vercel-edgeprints a heads-up that the Edge runtime is Web APIs only, with no Node built-ins or filesystem in server code. - Styling — skipped for terminal apps, which have no styling option.
- Extras — a multiselect showing only the extras your kind, render mode and target actually support. Skipped when none apply.
- Package manager — defaults to the one that ran
create(fromnpm_config_user_agent), falling back to the nearest lockfile. - Install dependencies? — defaults to yes.
- Initialize a git repository? — defaults to yes, or to no when you are already inside a repository (the prompt says so).
- Summary and confirmation. Answering no takes you back through the shape questions once.
Then it scaffolds, installs and initializes git as separate spinner phases, and prints the next steps for your package manager. A failed install never fails the run — the project is written, the tail of the install output is shown, and the install command is added to the next steps so you can retry it yourself. If git is not installed, the repository step is skipped with a note.
Esc or Ctrl+C at any prompt exits with code 130.
Flags combine with the wizard: pass any that shape the project and it skips the How do you want to start? question and uses your flags as the prompts' initial values.
To print the options without scaffolding anything:
pnpm create @sigx@latest -- --helpHeadless mode
create runs headlessly — no prompts — when any of these is true:
- stdin or stdout is not a TTY (CI, or piped output),
-y/--yesis passed,- a kind is given (
--kind,--typeor--preset) together with a positional name.
Headless never installs dependencies and never initializes git unless --install / --git say so, which keeps it safe in CI.
sigx create my-app --kind ssr --render resume --target cloudflare \
--styling tailwind --features server-fn,testing --pm npm -y
Flags
| Flag | Values | Default | Description |
|---|---|---|---|
name (positional) | a directory name | my-sigx-app | Target directory, created under the current folder. |
--kind | spa, ssr, ssg, terminal, lynx | spa | What to build. See Kinds. |
--type | basic, ssr, ssg, terminal, lynx | — | Deprecated alias of --kind; basic means spa. Giving both with different values is an error. |
--render | hydrate, islands, resume | hydrate | SSR only. See Render modes. |
--target | node, cloudflare, bun, deno, vercel, vercel-edge, netlify | node | SSR only. See Deploy targets. |
--styling | none, tailwind, daisyui | none | Stylesheet preset. Terminal apps take none. |
--features | comma-separated: router, i18n, testing, server-fn | — | Extras. See Extras. |
--pm | pnpm, npm, yarn, bun, deno | detected | Package manager the scripts and next steps are written for. |
--install / --no-install | — | off in headless | Install dependencies after scaffolding. |
--git / --no-git | — | off in headless | git init plus a first commit. |
--preset | quick | — | SPA + Tailwind + router + testing. |
--yes / -y | — | — | Skip the prompts. |
--list | — | — | Print every kind, render mode, target, styling and extra this build can generate, then exit. |
--help / -h | — | — | Print the options and a few examples, then exit without scaffolding. |
--render and --target apply to --kind ssr only; passing them with any other kind is an error.
Exit codes — 2 for an invalid or contradictory flag, 1 when scaffolding itself fails (for example the target directory already exists), 130 when you cancel a prompt.
To see exactly what your installed version can generate:
sigx create --list
Kinds
--kind | What you get |
|---|---|
spa | Client-rendered single-page app on Vite. |
ssr | Server-rendered web app — streaming, islands or resumable, deployable to seven targets. |
ssg | Static site with @sigx/ssg — file-based routing, MDX, built-in search. |
terminal | Terminal UI with @sigx/terminal — TSX + signals, HMR dev runner. |
lynx | Native iOS and Android app with SignalX Lynx from one component tree. |
basic is the legacy name for spa and still works through --type.
What each kind generates
Every project ships a README.md describing its layout, scripts and how to deploy, plus a .gitignore — with commands spelled for the package manager you chose.
spa
index.html vite.config.ts tsconfig.json package.json
src/main.tsx src/App.tsx src/components/Counter.tsx src/styles.css src/env.d.ts
public/favicon.svg
dev → vite, build → vite build, preview → vite preview.
ssr (target node shown)
index.html server.mjs vite.config.ts tsconfig.json package.json
src/entry-server.tsx src/entry-client.tsx src/App.tsx
src/components/Counter.tsx src/styles.css src/env.d.ts
public/favicon.svg
src/entry-server.tsx exports a per-request createApp(url) factory — each call builds a fresh app, so nothing is shared between concurrent requests. server.mjs is plain Node with two modes: Vite middleware plus createDevRequestHandler in dev, and static assets plus createRequestHandler over dist/server/sigx-app.js in production. Crawlers and AI agents are served the blocking document render; everyone else gets the streaming one.
dev → node server.mjs, build → vite build --app (one build for client and server), start → node --conditions production server.mjs.
ssg
ssg.config.ts vite.config.ts tsconfig.json package.json pnpm-workspace.yaml
src/pages/index.mdx src/pages/about.mdx src/layouts/default.tsx
src/components/Counter.tsx src/styles/global.css src/env.d.ts
public/favicon.svg
The stylesheet stays at src/styles/global.css and @sigx/ssg generates the HTML template. dev / build / preview map to sigx dev / sigx build / sigx preview.
terminal
tsconfig.json package.json pnpm-workspace.yaml
src/main.tsx src/App.tsx
dev → sigx-terminal-dev src/main.tsx (HMR), start → tsx src/main.tsx, plus a typecheck script.
lynx
lynx.config.ts signalx.config.ts tsconfig.json package.json
src/main.tsx src/main.thread.tsx src/App.tsx src/lynx-env.d.ts
assets/icon.png assets/splash.png assets/adaptive-foreground.png
The app starts on the Lynx release line your CLI was released against, with @sigx/lynx and every @sigx/lynx-* package on one caret range, so it can declare a typed, per-variant env in signalx.config.ts from the start.
--styling tailwind and --styling daisyui add tailwind.config.ts, postcss.config.js and src/styles.css; daisyUI also adds @sigx/lynx-daisyui and wraps the app in its ThemeProvider. With --pm pnpm, a pnpm-workspace.yaml allows the esbuild and sharp install scripts (see below).
| Script | Runs |
|---|---|
dev | sigx dev |
build | sigx build |
doctor | sigx doctor |
native:prebuild | sigx prebuild |
run:android / run:ios / run:web | sigx run:android / sigx run:ios / sigx run:web |
The native prebuild script was named prebuild before @sigx/cli 0.13. npm runs a script with that name as a pre-hook of build, so every npm run build regenerated the Android and iOS projects. In an older app, rename it to native:prebuild.
The next steps are npx sigx doctor and npm run run:android, spelled for your package manager (for example pnpm exec sigx doctor and pnpm run:android). sigx is a local dev dependency, so it runs through the package manager rather than as a bare sigx. See the Lynx getting-started guide for the toolchain.
Render modes
SSR projects choose how the page reaches the browser.
--render | Behaviour |
|---|---|
hydrate | Streaming SSR with full client hydration — the classic shape. The default. |
islands | A server-only page whose components hydrate individually per client:* directive, with an app-less hydrateIslands() client. See @sigx/ssr-islands. |
resume | Zero JavaScript on load; handlers are extracted into chunks and load on first interaction, with refreshComponents and createBoundaryRefresh wired for single-flight boundary refresh. See @sigx/resume. |
Deploy targets
Each target contributes its platform entry, its config, the Vite adapter, and deploy / start scripts, plus a deploy section in the generated README.
--target | Entry & config | Run / deploy |
|---|---|---|
node (default) | server.mjs (Express) | node --conditions production server.mjs |
cloudflare | src/entry.cloudflare.ts, wrangler.jsonc | wrangler deploy (wrangler dev to preview) |
bun | server.bun.ts | bun --conditions=production server.bun.ts |
deno | src/entry.deno.ts, deno.json | deno deploy |
vercel | src/entry.vercel.ts | vercel deploy --prebuilt |
vercel-edge | src/entry.vercel.ts (Edge runtime) | vercel deploy --prebuilt |
netlify | src/entry.netlify.ts, netlify.toml | netlify deploy --prod --no-build |
Every target develops the same way. dev is always the Vite dev server through server.mjs, whichever platform you deploy to — the platform entry is what build bundles and deploy ships. Express is a dev-only dependency everywhere except the node target.
vercel-edge runs on the Edge runtime: Web APIs only, no Node built-ins and no filesystem in server code.
For the platforms themselves, see the deployment guides.
Extras
--features takes a comma-separated list; the wizard offers the same set as a multiselect, filtered to what your other choices support.
| Feature | Adds | Available for |
|---|---|---|
router | @sigx/router, src/router.ts, Home/About pages, <RouterView />, createWebHistory in the browser and a per-request createMemoryHistory on the server | SPA, SSR (hydrate) |
i18n | @sigx/i18n, an app namespace in English and Swedish under src/locales/, lazy catalogs, ?lang=/cookie/browser detection, SSR preload and state transfer, a language switch | SPA, SSR (hydrate) |
testing | Vitest on happy-dom and oxlint, test and lint scripts, vitest.config.ts, .oxlintrc.json, and a sample test that mounts the app (or the Counter island on a static site) | SPA, SSR, SSG |
server-fn | @sigx/server, src/api/hello.server.ts declared with serverFn, read from a component with useData, and sigxServer() in vite.config.ts | SSR (any render mode or target) |
Router and i18n need a hydrated client, which is why they are hydrate-only — islands and resumable pages have no client app to route. Server functions compose into whichever platform entry you chose, so a plain hydrated app ships none of that code.
An extra that your kind, render mode or target cannot take is an error, not a silent no-op.
Versions and install scripts
Generated projects pin the matched sigx / @sigx/* set that your CLI was released against — never latest — so a fresh project's peer graph resolves to a single copy of @sigx/reactivity under strict peer deps. Third-party dependencies (vite, express, tailwindcss, …) keep their own caret ranges. The current CLI is v0.14.0.
TypeScript. Web, SSR, SSG and terminal projects scaffold on TypeScript 7 (typescript ^7.0.2, the native tsc), and their typecheck script runs it. Lynx projects stay on TypeScript 6 (^6.0.3): the Lynx build tool, @lynx-js/rspeedy, declares a typescript peer range of 5.1.6 - 6.0.x and loads lynx.config.ts through the TypeScript JS API, which TypeScript 7 doesn't ship. Keep a Lynx app on TypeScript 6 until the templates move.
Some projects need dependencies to run their install scripts: esbuild for SSG and terminal projects, and esbuild plus sharp for Lynx apps. With pnpm they ship a pnpm-workspace.yaml declaring them under both spellings — allowBuilds for pnpm 11, onlyBuiltDependencies for pnpm 10. Without it pnpm skips the scripts, and pnpm 11 fails the install outright (ERR_PNPM_IGNORED_BUILDS).
If you scaffold inside an existing pnpm workspace, @sigx/* dependencies in the generated package.json are rewritten to workspace:*.
Where to go next
- Commands — every command with its usage and flags.
- Deployment — the platform guides behind each
--target. - Installation — which plugin package provides which command.
