Skip to content

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, or pro - which determines project, API-request, and stored-user limits.

Authentication is done via Firebase. There is no username/password stored by SkyState - your identity is managed by your chosen sign-in provider.


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 globally unique lowercase identifier made from letters, numbers, and hyphens, 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, and production.

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

TierMax Projects
Free3
Hobby7
Pro15

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:

  1. Push and test in development.
  2. Promote to staging when the change is ready.
  3. Promote to production when staging is verified.

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 production

The 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.

You can promote only specific keys using --keys:

bash
sky state public promote --project my-app --from staging --to production --keys banner,features

Use --dry-run to preview changes without applying them, or --yes to skip the confirmation prompt in CI.

Environment Slugs and Aliases

CLI commands accept both full names and short aliases:

Full nameAlias
developmentdev
stagingstg
productionprod

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, public settings, announcements, theme values, safe client-visible 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, or limits. If you store a nested object under banner, read banner and 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

Each public-state object is stored as a JSON blob. The maximum size is 256,000 characters. Writes that exceed this limit are rejected.


Versioning

Every public-state write creates a new immutable version with a monotonically increasing integer version number. Previous versions are retained.

How Versioning Works

  • The first push to any environment creates version 1.
  • Each subsequent push increments the version number by 1.
  • The server rejects a write if the version has changed since your last read, preventing overwrite conflicts.

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:

bash
sky state public show --project my-app --env production

Use sky state public diff to compare public state in two environments:

bash
sky state public diff --project my-app --from development --to staging

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:

  • Shown once at creation time, then only the prefix is visible later.
  • Used by trusted automation and server-side tools for project-scoped API access.

The full API key value is only shown once, at the time of creation. After that, only the key prefix is visible. If you lose the key, generate a new one.

Dev API keys can be rotated at any time from the console or by revoking and recreating them with sky project keys.

Never commit your .env.local file. If you keep the key locally, manage it in your own secret flow.

Bearer Token (Admin Credential)

When you run sky login, the CLI stores a bearer token at ~/.config/skystate/token.json. 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.


Configuration Files

SkyState uses two configuration files:

~/.config/skystate/config.json (Global CLI Config)

Stores your personal CLI preferences. Written by sky config set.

json
{
  "api_url": "https://api.skystate.io",
  "format": "table"
}

Available keys:

KeyDefaultDescription
api_urlhttps://api.skystate.ioAPI base URL.
default_env(empty)Fallback environment for push and show commands.
formattableDefault output format: table, json, or plain.

Manage this file with sky config set <key> <value>, sky config get <key>, sky config list, sky config unset <key>, and sky config path.

.env.local (API Key)

Optional developer-managed file in your project root. Store local API URLs, auth-front URLs, or backend-only API keys here using names that match your stack.

Do not commit this file. It contains a secret credential.


The Network-First Model

The SDK follows a network-first architecture. When a component mounts:

  1. Keyed React hooks such as usePublicState('banner', fallback) return { value }, using the fallback until a server value is available.
  2. The no-argument status hook usePublicState() reports idle, loading, ready, or error.
  3. The core SDK exposes the same state through client.publicState.get(key, fallback) and client.getSnapshot().publicState.
  4. If the initial fetch fails, the keyed read continues to return the fallback while the status surface reports the error.

This means your app can render with hardcoded defaults while the SDK fetches public state or retries a recoverable failure.

Public-State Caching

Public-state responses are served with HTTP Cache-Control headers. The cache TTL depends on the environment:

EnvironmentCache TTL
development10 seconds
staging10 seconds
production900 seconds (15 minutes)

After you push a public-state update to production, deployed clients may continue to serve the previous version for up to 15 minutes. For development and staging, the maximum delay is 10 seconds.