# SplitHub Cloud

The hosted side: a dashboard at `app.splithub.io`, the ingest and API at `go.splithub.io`. It runs on Cloudflare's edge, so events are accepted close to the visitor and verdicts are computed from one database.

## Projects and keys

A project is a workspace: one app, its experiments, its members, its billing. Every project has a **public key** (`pk_…`, in the config and the browser, sends events) and any number of **API keys** (`sk_…`, for the CLI, CI and servers). Members join by invitation email with viewer, editor or admin roles; there is no per-seat price.

## Connecting an app

```bash
npx splithub init --mode cloud     # or: npx splithub login in an existing project
npx splithub push
```

`login` shows a code and a link; approving it in the dashboard (where you can also create the project) mints an API key for that folder. `push` uploads the normalized config; the first push writes the public key into the file. No manual key paste is needed; the CLI stores the secret locally.

## The dashboard

- **Experiments**: status, visitors, days, verdict per experiment; start, pause, finish; a quick-start with the one command and a "copy for your agent" prompt.
- **Experiment page**: results, timeline (daily visitors and conversions, cumulative rate), breakdowns by country, device, browser and host, realtime (last 30 minutes), raw events, notes, CSV export, the AI tab, targeting.
- **New experiment**: Redirect, Component or Value, with weights, traffic share, visitor cap, schedule, notes, and the CLI command that creates the same thing in the file.
- **Links**: short links with weighted and targeted destinations and QR codes.
- **Alerts**: rules, channels and the digest (Pro).
- **Setup**: the key, the install command, the drop-in script, the MCP entry.
- **Domains**: restrict which origins may send events.
- **Team**, **Billing**, **Settings** (goals, API keys, project).

## Live overrides

Pause, resume, finish, change `traffic`, reweight, or swap a `value` payload from the dashboard or with `PUT /v1/overrides/<id>`. Overrides sit on top of the config without a deploy. The browser SDK keeps them in a 60-second cache: later pages apply the cached copy at once and refresh it in the background. A visitor's first page has no cache, so the SDK waits for the overrides (about 150 ms, at most `remote.waitMs`, default 400) and renders control meanwhile; then each test is decided once, and the file decides if they are late. Next.js reads them on the server, middleware refreshes its cache on requests, and the script fetches them on page load. A variant never changes once a page has shown it. Experiments the file owns are read-only in the dashboard except for status changes; `pull` brings dashboard-created ones into the file.

## The gate

Before touching the database the edge checks the project. A project with no running experiments or no pushed config gets `202` with `idle` and the reason; one with no quota left or deleted gets `429` with a reason and `Retry-After`. Exposures for paused, finished or draft experiments are dropped. Nothing of that is stored or billed. An exposure-event cap (`maxExposures`) finishes the experiment automatically and emails the team.

## Emails

Everyone on the project gets an email when an experiment starts (who, which goal, link) and when it finishes (verdict, per-variant numbers, the AI review on Pro), on every plan. Each member switches these on or off in their profile. Alerts and the digest are additional (Pro).

## Retention

| | Raw events | Daily aggregates and verdict snapshots |
|---|---|---|
| Free | 30 days | 1 year |
| Packs or Pro | 90 days | 1 year |

Timelines and verdicts of finished experiments keep working after raw events expire.

## Limits

Up to 500 events per batch, 4,096 characters of serialized props per goal, and 64-character experiment, variant and goal keys. Experiments, goals, members and projects are unlimited.
