Hype StackHypeStack

Compose Your Stack

Packs are self-contained feature modules you install into an existing project. Each pack brings its own schema, routes, UI components, and migrations. The compose command lets you pick several at once and installs them in the right order.

Usage

bash
npx @hype-stack/cli compose

This opens an interactive picker that walks the three categories in order: one starter, one layout, then any feature packs. Billing is a one-of group, since a project takes a single provider. Installing anything needs a Hype Stack account, free packs included; compose opens the browser to sign in if you aren't. Free packs stay free. Paid packs you own are marked as owned; paid packs you don't own yet show their price and a lock.

Run it in a directory with no project and compose scaffolds one first with the create wizard, then installs your picks into it.

Use the wizard

You rarely need to hand-build the full command. Run npx @hype-stack/cli compose with no flags and the wizard walks you through picking packs, resolving dependencies, and handling licenses. Reach for the flags below only in CI or scripts where prompts aren't an option.

For CI or scripts, pass the packs directly:

bash
npx @hype-stack/cli compose --packs starter-saas-workos,pack-teams,pack-projects --yes

Pack families

Three groups of packs are interchangeable variants of one family: starters (starter-saas), layouts (layout), and billing (pack-billing). A family has one slot in a project. Ask for a second variant and compose refuses, with one exception: swapping a starter for one that provides more (the free starter-auth-betterauth to starter-saas-betterauth or starter-saas-workos) is an upgrade. The CLI replaces the files both starters ship, removes the ones only the old one had, and re-applies your layout. Your own files are never touched.

Packs depend on families, not on one engine. A calendar pack that needs a starter says starter-saas, and whichever starter your project has satisfies it.

Admin layout

When your project has an admin app, the picker asks once whether to copy the frontend layout for it, defaulting to yes. Say no and you get the full admin layout list, limited to the layouts the admin shell can actually render. To pin both sides yourself, suffix the pack with the shell it targets:

bash
npx @hype-stack/cli compose --packs layout-glass@frontend,layout-basic@admin

Theme, radius, and mode

compose takes the same look-and-feel flags as create, so one command reproduces a stack you built in the live preview:

bash
npx @hype-stack/cli compose --packs starter-saas-workos,layout-basic@frontend,pack-teams --theme ocean --radius 0.75rem --mode dark
FlagWhat it does
-t, --theme <theme>Frontend color theme.
--admin-theme <theme>Admin color theme. Defaults to --theme.
--mobile-theme <theme>Mobile app color theme. Defaults to --theme.
--extension-theme <theme>Extension color theme. Defaults to --theme.
--radius <value>Frontend corner radius as a CSS length, e.g. 0.75rem.
--admin-radius <value>Admin corner radius. Defaults to --radius.
--mobile-radius <value>Mobile app corner radius. Defaults to --radius.
--extension-radius <value>Extension corner radius. Defaults to --radius.
--mode <light|dark>Color mode the app boots in.

In an existing project compose only rewrites what you named: a plain compose never touches your styles.css.

All flags

FlagWhat it does
--packs <a,b,c>Install these packs without the picker. Layouts take an @frontend or @admin suffix.
--community <source>Also install a community pack. Repeatable.
--forceOverwrite files that already exist. Without it you are asked per file, and --yes keeps yours.
-y, --yesSkip confirmations. Keeps existing files, answers yes to migrations.
--cwd <path>Run against a different working directory.

What happens during install

  1. Dependency resolution - any packs your selection depends on are pulled in and ordered automatically, with family dependencies pinned to the variant your project already has
  2. Capability check - a pack that needs organizations or invitations is refused by name if no installed or selected starter provides them
  3. License check - paid packs are authorized against your license before a byte is downloaded. If something is locked, the CLI drops what you cannot install and shows where to buy it
  4. Validation - the whole plan is checked before a single file is written, so a bad install never leaves a half-modified project. Prisma models that clash with one already in your schema abort with both file names
  5. File install - schema, backend routes, and frontend pages are copied into the right places, in dependency order, then codemods register routes, nav entries, settings tabs, jobs, and permissions
  6. npm install - every pack's dependencies are added in one pass per workspace
  7. Secrets - env variables a pack marks as generated (an auth secret, a cookie password) are rolled for you
  8. Migrations - prisma generate always runs. If the packs added models, you are asked to run prisma migrate dev now. Installs that add no models do not ask
  9. Config update - stack.json records each installed pack and where it came from

Translations

Packs ship no hardcoded UI copy. Every string a pack renders comes from a Paraglide message catalog, and install merges each pack's messages into your app's messages/en.json instead of overwriting it. Two packs can contribute to the same file, and re-running compose produces no diff for messages you already have.

json
// apps/frontend/messages/en.json, after installing teams and billing
{
  "$schema": "https://inlang.com/schema/inlang-message-format",
  "app_title": "Acme",
  "teams_page_title": "Teams",
  "billing_upgrade_cta": "Upgrade"
}

Sidebar entries and settings tabs are merged the same way, so a pack's nav label is translatable too rather than being frozen into nav.constants.ts.

To add a language, add its code to locales in project.inlang/settings.json, drop a messages/<locale>.json next to the English one, and translate the values. Anything you have not translated yet falls back to English. Only en.json is merged on install, so your other locale files are never touched. Rewording a pack's English in en.json is fine, just know that re-installing that pack puts its own wording back.

Access tokens

Paid packs need access. Log in once with your browser:

bash
npx @hype-stack/cli login

That stores a token that expires after 90 days. For CI, create an API key on the API keys page and expose it as an env var. No flag, no secret in your shell history:

bash
HYPE_STACK_TOKEN=hsk_ci_xxx npx @hype-stack/cli compose --packs pack-billing-stripe --yes

API keys are revocable and shown in full only once, so a leaked key can be killed without touching your license.

Community packs

Packs you wrote, or someone else published outside our catalog, install through the same pipeline from a folder, a git repo, an npm package, or a registry namespace:

bash
npx @hype-stack/cli community add ../pack-analytics
npx @hype-stack/cli compose --packs pack-teams --community github:you/pack-analytics#v1.0.0

Anything that is not a local folder gets a confirmation that defaults to no. See Build your own pack.

Removing a pack

Packs are designed to be ejected. Once installed, the code lives in your project. Delete the files and revert the schema changes to remove a pack. The CLI doesn't automate removal, since most teams customize pack code after installing it.

Next

At the end of a compose run the CLI offers to walk you through onboard, which fills in the env vars your new packs need. You can also run it yourself later.