@zero.sc/create
v0.0.5
Published
Create a Zero service — landing page, console shell, sign-in and ten locales already wired.
Maintainers
Readme
The problem this solves
A new service does not start at zero. It starts at the floor everything else already stands on
— a nav that is 56px, controls that are 32px, a sidebar that becomes a drawer below lg, ten
locales where a missing key fails the build, a theme that flips without a flash, and a sign-in
that goes through Zero ID rather than a password form written that afternoon.
Reaching that floor by hand takes a day and a half, and it is a day and a half spent reproducing
rather than deciding. Worse, each reproduction drifts: one service names its theme key
fz-theme, another theme, a third zero-theme. Six months later the ecosystem has eleven theme
keys and twenty locale keys, and a person who changes the language on one service finds the next
one still in English.
This command exists so that the floor is not something you build. It is something you are handed.
Use
pnpm create @zero.sc foo-zeroIt asks four questions. Every one of them is also a flag, so CI never has to answer a prompt.
pnpm create @zero.sc foo-zero --name "Zero Foo" --port 58910 --no-api -y| Option | Meaning |
|---|---|
| <slug> | Service identifier. Not ending in -zero gets a warning and a confirmation |
| --name | Display name. Defaults to Zero Foo — the Zero <Product> form, never Foo Zero |
| --port | Dev port. Defaults to the next free 100-block |
| --with-api / --no-api | Reserve an api surface port beside the web app |
| --accent | Personal colour hue, 0–359. Never prompted — see below |
| -y, --yes | Accept every default. Nothing is asked |
| --no-git | Skip git init, the branch convention and the v0.0.1 tag |
| --json | Emit one JSON object to stdout, for agents and CI |
| --selftest | Build into a temp directory and grade the eight elements. No network |
What you get
foo-zero/
├── src/
│ ├── app/
│ │ ├── page.tsx public landing
│ │ ├── console/ the shell, behind sign-in
│ │ ├── api/auth/ PKCE routes — @zero.sc/auth-client
│ │ ├── api/foo/ your surface, named after the slug
│ │ └── globals.css imports @zero.sc/ui/styles.css
│ ├── i18n/
│ │ ├── en.ts source of truth
│ │ └── dictionaries/ ko ja zh es ru hi th ar pt
│ ├── components/
│ └── lib/
├── public/favicon.svg the mark — favicon and logo are one file
├── Makefile make dev · build · deploy
├── service.json the manifest other services read
└── next.config.tsEight of those pieces are not code the template writes. They are packages it depends on, so a fix to the shell reaches every generated service through an install rather than a copy.
Two things it will not guess
The port has no default. The port map is a single source of truth held outside this package,
so a CLI that picked a free number would be inventing a fact. It asks, or it takes --port, and
it validates the range — but it never chooses.
The accent hue is never prompted. A personal colour has to be registered before it is used, or
two services end up 12° apart and nobody can tell them apart in a launcher. Passing --accent is
allowed because that means you registered it. Omitting it produces a placeholder hue and a
warning that says leaving it violates the shell contract — a loud default rather than a quiet
one.
The four things it refuses to get wrong
The display name is Zero <Product>. Type foo-zero and the name becomes Zero Foo. The
suffix form (Foo Zero), the all-caps form (ZERO Foo) and the bare form (Foo) are all
rejected, because the brand is the part that has to be recognisable and it goes first.
English is the source of truth, and a missing key fails the build. Each locale file is typed against the English dictionary, so an untranslated string is a typecheck error rather than a sentence that silently renders in the wrong language. Partial fallback is not offered — a screen that is half-translated reads as broken in a way a fully-English screen does not.
Local development does not ask you to sign in. make dev opens /console directly. It takes
three conditions to get there — an exact NODE_ENV, an explicit opt-in variable, and a loopback
address — and failing any one of them closes the door. The dev identity is visibly fake
(dev@localhost, with a LOCAL DEV badge in the nav) so it can never be mistaken for a session.
The narrow screen is the floor. Components are authored at 375px and widened with md: and
lg:, not authored wide and trimmed with max-*. The two orders produce different bugs, and the
second order produces them in every service at once.
After it finishes
cd foo-zero
make dev # port recovery → docker → dev server, one shotThe generated Makefile is the single entry point. It reclaims the port if something is holding
it, starts the containers it needs, and then runs the dev server — so a stale process from
yesterday is not a thing you debug this morning.
Related
| Package | What it carries |
|---|---|
| @zero.sc/ui | Tokens, components, layouts, the locale runtime |
| @zero.sc/auth-client | Zero ID sign-in — routes, middleware, the session check |
| @zero.sc/motion | Spring physics and the named signature effects |
| @zero.sc/kit | Copy a component into your repo instead of depending on it |
License
MIT OR Zero License v1.0 — take whichever you prefer. Choosing MIT is enough; nothing further is required of you.
The Zero name, marks and logos are not covered — build anything you like with this code, just don't present it as a Zero product. That includes the mark shipped as a favicon in generated projects: replace it with your own.
Copyright (c) 2026 Zero. Source Code begins at Zero.
