VibeHost
Guides

Concepts

The model behind VibeHost: workspaces, teams, apps, deployments, channels, and grants.

VibeHost has a small number of moving parts. The CLI, the dashboard, and the API all work on the same few objects, and this page describes them.

The shape of an account

graph TD
  W["Workspace<br/>billing + admin boundary"] --> T1[Team A]
  W --> T2[Team B]
  W --> A1["App: my-site"]
  W --> A2["App: my-app"]
  A1 --> C1["channel: production"]
  A1 --> C2["channel: pr-42"]
  C1 --> D1["Deployment depl_abc<br/>healthy, current"]
  C1 -.older.-> D2["Deployment depl_xyz<br/>healthy, superseded"]
  C2 --> D3["Deployment depl_def<br/>healthy, current"]
  T1 -.grant: deployer.-> A1
  T2 -.grant: viewer.-> A2
  style W fill:#f4d8c5
  style A1 fill:#d8e8f5
  style A2 fill:#d8e8f5
  style C1 fill:#fff4d8
  style C2 fill:#fff4d8

A few things the diagram doesn't show:

  • The workspace owns every app. A team never owns an app; it only holds a grant on it.
  • Teams group people, not apps. They exist so you can grant access to many apps with one grant.
  • A user can belong to multiple workspaces, and to multiple teams within each.
  • Rolling back doesn't delete anything. A rollback only moves the channel alias, and the previous deployment is kept until vibehost gc prunes it.

Workspaces

A workspace is the billing and admin boundary. It has one plan, one bill, and one set of platform-admin overrides, and it owns every app, team, deployment, and audit log row inside it.

Workspace member roles:

RoleWhat it unlocks
memberBe in the workspace; see what app/team grants give you
adminCreate teams, manage workspace settings, see all apps
ownerPlus billing, plan changes, workspace deletion

A user can belong to multiple workspaces. Run vibehost whoami to see which one you're in, or pass --workspace to any command.

Teams

A team groups members inside a workspace. Teams exist so you can issue one grant ("the Web team can deploy to all marketing apps") instead of N email grants.

Team member roles:

RoleWhat it unlocks
memberBe in the team; receive whatever grants the team has
managerManage team members + settings
ownerPlus delete the team

For a workspace of one to three people, one team is usually enough. Add more when you want grant isolation between sub-groups (e.g. contractors vs full-time, web vs mobile).

Apps

An app is one project with one deploy target. Create one like this (the default runtime is static):

vibehost app create my-site

App names match [a-z][a-z0-9-]*, are 2 to 40 characters long, and must be unique within the workspace.

The name is the app's unique slug. It appears in URLs (my-site-acme.vibehost.space) and can't be changed after creation. An app also has two optional fields that are only for display:

  • displayName (1 to 100 characters) is what the dashboard shows. When it's unset, the dashboard shows the slug.
  • description (1 to 500 characters) is a short blurb that helps you tell apps apart.

Neither has to be unique, and you can change either one at any time without touching a URL:

vibehost app create my-site --display-name "Acme Marketing Site" --description "Landing pages for the spring campaign"
vibehost app update my-site --display-name "Acme Site v2"

An app belongs to its workspace and to no team. Teams reach an app only through grants, as described below.

Deployment lifecycle

sequenceDiagram
  actor You as You / agent
  participant CLI
  participant API as api.vibehost.com
  participant Storage as Asset storage
  participant Edge as Edge runtime
  You->>CLI: vibehost deploy ./dist
  CLI->>CLI: build (already done) + tarball + validate
  CLI->>API: POST /deployments (chunked blobs)
  API->>API: dedup against existing blobs
  API->>Storage: assemble release
  API-->>CLI: depl_abc { url, status: pending }
  API->>Edge: update channel alias
  Edge-->>API: alias active
  API-->>CLI: status: healthy
  CLI-->>You: print URL
  Note over You,Edge: From tarball POST to healthy URL: ~3–8s

In a client build, the build step (npm run build) runs on your machine. The server only validates, deduplicates, and assembles what you upload. It never runs npm install or a framework build inside our API, and keeping builds out of the API is how the platform scales.

Channels

Preview deploys are channels, not git branches. The server knows nothing about git.

vibehost deploy --channel production
vibehost deploy --channel pr-42
vibehost deploy --channel dark-mode-experiment

Every channel gets its own alias URL and runs independently. A deploy in dark-mode never affects production.

flowchart LR
  subgraph Channels
      Prod["production<br/>my-site-acme.vibehost.space"]
      PR42["pr-42<br/>my-site-ch-pr-42-acme.vibehost.space"]
      Dark["dark-mode<br/>my-site-ch-dark-mode-acme.vibehost.space"]
  end
  Prod -.alias.-> A[depl_001]
  PR42 -.alias.-> B[depl_042]
  Dark -.alias.-> C[depl_dark]
  D[depl_old] -.superseded.-> Prod

Promote between channels without re-uploading:

vibehost promote depl_042 --to-channel production --app my-site

The artifact at depl_042 doesn't re-upload. Only the production alias moves to point at it.

vibehost promote currently fails for static apps on vibehost.com with an INTERNAL error. Until that's fixed, deploy the same build output to the target channel instead, for example vibehost deploy ./dist --channel production --app my-site. Deploy the directory you tested without rebuilding it, and the files that go live are the files you tested. Uploads are content-addressed, so nothing the server already has is transferred again. vibehost rollback isn't affected.

How grants decide access

To do anything on an app, a user needs an app-level grant. Grants are additive: if both your team and your email have grants, the effective role is the max.

There are two kinds of grant:

  • A team grant is (app, team, role). Every member of the team gets the role.
  • An email grant is (app, email, role) and targets one person. The email doesn't have to belong to an existing user, so you can grant access before someone signs up.

App-level roles:

RoleCan do
viewerView deployments, see logs
deployerAbove + push new deploys, promote, rollback
adminAbove + manage grants, settings, custom domains

How a request is gated

Every viewer request runs through the platform's authz check. The password is the only gate that applies to every path, whenever one is set. Share links skip the visibility and grant checks but not the password. A valid share-link cookie or ?__vh_share=<token> URL parameter passes the share-link gate, and the password gate still applies after it. See Grants and visibility for the full ordered walkthrough.

flowchart TD
  Req[Visitor request] --> ShareCk{"Valid share-link cookie<br/>or ?__vh_share= token<br/>+ share row still active?"}
  ShareCk -- yes --> Pwd{Password gate set?}
  ShareCk -- no --> Vis{Visibility?}
  Vis -- public --> Pwd
  Vis -- workspace --> WMem{Is workspace member?}
  Vis -- private --> Grant{Has grant?}
  WMem -- yes --> Pwd
  WMem -- no --> Deny401["401 challenge"]
  Grant -- yes --> Pwd
  Grant -- no --> Deny401
  Pwd -- no --> Allow[Serve content]
  Pwd -- yes --> PwOk{"Correct password<br/>or cookie?"}
  PwOk -- yes --> Allow
  PwOk -- no --> Deny401
  style Allow fill:#d4f4d4
  style Deny401 fill:#f4d4d4

This is why making an app public doesn't unlock it when it also has a password. The password is a separate layer that every path has to pass, including the share-link path. Skipping visibility and grants is the one exception share links get, because minting a share link is the operator saying that anyone with the URL may pass those checks. It never overrides a password.

See Grants and visibility for the full model and decision tree.

Deployments

A deployment is an immutable artifact plus a runtime config. Every deploy gets two identifiers:

  • id, an opaque deployment ID
  • url, the alias URL that moves with the live deployment on this channel

The response also has an immutableUrl field, meant for a URL pinned to this exact version. vibehost.com returns null for it on new deployments, and URLs stored on older ones no longer resolve, so use the id when you need to name one version (see the glossary).

Rolling back doesn't change or delete the old deployment. It points the channel alias back at the older deployment. Old deployments are kept until vibehost gc prunes them or you app delete.

vibehost gc prunes old deployments. Only owners and admins can run it, and by default it keeps the last 5 per channel.

Personal access tokens

Personal access tokens are long-lived bearer tokens for CI and external integrations. Each token is scoped per resource group. You can also bind it to a specific workspace and team, to specific app IDs, or to both.

See Personal access tokens for the full scope list and rotation guidance.

How the pieces talk

graph LR
  subgraph Clients
      You[You / CLI]
      Agent[Agent / MCP]
      CI[CI / PAT]
      DB1[Dashboard]
  end
  subgraph ControlPlane["Control plane"]
      API[api.vibehost.com/api/v1]
  end
  subgraph EdgeRuntime["Edge runtime"]
      Edge[Tenant router]
      Static[Static assets]
  end
  You --> API
  Agent --> API
  CI --> API
  DB1 --> API
  API -.assets.-> Static
  Static --> Edge
  Edge --> Visitor(("*.vibehost.space<br/>visitor"))

The control plane runs the API and the dashboard. Tenant apps run in isolated edge sandboxes and share no process with it. The CLI, MCP, and the dashboard all call the same REST endpoints with the same auth checks.

Naming cheat sheet

TermWhat it meansCommon confusion
WorkspaceThe billing boundary; owns apps and teamsNot a team, which is a group of people inside the workspace
TeamA grant target that gives one group access to many appsDoesn't own apps, only receives grants
AppOne deploy target (one runtime, one set of channels)Not a project. One product is sometimes several apps
ChannelA named slot for a deployment (production, pr-42)Not a git branch. The server knows nothing about git
DeploymentAn immutable artifact, identified by its deployment IDSurviving rollback is by design, not a quota leak
GrantPer-app role given to a team or an emailComposes with visibility / password; never short-circuits
VisibilityWho gets in without a share link: public, workspace, or privateNot an alternative to grants; both apply
Share linkA cookie-issuing URL for time-bound public-ish accessUnlike public, each link can expire and be revoked on its own

Every other term the docs use is in the Glossary.

On this page