# Webflow Cli:cloud

> Initialize, build, and deploy full-stack Webflow applications to Webflow Cloud hosting. Supports site-attached deploys (linked to an existing Webflow site) and project app deploys (independent project, no existing site required). Use when creating new projects, deploying existing ones, or setting up CI/CD pipelines for Webflow Cloud.

- **Type:** Skill
- **Install:** `agentstack add skill-webflow-webflow-skills-webflow-cloud-command`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [webflow](https://agentstack.voostack.com/s/webflow)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [webflow](https://github.com/webflow)
- **Source:** https://github.com/webflow/webflow-skills/tree/main/plugins/webflow-skills/skills/webflow-cloud-command

## Install

```sh
agentstack add skill-webflow-webflow-skills-webflow-cloud-command
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Webflow Cloud

Initialize new projects from templates and deploy to Webflow Cloud. Supports two modes: **site-attached** (deploy to an existing Webflow site) and **project app** (deploy as an independent project, no existing site required).

## Instructions

### Step 0: Verify CLI is installed

```bash
webflow --version
```

If the command is not found, install it:

```bash
npm install -g @webflow/webflow-cli@latest
# or yarn global add @webflow/webflow-cli@latest
# or pnpm add -g @webflow/webflow-cli@latest
```

Then proceed to state detection.

### Step 1: Detect project state

Run both checks before deciding which path to follow:

```bash
# Is this project already set up on Webflow Cloud?
cat webflow.json

# Is there a git remote?
git remote get-url origin 2>/dev/null
```

**Quick reference:**

| `cloud.project_id` in `webflow.json` | git remote | → Path |
|---|---|---|
| No | — | **A** — new project |
| Yes | No | **B** — existing project, no git |
| Yes | Yes | **C** — ideal state |

---

> **You are running without a TTY.** The CLI's interactive prompts only fire when `process.stdin.isTTY` is true. As an agent invoking the CLI through a subprocess, you do not have a TTY — every prompt is silently skipped, and any required value that wasn't passed as a flag triggers a hard error like `--project-name cannot be empty`.
>
> **Rule for every command in this skill:** pass all required flags explicitly. Never rely on prompts. Pass `--no-input` when the CLI accepts it to make this contract explicit. The required flag set per command:
>
> | Command | Always pass |
> |---|---|
> | `cloud init` (site-attached) | `--no-input --project-name  --framework  --mount  --site-id ` |
> | `cloud init --new` (app) | `--no-input --project-name  --framework  --workspace-id ` |
> | `cloud deploy` (site-attached) | `--no-input --mount  --environment  --site-id ` plus `--project-name` on first deploy |
> | `cloud deploy` (project app, first deploy) | `--no-input --mount  --environment  --workspace-id  --project-name ` |
>
> `--site-id`, `--project-id`, `--framework`, and `--workspace-id` on `cloud deploy` let agents override what's in `webflow.json` at deploy time.
>
> **Multi-workspace tokens used to be an agent-fatal hang** because workspace selection had no non-TTY path. Now pass `--workspace-id` to skip the picker. **The workspace ID is not surfaced anywhere in the Webflow dashboard UI** — users can't look it up by hand. If the agent doesn't have it, ask the user to run `webflow cloud deploy` interactively once from inside their project. The preflight prompts for workspace selection and writes `cloud.workspace_id` to `webflow.json`; from that point the agent can read it from the manifest and pass `--workspace-id` on subsequent runs. Do **not** suggest `cloud init --new` for ID discovery — on an existing project it creates a discarded scratch directory. **Exception:** in Path A2 (empty directory) it *is* safe to try `cloud init --new` without `--workspace-id` to auto-resolve a single-workspace token — see [Path A2](#path-a2-empty-directory-scaffold-from-scratch).
>
> **Site IDs are visible in the dashboard.** When `--site-id` is needed but unknown, do not ask the user for a raw `site_XXXX` value — use [`webflow sites list`](#picking-a-site-id-from-a-list) to fetch their sites and present a picker keyed by display name. Users can still check their dashboard to fetch it.

---

### Path A: No `project_id` — new project

The project has not been deployed yet. **Before doing anything else, ask the user one question:**

> "Do you already have source code for this project (an existing Next.js or Astro codebase), or are you starting from an empty directory and want a Webflow starter scaffold?"

That answer chooses the branch — and they're meaningfully different:

| User has... | Branch | Init step |
|---|---|---|
| **Existing code** (their own Next.js / Astro project) | **Path A1** | **Skip `cloud init`.** It would create a `.//` subfolder with a hello-world scaffold inside their repo, which they don't want. |
| **Empty directory** or wants a Webflow starter | **Path A2** | Run `cloud init` to scaffold from `Webflow-Examples/hello-world-*`. |

After the branch decision, also ask **site-attached vs app** (only relevant before the first deploy):

| User says... | Mode | Outcome |
|---|---|---|
| "deploy to my Webflow site ``", "site-attached", references an existing site | **Site-attached** | Project is bound to an existing Webflow site; site URL hosts the app at the chosen mount path. Requires `--site-id`. |
| "project app", "standalone", "just an app", "no site", or no existing site mentioned | **Project app** | First deploy provisions a brand-new Webflow site (`-.webflow.io`). |

If the user is ambiguous on either question, **ask**. Do not default.

---

#### Path A1: existing codebase, no Webflow Cloud config yet

The user has working source. `cloud deploy` handles everything — framework detection runs against `package.json`, and the preflight phase resolves identity from flags or prompts the user. No `cloud init` needed, no `webflow.json` to hand-write up front.

**Step 1: One-time auth (human-only).** Tell the user to run this locally; agents cannot drive the browser flow:

```bash
webflow auth login
```

**Step 2: Deploy.** The exact form depends on what the agent knows.

**A1-a — Site-attached, `--site-id` is known:**

```bash
webflow cloud deploy --no-input \
  --site-id site_abc123 \
  --project-name my-app \
  --framework nextjs \
  --mount /app \
  --environment main \
  --skip-mount-path-check \
  --skip-update-check
```

`--framework` is optional if `package.json` has the framework's Cloudflare adapter (`@opennextjs/cloudflare`, `@astrojs/cloudflare`). Pass it explicitly for monorepos or when auto-detection is unreliable.

If the agent doesn't know the user's `--site-id`, do **not** ask for a raw `site_XXXX` value — use [`webflow sites list`](#picking-a-site-id-from-a-list) to fetch the user's sites and present readable display names to pick from.

**A1-b — Project app, `--workspace-id` is known:**

```bash
webflow cloud deploy --no-input \
  --workspace-id ws_abc123 \
  --project-name my-app \
  --framework nextjs \
  --mount / \
  --environment main \
  --skip-mount-path-check \
  --skip-update-check
```

**A1-c — Project app, workspace ID is unknown** (the common gap):

**The workspace ID is not visible anywhere in the Webflow dashboard UI.** Users cannot look it up by hand — the only way to discover it is to run the CLI. So the path is:

**Ask the user to run one interactive deploy locally.** From inside their project directory:

```bash
webflow cloud deploy
```

With no `--no-input` and no identity flags, the preflight prompts: *"This project isn't initialized for Webflow Cloud. How would you like to deploy?"* → user picks "Create a new app" → workspace picker → done. After this one human-driven deploy, `cloud.workspace_id` and `siteId` are written to `webflow.json` and `WEBFLOW_SITE_ID` to `.env`. The agent can then run all subsequent deploys with `--site-id` (the newly provisioned site).

> Do **not** ask the user to run `cloud init --new` to "discover" their workspace ID. On an existing project that creates a discarded `.//` scratch directory with a hello-world scaffold inside the user's repo. Use the interactive `cloud deploy` path above — it discovers the workspace ID *and* completes the first deploy in the same step.

**Step 3: Set up git** (if not already) — same as Path A2 step 3 below.

---

#### Path A2: empty directory, scaffold from scratch

1. **Scaffold the project** — pick the form that matches the user's intent:

   ```bash
   # Project app (no site attachment). --workspace-id avoids the multi-workspace hang.
   webflow cloud init --new --no-input \
     --project-name my-app \
     --framework astro \
     --workspace-id ws_abc123
   ```

   ```bash
   # Site-attached (connect to an existing Webflow site). Requires --site-id.
   webflow cloud init --no-input \
     --project-name my-app \
     --framework astro \
     --mount /app \
     --site-id site_abc123
   ```

   See [`cloud init`](#webflow-cloud-init) for all flags.

   **Workspace ID discovery for project apps in Path A2 only:** because Path A2 starts from an empty directory, `cloud init --new` creates a fresh scaffold either way — there's nothing to pollute. So if the agent doesn't have `--workspace-id`, it's safe to **try `cloud init --new` without it first**:

   ```bash
   # Try this first if --workspace-id is unknown (Path A2 only — empty dir)
   webflow cloud init --new --no-input \
     --project-name my-app \
     --framework astro
   ```

   - **Single-workspace tokens:** the CLI auto-selects the only workspace, writes `cloud.workspace_id` to `webflow.json`, and exits 0. Read it back from the manifest and pass it as `--workspace-id` to `cloud deploy` in step 2.
   - **Multi-workspace tokens:** the workspace picker fires and the command hangs (no TTY). **Set a 30-second timeout on the Bash call** (or wrap the command in `timeout 30s ...`) — a successful single-workspace init completes in 10–20 seconds (OAuth check + `GET /v2/workspaces` + scaffold download from GitHub), so anything past 30s with no output is the picker hanging. Once the timeout fires, ask the user for the workspace ID directly and re-run with `--workspace-id`.

   For **site-attached** in Path A2, there is no equivalent auto-discovery — `--site-id` is always required up front. Use the [site picker](#picking-a-site-id-from-a-list) pattern below to help the user pick.

   **Path A1 (existing codebase) does not get this trick.** Running `cloud init --new` in an existing project creates a discarded scratch subdirectory. The Path A1 workspace-ID discovery path stays as documented in Path A1-c.

#### Picking a `--site-id` from a list

When `--site-id` is needed (Path A1 site-attached, Path A2 site-attached, or anywhere else) and the user hasn't given one, use `webflow sites list --json` to enumerate sites the token can see, then present a short list of readable names for the user to choose from. The site ID is visible in the Webflow dashboard URL config, but a numeric-ID prompt is bad UX; surface display names instead unless asked for IDs.

```bash
# Returns a JSON array of sites with id, displayName, lastPublished, etc.
webflow sites list --json
```

Workflow:

1. Run `webflow sites list --json`. The CLI exits 0 with a JSON array.
2. Parse the output. Show the user a short list keyed by `displayName` (and `lastPublished` if the user has many sites). Example:

   ```
   Which site should this project deploy to?

   1. Acme Marketing  (last published 2 days ago)
   2. Acme Docs       (last published 3 weeks ago)
   3. Acme Internal   (never published)
   ```

3. Map the user's pick back to its `id` field. Pass that as `--site-id`.

If `webflow sites list` errors (auth missing / expired), surface the error and ask the user to run `webflow auth login` locally; do not try to drive it from the agent.

2. **Deploy:** pick the form matching the init form above. Pass `--site-id` (or `--workspace-id` for project-app first deploy) so the deploy can't misread the manifest if something is half-written.

   ```bash
   # Project-app first deploy — provisions the Cloud site/project/env
   webflow cloud deploy \
     --no-input \
     --project-name my-app \
     --workspace-id ws_abc123 \
     --mount / \
     --environment main \
     --skip-mount-path-check \
     --skip-update-check
   ```

   ```bash
   # Site-attached first deploy — uses the existing Webflow site
   webflow cloud deploy \
     --no-input \
     --project-name my-app \
     --site-id site_abc123 \
     --mount /app \
     --environment main \
     --skip-mount-path-check \
     --skip-update-check
   ```

   This creates the project on Webflow Cloud and sets `cloud.project_id` in `webflow.json`. Commit the updated `webflow.json`.

3. **Set up git** (if not already):
   ```bash
   git init && git add . && git commit -m "init"
   git remote add origin https://github.com/your-org/my-app.git
   git push -u origin main
   ```

4. **(Optional) Enable push-to-deploy via the Webflow dashboard.** Pushing to GitHub alone does **not** trigger deploys — that wiring lives in the Webflow dashboard, not in the CLI or the repo. Tell the user:

   1. Open the Webflow dashboard → their Cloud project → **Settings** → **Git**
   2. Connect their GitHub account, then select the repository and branch
   3. Confirm — the dashboard runs one initial deploy automatically to verify the connection
   4. From that moment on, every push to the connected branch triggers a deploy

   The CLI cannot perform any of these steps. If the user skips this, every deploy must be a manual `webflow cloud deploy` invocation (Path B–style) or a CI/CD pipeline.

> If a deploy auth error occurs in step 2: run `webflow auth login`, complete the browser flow, then retry.

---

### Path B: `project_id` exists, no git remote — existing project, no git

The project is already on Webflow Cloud but has no git repo. Deploy directly and nudge toward git setup.

1. **Deploy:** read `webflow.json` first. If `siteId` is set, pass `--site-id` matching it. If only `cloud.workspace_id` is set, pass `--workspace-id` matching it.

   ```bash
   webflow cloud deploy \
     --no-input \
     --site-id site_abc123 \
     --mount / \
     --environment main \
     --skip-mount-path-check \
     --skip-update-check
   ```

2. **Nudge toward push-to-deploy:** suggest the user initialize a git repo, push to GitHub, **and then connect the repo in the Webflow dashboard** (project → Settings → Git). The dashboard step is what activates push-to-deploy — the CLI can't do this. See Path A, steps 3–4.

> If a deploy auth error occurs: run `webflow auth login`, complete the browser flow, then retry step 1.

---

### Path C: `project_id` exists + git remote — possibly ideal

The project is deployed and has a git remote, **but the existence of a remote is not proof that push-to-deploy is wired up.** That wiring is a dashboard-side connection that the CLI can't introspect. Confirm before suggesting anything.

> **Always ask the user:** *"Is this repo connected to your Webflow Cloud project in the dashboard (project → Settings → Git, with a branch selected)?"* The answer changes the recommendation:
>
> - **Yes, connected** — push-to-deploy is active. The only action needed is `git push`. Do not suggest re-linking or re-deploying.
> - **No, not connected** — `git push` does nothing on the Webflow side. Either run a manual deploy now, or have the user connect the repo in the dashboard first to activate push-to-deploy for future commits.
> - **Don't know** — assume not connected and recommend the dashboard connection (one-time setup, then push-to-deploy is permanent).

1. **If connected** — just commit and push:
   ```bash
   git add .
   git commit -m "your message"
   git push
   ```
   Webflow Cloud picks up the push and deploys automatically. The first deploy after connection is run by the dashboard itself; subsequent pushes are picked up automatically.

2. **If not connected** — two routes:

   - **Activate push-to-deploy for future commits** (recommended). Tell the user to open the Webflow dashboard → their Cloud project → **Settings** → **Git**, connect the repo, select the branch. The dashboard runs an initial deploy automatically to verify the connection. From then on, every `git push` to that branch deploys.
   - **One-off manual deploy now**, without enabling push-to-deploy. Pass `--site-id` matching the `siteId` in `webflow.json`:
     ```bash
     webflow cloud deploy \
       --no-input \
       --site-id site_abc123 \
       --mount / \
       --environment main \
       --skip-mount-path-check \
       --skip-update-check
     ```
     This deploys the current state but does **not** wire up push-to-deploy. The next `git push` will still be a no-op on the Webflow side

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [webflow](https://github.com/webflow)
- **Source:** [webflow/webflow-skills](https://github.com/webflow/webflow-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-webflow-webflow-skills-webflow-cloud-command
- Seller: https://agentstack.voostack.com/s/webflow
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
