Install
$ agentstack add skill-webflow-webflow-skills-webflow-cloud-command ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
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
webflow --version
If the command is not found, install it:
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:
# 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:
webflow auth login
Step 2: Deploy. The exact form depends on what the agent knows.
A1-a — Site-attached, --site-id is known:
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:
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:
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
- 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_idtowebflow.json, and exits 0. Read it back from the manifest and pass it as--workspace-idtocloud deployin 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.
# Returns a JSON array of sites with id, displayName, lastPublished, etc.
webflow sites list --json
Workflow:
- Run
webflow sites list --json. The CLI exits 0 with a JSON array. - Parse the output. Show the user a short list keyed by
displayName(andlastPublishedif the user has many sites). Example:
``` Which site should this project deploy to?
- Acme Marketing (last published 2 days ago)
- Acme Docs (last published 3 weeks ago)
- Acme Internal (never published)
```
- Map the user's pick back to its
idfield. 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.
- Deploy: pick the form matching the init form above. Pass
--site-id(or--workspace-idfor 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.
- 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 ``
- (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:
- Open the Webflow dashboard → their Cloud project → Settings → Git
- Connect their GitHub account, then select the repository and branch
- Confirm — the dashboard runs one initial deploy automatically to verify the connection
- 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.
- Deploy: read
webflow.jsonfirst. IfsiteIdis set, pass--site-idmatching it. If onlycloud.workspace_idis set, pass--workspace-idmatching it.
``bash webflow cloud deploy \ --no-input \ --site-id site_abc123 \ --mount / \ --environment main \ --skip-mount-path-check \ --skip-update-check ``
- 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).
- 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.
- 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 pushto that branch deploys. - One-off manual deploy now, without enabling push-to-deploy. Pass
--site-idmatching thesiteIdinwebflow.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
- Source: webflow/webflow-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.