Core Concepts
Understanding the key ideas behind SkyState will help you use it effectively and avoid common mistakes. This page covers the building blocks: accounts, projects, environments, public state, user state, credentials, and versioning.
Accounts
An account is the top-level identity in SkyState. It has:
A unique account route identifier - an
acc_...identifier used in API and SDK routes.Changing the account or project identifier in an SDK configuration breaks that integration immediately. Apps must use the current account route identifier and project identifier.
A subscription tier -
free,hobby, orpro- which determines project, API-request, and end-user limits.
You sign in to SkyState with your Google or GitHub account through a hosted login page. There is no username/password stored by SkyState - your identity is managed by your chosen sign-in provider.
Your app's own users sign in separately through end-user auth. Their sign-ins are isolated per account, and the same person is a distinct end-user in each of your projects.
Projects
A project is the unit of organization for a set of related public and user state. You might have one project per application, or one project per service in a larger system.
Each project has:
- A name - a human-readable display name.
- A slug - a lowercase identifier made from letters, numbers, and hyphens, unique among your own projects, used in CLI commands and API paths. Example:
my-api,web-app,marketing-site. The slug is permanent and cannot be changed after creation. - Three fixed environments:
development,staging, andproduction.
Projects are created from the console or with sky project create.
sky onboarding is an interactive wizard that helps you pick a project and shows the right starter path. If you need a local API key for your own secret-management flow, use sky project keys create.
Project deletion is permanent. Deleting a project removes its environments, public-state versions, user state, API keys, and auth settings with no recovery option.
Project Limits by Tier
| Tier | Max Projects |
|---|---|
| Free | 3 |
| Hobby | 7 |
| Pro | 15 |
Environments
Every project has exactly three environments: development, staging, and production. They are created automatically when the project is created - there is nothing to provision.
Environments are isolated from one another. Pushing public state to development has no effect on staging or production. This lets you iterate safely:
- Push and test in
development. - Promote to
stagingwhen the change is ready. - Promote to
productionwhen staging is verified.
Selecting the Environment in Your App
The SDK environment option and the React environment prop take the full slug only (development, staging, or production). With Vite, one approach is to map the built-in MODE onto a slug:
ts
// MODE is 'development' in the dev server, 'production' by default for
// vite build, and 'staging' for vite build --mode staging.
const mode = import.meta.env.MODE as string;
const client = createSkyStateClient({
account: 'acc_example',
project: 'my-project',
environment: mode === 'staging' ? 'staging' : mode === 'development' ? 'development' : 'production',
});The tradeoff: --mode also selects Vite's .env.[mode] files and other mode-dependent behavior, so the SkyState environment rides along with the rest of your build configuration.
WARNING
If your staging builds run plain vite build, MODE stays production, so staging and production builds resolve to the same SkyState environment. Nothing errors; the app just reads production state. Passing --mode staging avoids this, as does a variable of your own injected by the shell or CI. A variable that lives only in .env.staging does not: a plain vite build never loads that file, so the build falls back to whatever .env or .env.production supplies.
Promoting Between Environments
The sky state public promote command applies the differences between two environments, updating the target to match the source:
bash
sky state public promote --project my-app --from staging --to productionThe command shows a diff and prompts for confirmation before applying changes. It creates a new version in the target environment. The source environment is not modified.
It also supports key selection, dry runs, and non-interactive confirmation. See sky state public promote.
Environment Slugs and Aliases
CLI commands accept both full names and short aliases:
| Full name | Alias |
|---|---|
development | dev |
staging | stg |
production | prod |
For example, sky state public push --project my-app --file config.json --env dev is equivalent to --env development.
Public State
Public state is a JSON object stored for a specific project and environment. It holds client-readable values that browser apps can read anonymously through the SDK.
Use public state for application config, feature flags, settings, announcements, theme values, safe limits, and catalog or inventory data that does not require reservation-grade consistency. Do not store secrets, private user data, or security-sensitive values in public state.
Key properties of public state:
- JSON objects only - public state must be a JSON object (
{}), not an array or primitive. - Top-level SDK keys - SDK accessors read top-level keys such as
banner,features, orlimits. If you store a nested object underbanner, readbannerand select nested fields in your app. - Public reads, controlled writes - browser clients can read public state. Writes require the CLI, console, developer bearer token, or project API key.
- Versioned - every write creates an immutable new version. The latest version is always kept; older versions are retained for a plan-dependent window (none on Free, 5 days on Hobby, 30 days on Pro). See Tiers.
Example Public State
json
{
"maintenance": { "enabled": false },
"banner": {
"enabled": true,
"text": "Spring sale - 20% off all plans!",
"color": "#3b82f6"
},
"features": { "darkMode": false, "maxItems": 10 },
"limits": { "maxUploadMb": 25 },
"inventory": { "starterKitAvailable": true, "popularPlan": "pro" }
}Public-State Size
Public state has a maximum serialized size, the same on every tier. The exact limit and the rejection codes are on the Public State API page.
Versioning
Every public-state write creates a new immutable version with a monotonically increasing integer version number. The latest version is always kept; older versions are retained for the plan-dependent window described under Public State above (none on Free).
How Versioning Works
- The first push to any environment creates version
1. - Each subsequent push increments the version number by 1.
- Every write carries a version expectation, and the server rejects the write with
412if the current version no longer matches, preventing overwrite conflicts. The CLI supplies the current version automatically unless you pass--expect-versionor--expect-none(seesky state public push).
Breaking-Change Detection
When you run sky state public push, the CLI fetches the current public state and compares it to the file you are pushing. If the CLI detects breaking changes (key removals or type changes), it prompts for confirmation before proceeding.
Viewing and Comparing Public State
Use sky state public show to see the current public state for an environment and sky state public diff to compare two environments.
API Keys
SkyState uses two types of credentials.
Dev API Keys
A dev API key can be created with sky project keys create for local development. It is used by trusted automation and server-side tools for project-scoped API access.
API keys authenticate project public-state operations plus the /v1/api-key/info key-metadata endpoint. Everything else (projects, user state, API key management, hosted auth settings, account, and billing) requires a developer login from sky login.
See Dev API Keys for the full key lifecycle: creation, storage, rotation, and revocation.
Bearer Token (Admin Credential)
When you run sky login, the CLI stores a bearer token locally (the path is on the CLI reference). This token:
- Is tied to your account and grants full admin access to all your projects.
- Is refreshed automatically by the CLI while its refresh token is valid.
- Should never be shared or committed.
The CLI reads this token automatically for all sky commands.
CLI Configuration
Personal CLI preferences such as the API URL, default environment, and output format live in ~/.config/skystate/config.json, managed with sky config.
Public-State Caching
Public-state responses are cached per environment, so deployed clients may briefly serve the previous version after a push. See Caching for the TTLs.