create-skalx-app
v0.2.4
Published
Scaffold a new Skalx-integrated app (OIDC, optional SCIM) — Vite + React + TypeScript
Maintainers
Readme
create-skalx-app
One command. Production-shaped React + Vite + TypeScript app with Sign in with Skalx (OIDC) already wired up — no copy-paste from docs, no hand-rolled provider, no token-storage debate to relitigate.
npm create skalx-app@latest my-appWhat it does
create-skalx-app is a CLI scaffolder (think create-react-app /
create-vite) that drops a working Skalx-integrated SPA onto disk and
installs it. The generated app already has:
- The OIDC provider configured (Authorization Code + PKCE, JWKS
id_tokenvalidation, silent renew, multi-tab sync, RP-initiated logout). - The axios client wired with
Bearer <access_token>+Saas-App-Tokenheaders,429 Retry-Afterbackoff, and a401bounce back to/sign-in?session=expired. - The auth UI — public pages (
/sign-in,/oidc/callback,/forgot-password,/reset-password,/accept-invite), gating components (<SignedIn>,<SignedOut>,<SignInButton>,<UserButton>,<ProtectedRoute>), and a dashboard with the OIDC diagnostics you need on day one. - Optional SCIM 2.0 admin + dev-only playground (
--with=scim) for apps that need IdP-driven provisioning. - A
npm run verifyscript that smoke-tests OIDC discovery / JWKS / userinfo against your Skalx host and prints PASS/FAIL.
After scaffolding, see README.md inside the generated app for the
full integration guide — env vars, routes, deployment, security
considerations, troubleshooting, OIDC cheat sheet.
Why we built it
Wiring Skalx OIDC into a fresh SPA the first time is a 1–2 day job. You end up making the same set of decisions every team makes: how to store tokens, how to handle silent renew failure, where 401s bounce, how to keep tabs in sync, how to gate routes. Most teams get one of those wrong on the first pass and discover it later.
This CLI bakes those decisions in once, the way Skalx wants them:
- Defaults that match the Skalx OIDC contract. PKCE S256, public
client, refresh-token silent renew,
loadUserInfo, scope shape that works against Skalx's authorization server out of the box. - One supported pattern. No "axios vs fetch", no "Zustand vs Context", no "Redux for auth". The scaffold picks one shape so the Skalx team can support it consistently — and so your codebase doesn't grow three competing auth implementations.
- No copy-paste from the docs. The integration guide exists in the generated app's README, but the corresponding code is already there, lint-clean, type-checked, and built.
- Safe by default. Validates every CLI input up front, refuses to write outside the working directory, refuses to ship a production build with a non-HTTPS issuer.
If you want to deviate from the defaults later — different state
library, a Backend-for-Frontend, no SCIM — go ahead. The scaffold is
yours after npm create; we don't reach back into it.
Usage
# Interactive (prompts you for the values below):
npm create skalx-app@latest my-app
# or via npx:
npx create-skalx-app my-appPrompts
| Prompt | What goes here |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Project name | Lowercase, no spaces. Single folder name (the CLI refuses anything that looks like a path). |
| Skalx API base URL | e.g. https://api.main.skalx.ai (default). The OIDC issuer is derived from this as {API_BASE_URL}/authorization/v2/oidc — no separate prompt. |
| Dev server port | Default 4400. Must be an integer in 1024..65535. |
| Include SCIM admin + playground? | y/N — opt in to the SCIM 2.0 provisioning UI and the dev-only playground. SCIM is IdP-side (Okta / Entra / OneLogin push users into Skalx); your app still signs users in via OIDC. Adds the application-id prompt below. |
| Application id | Integer from the Skalx admin URL. Only asked when SCIM is enabled — the /scim admin page needs it. |
| App key | Hex Saas-App-Token value — a public multi-tenant identifier sent on every request to pick the workspace. Not a secret (treat like a Stripe publishable key). |
| OIDC client id | From Skalx admin → your app → OIDC tab (or leave blank and fill in later in .env.development). |
Skip prompts (--yes)
# OIDC only (no SCIM):
npm create skalx-app@latest my-app -- --yes
# OIDC + SCIM (admin + playground):
npm create skalx-app@latest my-app -- --yes --with=scim--yes defaults SCIM to off. Pair it with --with=scim if you
want the SCIM pages.
Pre-fill values from your admin dashboard
Every prompt has a matching --flag=value form. The Skalx admin
dashboard's "Copy install command" button emits one of these so a new
project drops in with its API URL, app token, and OIDC client id
already filled into .env.development:
npm create skalx-app@latest my-app -- --yes \
--api-url=https://api.main.skalx.ai \
--app-token=<hex> \
--oidc-client-id=<oidc-client-id>
# With SCIM:
npm create skalx-app@latest my-app -- --yes --with=scim \
--api-url=https://api.main.skalx.ai \
--app-token=<hex> \
--oidc-client-id=<oidc-client-id> \
--app-id=<application-id>Each field flag also works without --yes — the matching prompt is
suppressed for any value supplied on the command line, leaving the
rest to be filled in interactively. Empty values (--app-token=)
fall through to the placeholder, same as hitting Enter at the prompt.
Note: --app-token is the public Saas-App-Token, not a secret,
but it will still land in your shell history.
Flags
| Flag | Effect |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| --yes, -y | Skip prompts; use defaults and placeholders for unset values. |
| --with=scim | Include the SCIM admin page (/scim) and the dev-only SCIM playground (/playground). Also enables the application-id prompt. Default: off. |
| --api-url=<url> | Pre-fill the Skalx API base URL (suppresses the prompt). |
| --app-token=<hex> | Pre-fill VITE_APP_SAAS_APP_TOKEN — the public app key. |
| --oidc-client-id=<id> | Pre-fill VITE_APP_OIDC_CLIENT_ID. |
| --app-id=<int> | Pre-fill VITE_APP_SAAS_APP_ID. Only relevant with --with=scim. |
| --port=<n> | Pre-fill the dev server port. |
| --no-install | Don't run npm install afterwards. |
| --no-git | Don't run git init afterwards. |
| --verify-build | Run npm run type-check + npm run build in the scaffold after install. Fails the CLI if either is red. Implies --install. |
| --help, -h | Show inline help. |
What you'll need before scaffolding
- Org admin access to your Skalx workspace.
- A third-party application registered in the Skalx admin UI — it
gives you the application id and
Saas-App-Token. - An OIDC client — from the OIDC tab on your app. Hand the Skalx admin your redirect URI(s); they hand back a Client ID.
- Only if you opt into SCIM: an inbound SCIM bearer token
(
scim_…) — needed at runtime in the/scimadmin page. The scaffold can rotate it for you from inside the app.
You can leave any of those blank at prompt time — the CLI writes
placeholders into .env.development, and npm run verify will tell
you exactly what's still missing.
CLI safety
This CLI runs on developer machines and writes files. A few guarantees worth knowing about:
- Project-name validation: must match
[a-z0-9][a-z0-9-_]{0,213}— no path separators, no.., no absolute paths, no npm-reserved names. The scaffold is always written inside your current working directory. - Strict input validation: API base URL must be
http(s)://, port must be1024..65535, application id must be numeric, app token must be 16–128 hex chars. Bad inputs are rejected up front. - JSON-safe rendering:
package.jsonis parsed back after string-substitution to confirm we didn't corrupt the file. - Cleanup on partial failure: if writing throws mid-way, the partially-written directory is removed so you don't end up with a half-scaffold.
- No shell evaluation:
npm installandgit initare spawned with argv arrays, not shell strings — no command-injection surface. - Runtime HTTPS guard (in the scaffold): the generated app refuses
to boot any non-dev build whose
VITE_APP_OIDC_ISSUERisn't HTTPS, or whose origin is plainhttp://(exceptlocalhost).
Working on this CLI
Contributors / forkers — the CLI itself is plain ESM Node, no build step:
npm install
npm test # vitest — validator + path-safety suite
npm run check-template # refuses to publish if templates/ has dev artifacts
npm run smoke # scaffolds + installs + type-checks + builds end-to-end
npm run format # prettier --write .
npm run format:check # prettier --check . (CI-friendly)Layout:
bin/ # the npx entry point
src/ # CLI logic (run.js, validators.js, regions.js)
templates/default/ # the scaffold copied into user projects
test/ # vitest suites
scripts/ # check-template + smokeprepublishOnly runs check-template + test + smoke + npm pack --dry-run
before publishing — broken templates never reach the registry.
Support & docs
- Docs: skalx.ai/docs — search for "Sign in with Skalx — OIDC integration guide" or "SCIM 2.0" for the canonical product integration guides.
- Email: [email protected] — include the
CLI version (
npm ls create-skalx-app), yourVITE_APP_OIDC_ISSUER(no tokens!), and the failing step. - Scaffold issues: file at github.com/skalx/create-skalx-app/issues if the bug is in the CLI / scaffold itself; for product bugs use email.
License
MIT — see LICENSE.
