> For the complete documentation index, see [llms.txt](https://docs.winga.me/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.winga.me/getting-started/quickstart.md).

# Quickstart

This is the golden path. By the end you'll have a real flag in Winga and your app reading it through `@winga/js`. Every code block runs as written — just swap in your own flag key and API key.

***

### 1. Create your account

Sign up at [winga.me/sign-up](https://winga.me/sign-up). You can register with an email and password, or continue with Google or GitHub. Press **Continue** to create the account.

***

### 2. Create a workspace

On your first login, Winga walks you through a short setup wizard. The first step asks what to call your workspace — name it after your company or product (for example, `Acme`). The wizard also asks for an optional website, your team size, and a plan. Pick the **Free** plan to start and press **Create workspace**.

A workspace is the top-level container for everything you do in Winga. Projects, flags, and members all live inside it.

***

### 3. Create a project

Inside your workspace, start a new project. The project wizard asks for a name, what you're building, and how often you ship. When the project is created, Winga sets up three environments for you by default:

* `development`
* `staging`
* `production`

Each environment holds its own value for every flag, so you can flip something on in `development` without touching `production`.

***

### 4. Create your first flag

Open your project's **Flags** page and press **Add flag**. Give the flag a name — Winga derives a key from it automatically. Keys are **kebab-case** by default (lowercase letters, numbers, and hyphens, e.g. `new-checkout`), and the dashboard validates the format as you type. Choose a flag type (boolean, string, number, or JSON); boolean is the default.

Once the flag exists, toggle it **on** in the `development` environment using that environment's switch. That's the value your SDK will read in a moment.

***

### 5. Install the SDK

Install the core JavaScript SDK:

```bash
npm install @winga/js
```

Then initialise a client. `Winga` is a factory function — call it directly, no `new`:

```ts
import { Winga } from '@winga/js'

const ff = Winga({
  apiKey: 'proj_live_xxx',
  environment: 'development',
})
```

You'll find your real API key in the dashboard under **Project Settings → API Keys**. Press **Create key**, copy the value (it starts with `proj_live_` and is shown only once), and store it as an environment variable rather than hardcoding it. Set `environment` to the environment you want to read — `development` here, `production` in prod.

***

### 6. Evaluate the flag

For a boolean flag, `isEnabled` returns its current value:

```ts
if (ff.isEnabled('new-checkout')) {
  // flag is on
}
```

For typed flags, use `getValue` with a default. The default is also returned if the flag is missing or its type doesn't match what you expect:

```ts
const limit = ff.getValue<number>('upload-limit', 10)
const config = ff.getValue<{ theme: string }>('ui-config', { theme: 'light' })
```

On the server, `await ff.ready()` once before your first read so the initial flag snapshot has loaded. `ready()` never rejects — on a failed load it resolves after reporting the problem to your `onError` handler, and reads fall back to their defaults:

```ts
const ff = Winga({
  apiKey: process.env.WINGA_API_KEY!,
  environment: 'production',
  onError: (err) => console.error(err.code, err.message),
})

await ff.ready()

if (ff.isEnabled('new-checkout')) {
  // safe to read — flags are loaded
}
```

In the browser you don't have to await `ready()`; reads return `false` or the default until the first snapshot arrives, then update automatically.

***

### 7. React to changes in realtime

Winga keeps the client in sync over a streaming connection. Subscribe to flag changes with `on('change', ...)`:

```ts
ff.on('change', (event) => {
  console.log(`flag ${event.key} changed`, event.state)
})
```

The listener fires whenever a flag's value changes in the environment you're reading. When a flag is deleted, `event.state` is `undefined`, so guard for it before reading fields like `event.state.enabled`.

When you're done with a client (for example, tearing down a server or component), call `ff.dispose()` to close the connection and release listeners.

***

### Next steps

* [Concepts](/getting-started/concepts.md) — flags, environments, and workspaces explained.
* [FAQ](/getting-started/faq.md) — what happens when Winga is unreachable, and using Winga without a JS SDK.
