Ship public state to production
In the earlier tutorials you pushed public state to the development environment and read it from an app. Real apps serve people from production. This tutorial explains how SkyState environments work, then takes you through one promotion end to end: preview the change, then apply it to move the welcomeText key from staging to production.
Estimated time: 15 minutes.
What you'll build
You carry the welcomeText key from a tutorial track through to production:
- Wire the provider so a build variable picks the environment, instead of a value fixed in the source.
- Enable end-user auth for the project and register callback URLs for deployed environments, so sign-in and user state keep working outside local development.
- Push a staging welcome message with the CLI.
- Preview the promotion with
sky state public promote --dry-runbefore anything is written. - Apply the promotion at the confirmation prompt, and check the result in production.
- See where
--yesand--commentfit for automation and audit trails.
Prerequisites
- One tutorial track: React, Vanilla, or API. You need its project created and
welcomeTextbeing read from public state. - The SkyState CLI, signed in with
sky login.
Step 1: Understand the environment model
Every project has three fixed environments, and every command selects one through --env (aliases dev, stg, and prod resolve to the full names). See Environments for the model; this tutorial uses promote to copy public state from staging to production.
Step 2: Pick the environment from a build variable
You wired the environment as development for the first run. A production build should reach production, so drive the environment prop from a build variable instead of fixing it in the source. Update the provider in src/main.tsx (replace YOUR_ACCOUNT_ID with the ACCOUNT ID from sky status):
tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { SkyStateProvider } from '@skystate/react'
import App from './App.tsx'
const skyStateEnv = import.meta.env.VITE_SKYSTATE_ENV ?? 'development'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<SkyStateProvider
account="YOUR_ACCOUNT_ID"
project="tutorial-app"
environment={skyStateEnv}
callbackUrl={window.location.origin}
>
<App />
</SkyStateProvider>
</StrictMode>,
)VITE_SKYSTATE_ENV is a name you choose; set it to development, staging, or production per build (on the Vanilla or API track, pass the same value where you set the environment). See SkyStateProvider for prop detail and Environments for choosing the value.
Step 3: Register deployed callback URLs
Public state does not need sign-in. If your app also reads user state, that needs sign-in, and sign-in needs two things: end-user auth enabled on the project, and a callback URL for each deployed environment.
On the React track, Part 2 registered http://localhost:5173 for development only. Register the deployed staging and production URLs before you test sign-in there:
bash
sky project auth callback-urls add \
--project tutorial-app \
--url https://your-staging-app.example.com \
--env staging
sky project auth callback-urls add \
--project tutorial-app \
--url https://your-production-app.example.com \
--env production
sky project auth enable --project tutorial-appEnabling end-user auth is project-scoped, so it takes no --env and is done once per project. If you already enabled it during your track, skip that command.
Register the exact URL your app passes as callbackUrl. This tutorial passes window.location.origin, so register the bare origin each deployed build serves from, as you did for http://localhost:5173 in development. The full matching rule is on the CLI reference: Callback URL matching.
Step 4: Push a staging welcome message
Set welcomeText in staging. This is the state you promote to production next.
bash
sky state public push \
--json '{"welcomeText":"New dashboard is live. Try it now."}' \
--project tutorial-app \
--env staging \
--comment "Prepare welcome text for production launch"Confirm it landed:
bash
sky state public show --project tutorial-app --env stagingStep 5: Preview the promotion
A dry-run shows the change without writing it:
bash
sky state public promote \
--project tutorial-app \
--from staging \
--to production \
--keys welcomeText \
--dry-run--keys welcomeText limits the promotion to that one top-level key. The output lists every change it would make: here, a single addition, since production has no state yet. The dry-run exits without writing anything.
TIP
Use diff when you only want to compare two environments, without preparing a promotion:
bash
sky state public diff \
--project tutorial-app \
--from staging \
--to production \
--keys welcomeTextIt prints the public-state differences and never writes to either environment.
Step 6: Apply the promotion
Run the same command without --dry-run. The CLI recomputes the changes, shows them as a diff, and asks you to confirm:
bash
sky state public promote \
--project tutorial-app \
--from staging \
--to production \
--keys welcomeText \
--comment "Promote launch welcome text to production"Apply all changes? [y/N]Confirm with y. The CLI applies the changes and prints the environment, the number of changes, and the new version number.
Verify
Check that production now carries the welcome message:
bash
sky state public show --project tutorial-app --env productionThe output should show the welcomeText value from staging. To see the SDK read it, run a production build, or set VITE_SKYSTATE_ENV=production in .env.local and restart the dev server. The app shows the production welcome text.
If your app includes the user-state parts of the tutorial, sign in on the production URL too. The callback URL from Step 3 is what lets SkyState return to the production app after sign-in.
Two more paths worth seeing.
--yes skips the prompt, for CI that has no terminal to answer it:
bash
sky state public promote \
--project tutorial-app \
--from staging \
--to production \
--keys welcomeText \
--yes \
--comment "CI: promote welcome text to production"If two promotions hit the same target at once, the server rejects the second with 412, and the CLI exits with code 1 and prints Conflict: production was updated while you were editing. Run sky state public show --project tutorial-app --env production to see the current state, then promote again.
What you learned
- The provider takes its environment from a build variable, so development, staging, and production builds each reach their own state.
- User-state sign-in needs end-user auth enabled once per project, and a callback URL per deployed environment.
- A promotion always follows the same path: preview with
--dry-run, apply at the prompt, then check. --keysnarrows a promotion to specific top-level keys, so you ship one key at a time and leave other production values alone.--yesstands in for the confirmation a CI pipeline cannot give.