Skip to main content

Maxisnap Studio 2.3.0 · for web developers and IT

Cloudflare setup: technical brief

Exactly what the Cloudflare edition’s deploy tool in the Studio download (cloudflare/deploy/cli.mjs) creates, the permissions it uses and why, what it refuses to do, where the credential lives, and how to revoke or remove everything. A developer runs it from a terminal, or the customer’s AI assistant runs it for them following AGENTS.md in the package: the same tool with the same plan-first checks either way.

Someone asked you to approve this? The plain-language version is the Studio setup guide.

Summary

  • Studio’s Cloudflare edition is one Worker (with static assets), one R2 bucket and one D1 database in the customer’s own account. Address: the account’s workers.dev subdomain, optionally one new Workers Custom Domain as well.
  • Setup is additive only. Existing names are refused, not reused; existing DNS records block a custom domain; removal deletes only what the deployment record says the tool created.
  • The tool runs on the customer’s or developer’s computer: node deploy/cli.mjs in the package’s cloudflare folder, with Node.js 20 or later and an API token in CLOUDFLARE_API_TOKEN. It reads the account, prints a plan, and changes nothing until it is run again with --yes. The deploy logic is cloudflare/deploy/engine.mjs.
  • No captures, library data, people or settings go to Maxisnap. Captures live in the customer’s R2 bucket; the library, people and settings in their D1 database.

What is created

ResourceNameNotes
Worker<name> from --name, default snapsES module Worker, compatibility date 2026-10-01, Workers Logs on, tag maxisnap-studio. Bindings: MEDIA (R2), DB (D1), ADMIN_KEY (secret). Static assets: the dashboard’s CSS, JS and fonts.
R2 bucket<name>-media (next free name if taken)Captures (media/) and browser-made previews (thumbs/). Default location and storage class.
D1 database<name> (next free name if taken)Library, people, sessions, settings. The Worker creates its schema on first request.
workers.dev address<name>.<subdomain>.workers.devEnabled for this Worker, also when it gets a custom domain; preview URLs off. If the account has no workers.dev subdomain yet, the customer chooses one and it is registered (account-wide; Cloudflare makes it hard to change later).
Custom domain (optional)e.g. snaps.example.comWorkers Custom Domain: Cloudflare creates one proxied DNS record and a certificate for that hostname only. The zone must be in the same account; while it is not active yet, the plan warns that the hostname will not work until it is.

The Admin key is 40 random characters, stored as the Worker secret ADMIN_KEY and shown to the customer once. The CLI generates it and prints it; the customer signs in to the dashboard with it and pastes it into the Maxisnap app to connect.

Permissions and why

API token permission Used for
Account Settings: Read List the accounts the credential can use.
Workers Scripts: Edit Read existing Worker names; upload Studio; enable workers.dev; register a workers.dev subdomain; attach the custom domain. On removal: detach the custom domain and delete the Worker.
Workers R2 Storage: Edit Check R2 is on; list bucket names; create the bucket. On removal with “delete data”: list and delete the bucket’s objects, then the bucket.
D1: Edit List database names; create the database. On removal with “delete data”: delete the database.
Zone: Read List the account’s domains: they appear in the plan’s “Will not touch” list, and the zone given with --zone is checked against them.
DNS: Read Refuse a hostname that already has DNS records.
Workers Routes: Read Refuse a hostname an existing Worker route (e.g. *.example.com/*) already covers. Without it the plan shows a warning instead.

No DNS, zone-settings, firewall, billing or user write permission is requested. Zone Read, DNS Read and Workers Routes Read are needed only for a custom domain. Create the token at My Profile → API Tokens as a custom token; scope it to one account, and to one zone for a custom domain, if you prefer.

Every API call

Read (planning)

GET  accounts
GET  user                                      (email for display; optional)
GET  accounts/{a}/r2/buckets                   (error 10042 = R2 not enabled yet)
GET  accounts/{a}/workers/subdomain
GET  accounts/{a}/workers/scripts
GET  accounts/{a}/d1/database
GET  zones?account.id={a}
GET  zones/{z}/dns_records?name={hostname}      (custom domain only)
GET  accounts/{a}/workers/domains?hostname={hostname}   (custom domain only)
GET  zones/{z}/workers/routes                  (custom domain only)

Write (after the customer confirms the plan)

PUT  accounts/{a}/workers/subdomain             (only when the account has none)
POST accounts/{a}/r2/buckets
POST accounts/{a}/d1/database
POST accounts/{a}/workers/scripts/{w}/assets-upload-session
POST accounts/{a}/workers/assets/upload?base64=true   (upload JWT, not the credential)
PUT  accounts/{a}/workers/scripts/{w}           (module upload with bindings)
POST accounts/{a}/workers/scripts/{w}/subdomain (enabled: true, previews_enabled: false)
PUT  accounts/{a}/workers/domains               (custom domain only)

Delete (removal only, and only for resources in the deployment record)

DELETE accounts/{a}/workers/domains/{id}
DELETE accounts/{a}/workers/scripts/{w}?force=true
DELETE accounts/{a}/d1/database/{id}            (only with "delete data")
GET    accounts/{a}/r2/buckets/{b}/objects      (only with "delete data": lists what to empty)
DELETE accounts/{a}/r2/buckets/{b}[/objects/…]  (only with "delete data")

Deletes run only from remove --record deployment.json --yes or by hand in the Cloudflare dashboard (see Revoke and remove).

An update (new Studio version or new branding) repeats the asset upload and the script PUT, plus the custom-domain call when a subdomain was newly chosen, and keeps the existing ADMIN_KEY secret.

What it refuses to do

  • Replace a Worker. A Worker name that already exists in the account is a blocker in the plan, unless the deployment record in use says this tool created it (an update, or finishing an install that stopped).
  • Rename your workers.dev subdomain. A subdomain is registered only when the account has none yet; otherwise --subdomain is ignored and the existing one is used.
  • Read your content. It lists bucket objects only to empty a bucket from its own record during remove --delete-data, and reads DNS records only for the one hostname being checked.
  • Take an existing hostname. Any DNS record at the name, a custom domain attached to another Worker, or an overlapping Worker route blocks the plan. The zone apex is refused.
  • Delete anything it did not create. remove touches only the resources the deployment record lists as created by the tool, and keeps the bucket and database unless --delete-data is given.
  • Act without a yes. plan only reads. deploy without --yes prints the plan and stops; update and remove also need --yes.
  • Take the token as an argument. The CLI reads it from the CLOUDFLARE_API_TOKEN environment variable; it has no command-line option for it.

An install that stops half-way (network drop, closed terminal) is recorded step by step in the deployment record; running the same deploy command again plans from that record and continues without creating anything twice.

Credential and local files

WhatWhere
Cloudflare API tokenRead from the CLOUDFLARE_API_TOKEN environment variable of the terminal session that runs the CLI.
Deployment record (names, ids, addresses, what it created; no secrets)deployment.json in the folder the CLI runs from (normally the package’s cloudflare folder), or the file given with --record. Updates and removal read it.
Admin keydeploy prints it once and stores it as the Worker secret ADMIN_KEY; it is not in the deployment record. The customer keeps it and pastes it into the Maxisnap app to connect.

Once connected, the Maxisnap app keeps the Studio address and key in its own settings on that computer (on a Mac, the key goes in the Keychain). It does not need the Cloudflare token.

Custom domain checklist

The Maxisnap desktop app uploads with an X-Dashboard-Key header, not a browser session. On the Studio hostname make sure that:

  • No Cloudflare Access application covers it (for example a wildcard *.example.com policy). Share links must also be reachable by the people you send them to.
  • Bot Fight Mode, Super Bot Fight Mode, Under Attack mode and WAF custom or managed rules do not challenge or block /api/*. A WAF skip rule for the Studio hostname is the simplest fix.
  • No Cache Rule or Page Rule forces caching of HTML or /api/*. Studio sends private, no-store and no-transform on media and pages.
  • Uploads arrive at /api/upload.php. Maxisnap for Windows and Maxisnap for Mac send each upload to a Cloudflare Studio in one request, which it accepts up to 25 MB per file.

A workers.dev address is not affected by zone settings, which is why it is the default.

Usage and cost

Studio is built for Cloudflare’s free plan. Cloudflare publishes the current free allowances, limits and prices; check them against your expected use.

ServiceStudio’s useCloudflare’s current terms
Workers Opening a share link is about two Worker requests. Route modules load lazily to stay inside the Free plan’s CPU time per request; measured CPU is 1–8 ms per request, warm. Static asset requests are served before the Worker runs. Workers pricing and limits
R2 Captures and their previews. Maxisnap for Windows and Maxisnap for Mac send each upload to a Cloudflare Studio in one request, which it accepts up to 25 MB per file. R2 pricing
D1 One row per capture, plus small session and settings rows. D1 pricing

Cloudflare may ask for a payment method before R2 can be turned on, even within the free allowance. Cloudflare’s Workers error list, read in October 2026, gives error 1027 as a Worker exceeding the free tier’s daily request limit. Its Workers limits page describes the current limits and the Workers Paid plan.

Revoke and remove

Revoke the deploy token

  • In Cloudflare: My Profile → API Tokens → delete the token you created for the deploy. An update or removal later needs a token with the same permissions.

Revoking does not affect the running Studio or uploads; those use the Studio’s own Admin key.

Remove the Studio

# PowerShell, in the cloudflare folder you deployed from (it holds deployment.json)
$env:CLOUDFLARE_API_TOKEN = "<token>"
node deploy/cli.mjs remove --record deployment.json --yes                 # keeps captures (bucket + database)
node deploy/cli.mjs remove --record deployment.json --yes --delete-data   # deletes everything it created

By hand in the dashboard: delete the custom domain (Worker → Settings → Domains & Routes), the Worker, then the R2 bucket (after emptying it) and the D1 database. The DNS record Cloudflare made for the custom domain is removed with the custom domain.

Doing it yourself

The cloudflare folder in the Studio package is a standard Wrangler project. cloudflare/README.md covers wrangler deploy; docs/Developer guide.html covers the architecture and upload API. With plain Wrangler you create the bucket and database yourself and check names by hand; the bundled CLI (node deploy/cli.mjs plan|deploy|update|remove|whoami) does the planning and guards described above. The developer route of the setup guide has the commands.

Questions about this brief?

Email support@maxisnap.com. Every Studio download also has a technical brief, docs/Cloudflare setup - technical brief.html.