Skip to main content
A spa module is a standalone Vite single-page application that lives inside your project but runs on its own dev server — it is not part of the backend. The spa:create generator pulls the spa source from the upstream skeleton repository, marks the module as a spa in its yml config, links it to a design module, assigns a free dev port, and installs the spa dependencies. After it finishes you have a working frontend you can start with one command. If you are new to spa modules, read the spa overview first. This page is the friendly walkthrough; for the terse flag reference see spa:create.

CLI command

ooneex spa:create [options]
Run it with no flags and it prompts for everything it needs — the spa name and the design module.

Examples

# Interactive: prompts for the spa name and design module
ooneex spa:create

# Provide the name as a flag
ooneex spa:create --name=dashboard

# Link the spa to a design module
ooneex spa:create --name=dashboard --design=ui

Options

OptionDescriptionDefault
--nameSpa name. Normalized to PascalCase with any trailing Module stripped; the module folder uses its kebab-case form.Prompted if omitted
--designDesign module the spa uses. An existing design can be chosen interactively, or a new name is scaffolded.Prompted if omitted
--cwdProject directory the spa is created in.Current working directory
--silentSuppress prompts, spinners, and output.false
The command clones the spa source and installs packages, so it needs git and network access. If either is unavailable the create will not complete.
Every spa composes a design module — a type: "design" module that holds the shared UI building blocks. During create you choose which one:
  • Pick an existing design. If your project already has type: "design" modules, you choose one interactively (or pass it with --design).
  • Name a new one. Give a name that does not exist yet and the generator scaffolds it for you with design:create.
The choice is recorded as design: in the spa’s yml config, so the link between the spa and its design module is explicit and persistent.

What happens

When you run spa:create, the generator works through these steps in order:
1

Scaffold the base module

A base module is scaffolded under modules/<kebab-name>/, using the kebab-case form of the name you gave.
2

Detach it from the backend

A spa is a frontend, not part of the backend — so it is un-registered from AppModule and SharedModule, and its root tsconfig path alias is removed.
3

Remove the backend module class

The scaffolded <Pascal>Module.ts and its spec file are deleted; a spa does not ship a backend module class.
4

Mark it as a spa

The module yml is marked type: "spa" and records design: "<kebab>" for the design module you chose.
5

Add Vite scripts and assign a port

Vite dev, build, and preview scripts are added to the module package.json. The dev script gets a free dev port — 5000 by default, or the next free port if 5000 is taken (the generator scans other modules’ --port usage to find a free one).
6

Clone the spa source

The upstream skeleton-spa repo is cloned (shallow) into the module’s src/, and every shared/ sub-layer is ensured to exist via .gitkeep: assets, components, hooks, layouts, services, store, styles, types, and utils.
7

Install dependencies

The spa’s dependencies and devDependencies are installed into the project.
8

Scaffold the design module if needed

If the design module you chose does not exist yet, it is scaffolded via design:create.

What you get

You end up with a self-contained spa module under modules/<kebab-name>/ — its own Vite setup, a src/ populated from the skeleton, the full shared/ layer in place, a dedicated dev port, and a recorded link to its design module. See the spa structure for a tour of the generated layout.

Start and stop the spa

Run the spa from the project root with app:start. The --spa flag narrows the run to spa modules, so only the dev servers come up:
# Start every spa module on its assigned port
ooneex app:start --spa

# Start just one spa by name
ooneex app:start --spa=dashboard

# Run the spa alongside the api modules it talks to
ooneex app:start --api --spa
Vite serves the spa on the port assigned at create time. The spa is a frontend dev server, not a Docker service, so to stop it you interrupt the running process with Ctrl+C.
Running ooneex app:start with no flag starts the spa together with every api and microservice module — handy when the spa needs a live backend.

Next steps

Run the dev server

Start the spa from the project root with ooneex app:start --spa — Vite serves it on the assigned port.

Add features

Build out pages and flows with spa:feature:create.
To take the spa back out, see remove a spa.

Use with Claude and Codex

The generator ships a matching spa:create skill. It runs the scaffold and then guides your AI agent through what comes next — choosing or naming the design module, starting the dev server, and adding the first features. Initialize the skills once for your agent:
ooneex claude:init
Then ask Claude in natural language — it maps the request to the generator and runs it:
Prompt
Create a spa called dashboard that uses the ui design module.
For example, the prompt above maps to spa:create --name=dashboard --design=ui. For the full command reference, see spa:create.