/app).neuromast/ code. Webflow Cloud watches the branch you connect and redeploys on every push, so it needs write access to a repo you control — you can't point it at upstream Roach/axol. Easiest path is to fork Axol; alternative is to copy just the neuromast/ directory into a fresh repo.@webflow/webflow-cli only if you want local npm run dev / webflow cloud deploy for emergency manual pushes.neuromast/ to your own GitHub repoIf you forked Axol, skip to step 2 — your fork is already on GitHub. Otherwise, seed a fresh repo with just the neuromast/ tree:
cp -r neuromast /tmp/my-neuromast
cd /tmp/my-neuromast
git init -b main
git add .
git commit -m "seed neuromast"
gh repo create my-neuromast --private --source=. --push
Private is fine — Webflow Cloud's GitHub App reads private repos you grant it access to. The only env vars in the repo are placeholder shapes; real secrets never get committed.
Your site's Designer → Webflow Cloud (left nav, near the bottom) → New project.
Click Connect GitHub and authorize Webflow's GitHub App for the repo you just pushed. The dashboard will list the repo; select it and pick the branch to deploy (typically main).
If you seeded a fresh repo with just the neuromast/ contents, leave Root directory blank. If you forked the whole Axol repo, set Root directory to neuromast so Webflow builds from there and ignores the macOS app code.
Mount path: /app — must match base: '/app' in astro.config.mjs. All API routes live under <site>.webflow.io/app/api/… as a result.
Before the first deploy runs, add these in Environments → Variables (mark each as secret):
POLL_TOKEN — bearer the local forwarder uses for /pull + /ack. Generate with openssl rand -hex 32.SHARED_SECRET (optional) — query-key fallback for senders that can't sign HMAC. Same command.HOOK_SCHEME_<SOURCE> + HOOK_SECRET_<SOURCE> per signed source (e.g. HOOK_SCHEME_GITHUB=github, HOOK_SECRET_GITHUB=<your-repo-webhook-secret>).Webflow Cloud kicks off a deploy as soon as the repo is connected. Watch the Deployments tab — the first run builds the Astro bundle, auto-provisions the QUEUE KV namespace, and registers the /app mount.
When the dashboard shows Environment URL: Needs deployment, the worker built fine but the Webflow site hasn't been republished to expose the mount. Click Publish on the site (Designer → Publish) — the Environment URL flips to https://<your-site>.webflow.io/app.
export AXOL_CLOUD_URL=https://<your-site>.webflow.io
export POLL_TOKEN='the-bearer-you-set'
export SHARED_SECRET='the-shared-key-you-set'
curl -X POST "$AXOL_CLOUD_URL/app/api/hooks/smoke?key=$SHARED_SECRET" \
-H 'content-type: application/json' \
-d '{"title":"hello","body":"from the cloud"}'
curl -H "Authorization: Bearer $POLL_TOKEN" "$AXOL_CLOUD_URL/app/api/pull"
Expect 204 on the POST and a JSON body with your item on the GET. 401 on either means a mismatched env var — fix in the dashboard, then re-push or wait for the variable change to pick up on the next deploy.
With the cloud side live, wire up the bash + launchd forwarder on the machine running Axol. From the repo root:
AXOL_CLOUD_URL="$AXOL_CLOUD_URL" \
AXOL_POLL_TOKEN="$POLL_TOKEN" \
./lateral-line/install.sh
The installer renders a launchd plist with absolute paths and your env, drops it in ~/Library/LaunchAgents/, and loads it. Idempotent — re-run any time a token rotates.
With Axol running and the forwarder loaded:
curl -X POST "$AXOL_CLOUD_URL/app/api/hooks/demo?key=$SHARED_SECRET" \
-H 'content-type: application/json' \
-d '{"title":"remote alert","body":"delivered by the lateral line"}'
Within 15 seconds a speech bubble pops on your screen. tail -f ~/Library/Logs/Axol/lateral-line.log shows the pull → forward → ack cycle.
Every subsequent code change is just:
git push
Webflow Cloud watches the connected branch and kicks off a new deploy automatically. The Deployments tab shows the build log per commit; rollback is git revert and push again.
Env var changes take effect on the next deploy — edit in the dashboard, then either push an unrelated commit or click Redeploy on the latest deployment.
If GitHub is down or you need to test an unpushed branch:
npm install -g @webflow/webflow-cli
cd neuromast
webflow cloud deploy --mount /app --auto-publish
Requires running webflow cloud init once beforehand to authenticate and link to the site. Subsequent pushes to the connected GitHub branch will overwrite whatever the CLI deployed.
If POLL_TOKEN, SHARED_SECRET, or an HMAC secret leaks:
POLL_TOKEN: re-run lateral-line/install.sh locally with the new value to regenerate the launchd plist.GitHub App permissions are scoped per-repo. Go to github.com → Settings → Applications → Webflow Cloud → Configure, and grant access to the specific repo. The repo should then appear in the Webflow dashboard's picker.
If you forked the whole Axol repo, make sure the Root directory in the Webflow project settings is neuromast — otherwise Webflow tries to build from the repo root (which has no package.json) and the build dies immediately.
401 on every request
The worker deployed but env vars aren't set or the site wasn't republished after adding them. Dashboard → Environments → Variables, confirm the secret is present, then click Redeploy.
GET /pull always empty
The QUEUE binding may not have been provisioned. Check dashboard → Cloud → KV namespaces for an entry named QUEUE. If missing, push a trivial commit to trigger a fresh deploy — Webflow Cloud creates missing bindings on first build that references them.
The worker built but the Webflow site hasn't been republished to expose the mount path. Click Publish on the site in the Designer. The URL flips to https://<your-site>.webflow.io/app once the site publish completes.