Skip to content

Websites

import { Aside } from ‘@astrojs/starlight/components’;

A Website is the central entity in Melbora. Each client site you manage is one Website row. Everything else — the GitHub repo, the Vercel project, the Shopify store, the bookings handle, the domains — hangs off a Website.

interface Website {
websiteId: string; // wb_<ulid>
clientId?: string; // owning client, null if unassigned
name: string;
slug: string; // globally unique, used in repo naming
status: "pending" | "provisioning" | "active" | "failed" | "suspended";
features: {
openrouter: boolean;
resend: boolean;
bookings: boolean;
seo: boolean;
shopify: boolean;
};
createdAt: string; // ISO timestamp
updatedAt: string;
}

The slug is globally unique across all Websites — it’s used to name the GitHub repo (client-<slug>) and (today) the Vercel project. Pick slugs that read well in URLs and don’t collide with other clients.

create job enqueued provisioning succeeds
────▶ pending ──────▶ provisioning ──────────────▶ active
│ provisioning fails
failed ─── (operator can retry or delete)
─── (operator can suspend)
suspended
  • pending — row created but the provisioning job hasn’t been picked up by the worker yet. Usually flips to provisioning within seconds.
  • provisioning — orchestrator is running. Visible in the portal but not usable yet. Lasts ~60-90s for a basic site, longer if Shopify or other features are enabled.
  • active — fully deployed, accepting traffic, all toggled features wired.
  • failed — one of the provisioning steps failed. The vantage-provisioning-jobs table has the failed step in its errors array. Either retry or delete.
  • suspended — billing lapsed or operator manually paused. Resources stay provisioned but Vercel deployments are paused; flips back to active on reactivation.

The minimum to provision a Website is a name and a slug:

Terminal window
vantage websites create --name "Joe's Plumbing" --slug joes-plumbing

This:

  1. Creates the row in vantage-websites with status: "provisioning"
  2. Enqueues a ProvisioningJob to SQS
  3. Returns the Website synchronously — the job runs asynchronously

By default no optional features are enabled (openrouter: false, resend: false, etc.). Toggle them after creation, or pass --client-id to assign ownership at creation time.

Terminal window
vantage websites features <websiteId> --openrouter --resend

Each feature flag corresponds to an integration that gets provisioned (or torn down) as the flag changes. Some flags trigger work that takes seconds (creating an OpenRouter key); others take minutes (provisioning a Resend domain with DNS verification).

Terminal window
vantage websites list # all websites you can see
vantage websites get <id> # one website, full record

Or via SDK:

import { VantageClient } from "@vantageconnections/sdk";
const vc = new VantageClient({ token: process.env.VANTAGE_TOKEN! });
const { websites } = await vc.websites.list();
const w = await vc.websites.get("wb_01J7XXX");
  • Admin tokens see every Website
  • Client tokens only see Websites where clientId matches the token’s owner

If you get a 403 calling /v1/websites (the list endpoint), you’re holding a client token. Use /v1/websites/<id> for your specific site instead.

Terminal window
vantage websites delete <websiteId> # confirms by id
vantage websites delete <websiteId> --yes # skip confirm

This is a destructive operation. It:

  • Archives the GitHub repo
  • Deletes the Vercel project
  • Revokes secrets in Secrets Manager
  • Tears down any provisioned features (OpenRouter key revoked, Resend domain removed, etc.)
  • Removes the Website row from vantage-websites

If teardown of any single resource fails, the operation returns partial-success with an errors array — the row is still removed, and you can clean up the failed resource by hand.

  • Services — the integration rows attached to a Website
  • Provisioning — what the orchestrator actually does during provisioning status
  • Domains — attaching custom hostnames