> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gavai.io/llms.txt
> Use this file to discover all available pages before exploring further.

# gavai publish

> Promote the current draft of a page to live.

export const ErrorTable = ({errors}) => <div className="gv-error-table" role="table" aria-label="Errors and fixes">
    <div className="gv-error-table__head" role="row">
      <span className="gv-error-table__col-head" role="columnheader">Error</span>
      <span className="gv-error-table__col-head" role="columnheader">Cause</span>
      <span className="gv-error-table__col-head" role="columnheader">Fix</span>
    </div>
    {errors.map((err, i) => <div className="gv-error-table__row" role="row" key={i}>
        <code className="gv-error-table__code" role="cell">{err.code}</code>
        <div className="gv-error-table__cause" role="cell">{err.cause}</div>
        <div className="gv-error-table__fix" role="cell">{err.fix}</div>
      </div>)}
  </div>;

export const Def = ({term, type, defaultValue, required, children}) => <>
    <dt className="gv-def-list__term">
      <span className="gv-def-list__name">{term}</span>
      {type && <span className="gv-def-list__type">{type}</span>}
      {required && <span className="gv-def-list__required">required</span>}
      {defaultValue !== undefined && <span className="gv-def-list__default">
          default <code>{defaultValue}</code>
        </span>}
    </dt>
    <dd className="gv-def-list__description">{children}</dd>
  </>;

export const DefList = ({children}) => <dl className="gv-def-list">{children}</dl>;

export const BrandCard = ({eyebrow, title, href, icon, badge, cta, featured = false, horizontal = false, children}) => {
  const classes = ["gv-card", featured && "gv-card--featured", horizontal && "gv-card--horizontal"].filter(Boolean).join(" ");
  const inner = <>
      {icon && <span className="gv-card__icon" aria-hidden="true">
          <Icon icon={icon} />
        </span>}
      <div className="gv-card__main">
        {(eyebrow || badge) && <div className="gv-card__meta">
            {eyebrow && <Eyebrow label={eyebrow} tone="muted" />}
            {badge && <span className="gv-card__badge">{badge}</span>}
          </div>}
        <h3 className="gv-card__title">{title}</h3>
        {children && <div className="gv-card__body">{children}</div>}
        {cta && <span className="gv-card__cta">
            {cta}
            <svg className="gv-card__cta-arrow" viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <line x1="7" y1="17" x2="17" y2="7" />
              <polyline points="7 7 17 7 17 17" />
            </svg>
          </span>}
      </div>
    </>;
  return href ? <a className={classes} href={href}>
      {inner}
    </a> : <div className={classes}>{inner}</div>;
};

export const Eyebrow = ({label, tone = "default"}) => <div className={`gv-eyebrow gv-eyebrow--${tone}`}>
    <span className="gv-eyebrow__bar" aria-hidden="true" />
    <span className="gv-eyebrow__label">{label}</span>
  </div>;

<Eyebrow label="CLI" />

Promote the current draft of a page in the active workspace to live. Visitors see the new version immediately on the next request. This page covers the synopsis, what the server-side promotion does, and the exit codes a CI step should branch on.

## Synopsis

```bash theme={null}
gavai publish <id>
```

## Arguments

<DefList>
  <Def term="<id>" type="string" required>
    The page ID. Format: `page_01HXR...`.
  </Def>
</DefList>

## Flags

<Note>
  Run `gavai publish --help` for the authoritative flag list, including whether the page ID may also be passed as a flag in this version of the CLI.
</Note>

## Behavior

The command calls `POST /v1/workspaces/{slug}/pages-publish` against the active workspace. The server snapshots the current draft, writes it as the new live version, and invalidates the edge cache for that page. The response includes the publish timestamp and the number of page drafts promoted; the CLI prints it as JSON.

For the underlying endpoint's full contract, see the [Pages API reference](/api-reference/resources/pages).

<Warning>
  This writes to the live site immediately. For experimentation, run `gavai patch` against a test workspace, verify the draft with `gavai get`, and only then publish to production.
</Warning>

## Examples

Publish a single page:

```bash theme={null}
gavai publish page_01HXR8K2M4
```

Publish from CI after a successful build, branching on the exit code:

```bash theme={null}
if gavai patch page_01HXR8K2M4 --ops dist/patches.json; then
  gavai publish page_01HXR8K2M4
else
  echo "Patch rejected — leaving live version unchanged" >&2
  exit 1
fi
```

## Exit codes

<ErrorTable
  errors={[
{ code: "0", cause: "Draft promoted to live.", fix: "—" },
{ code: "2", cause: "Missing `<id>` or malformed ID.", fix: "Pass a `page_01H...`-shaped ULID." },
{ code: "3", cause: "Not authenticated.", fix: "Run `gavai login`." },
{ code: "4", cause: "Insufficient scope for this page.", fix: "Mint a token with `pages:publish`." },
{ code: "5", cause: "Page not found in the active workspace.", fix: "Confirm the ID and the workspace with `gavai whoami`." },
{ code: "6", cause: "No draft to publish, or concurrent publish in flight.", fix: "Run `gavai patch` to create a draft, or wait for the in-flight publish." },
{ code: "7", cause: "Network or API server error.", fix: "Retry with backoff." },
]}
/>

See [CLI overview — exit codes](/cli/overview#exit-codes) for the full table.

<BrandCard eyebrow="API REFERENCE" title="Pages resource" href="/api-reference/resources/pages">
  Full endpoint reference for listing, patching, publishing, and rolling back pages.
</BrandCard>
