Drop a folder of HTML, get a URL. Plus a zero-config database, realtime, file uploads and AI – all on your own Cloudflare account, on the free tier.
OpenQuick is an open-source, self-hosted take on Quick, Shopify's internal hosting platform that changed how their teams build and share ("demos over memos"). Shopify runs Quick on a single $200/month VM behind their IAP. OpenQuick gives you the same experience on Cloudflare Workers for $0.
pnpm add -g openquick # or: npm i -g openquick
oquick setup # one-time: deploys the platform to YOUR Cloudflare account
oquick init lunch-poll
cd lunch-poll
oquick deploy # → https://openquick.<you>.workers.dev/lunch-poll/That's the whole thing. The only requirement is a Cloudflare account – oquick setup uses
wrangler (bundled) and opens the browser login if needed. The defaults give you:
- the hub at your platform URL – drag & drop deploys from the browser, site directory
- public sites (anyone with a URL can view), token-gated deploys (only you can publish)
- AI, database, realtime and file APIs on every site, rate-limited inside the free tier
Tune the install at setup time – or any time later, re-running oquick setup is always safe:
| flag | what it does |
|---|---|
--no-hub / --hub |
turn the hub page (drag & drop deploys at the root URL) off / back on |
--private / --public |
org mode: require Cloudflare Access logins for everything (see below) |
--open-deploys / --token-deploys |
playground mode: anyone may deploy sites, no token (delete keeps it) |
--chat-model <@cf/…> |
quick-wide default chat model (or pick from a list later: oquick models) |
--image-model <@cf/…> |
quick-wide default image model |
--limits '<json>' |
override rate limits – AI caps, deploy caps, site ceiling, storage quota |
--worker-name <name> |
the worker / workers.dev URL prefix (default openquick) |
And the everyday mode switches, no setup re-run needed:
oquick token open # playground mode on (oquick token require = off)
oquick auth enable # org mode, guided (oquick auth disable = off)
oquick models # pick default AI models from a curated list
oquick domain add quick.you.com # pretty URLs on your own domainOrg mode (oquick auth enable) is the full Shopify-Quick experience: everything behind a
login (free ≤50 users via Cloudflare Zero Trust), teammates deploy from the hub with no token,
and quick.id() returns verified emails. Needs a custom domain; oquick auth enable walks
you through the two dashboard steps. oquick auth disable reopens the platform.
Include one script tag and window.quick is your backend:
<script src="__quick.js"></script>// Firebase-style JSON database, namespaced per site
const posts = quick.db.collection('posts');
const doc = await posts.create({ title: 'Hello Quick DB' });
await posts.update(doc.id, { status: 'published' });
const all = await posts.list({ order: 'desc' });
// Realtime: changes sync to every connected client
posts.subscribe({
onCreate: (doc) => console.log('new:', doc),
onUpdate: (doc) => console.log('changed:', doc),
onDelete: (id) => console.log('gone:', id),
});
// Multiplayer channels with presence
const room = quick.channel('lobby');
room.send({ cursor: [x, y] });
room.on('message', (data, from) => { ... });
// File uploads
const { url } = await quick.files.upload(file);
// AI – Workers AI on your account, zero API keys in the client
const text = await quick.ai.chat('haiku about deploys');
const { url: img } = await quick.ai.image('a watercolor fox');
// Identity
const me = await quick.id(); // stable anonymous id (+ email behind Cloudflare Access)No schemas, no migrations, no API keys, no per-site provisioning. oquick init also drops an
AGENTS.md/CLAUDE.md with the full API reference, so any coding agent can build sites
out of the box – same trick as Quick's quick init.
Shopify's Quick is NGINX + a GCS bucket + one small API server + one database. OpenQuick is the
same idea translated to Cloudflare primitives, needing nothing beyond a normal wrangler login:
| Quick (Shopify) | OpenQuick (your Cloudflare account) |
|---|---|
| NGINX + GCS bucket + gcsfuse | one Worker serving assets from SQLite |
| small node/Go API server | the same Worker, /__api/* |
| CloudSQL "big JSON store" | one Durable Object per site (SQLite) |
| big files in the bucket | shared R2 bucket, folder per site (automatic) |
| websockets | the same DO, hibernating WebSockets |
| AI proxy, keys on the server | Workers AI binding |
| IAP identity | anonymous ids, or Cloudflare Access (optional) |
quick deploy (rsync wrapper) |
oquick deploy (hash-diff upload, FTP feel) |
| $5–$200/mo VPS + separate AI bills | $0 (free tier) / $5 Workers Paid – AI included |
Each site is one Durable Object: its files, documents, uploads and live websocket connections all live together – "namespace per site", exactly like Quick's data model. Deploys are atomic (a manifest swap in one transaction) and diffed (unchanged files never re-upload).
Big files spill to R2 automatically. Files over 5 MB skip SQLite and land in a shared R2
bucket under the site's folder (sites/<site>/…) – Shopify's exact bucket-of-folders layout –
raising the per-file cap from 25 MB to ~95 MB with zero configuration. Setup creates the bucket
if the account has R2 enabled (free 10 GB tier, one-time enable in the dashboard); without it,
everything still works with the 25 MB cap. oquick delete removes the site's R2 folder along
with its Durable Object.
- workers.dev (default, zero config):
https://openquick.<you>.workers.dev/<site>/ - Your domain, path mode (free):
oquick domain add quick.yourdomain.com→https://quick.yourdomain.com/<site>/– needs one proxied DNS record (the CLI walks you through it). - Wildcard subdomains (the true Quick feel):
oquick domain add quick.yourdomain.com --wildcard→https://<site>.quick.yourdomain.com/. Note: Universal SSL only covers one subdomain level – use a dedicated zone (*.myquicksites.comis free) or Advanced Certificate Manager for second-level wildcards.
oquick open your hub: drag & drop a folder, get a URL
oquick . deploy the current folder (any dir path works)
oquick setup provision/upgrade the platform worker
oquick init [name] scaffold a site + agent docs
oquick deploy [dir] [--name x] deploy a folder (diff upload) → URL
oquick list all sites with size + last deploy
oquick open <site> open in browser
oquick delete <site> [-y] delete a site and all its data
oquick token print the deploy token (for hub teammates)
oquick dev [dir] [--port 4400] local server against the real deployed API
oquick domain add|list|remove custom domains
The platform's root URL is a deploy surface: a Quick-style hub where anyone you choose can drag & drop a folder and get a site – no CLI, no node, nothing installed. It shows every site on the platform, celebrates fresh deploys with confetti, and deletes sites too.
Sharing it: run oquick token, send a teammate the hub URL + token, they paste it once
(it stays in their browser's localStorage). Deploys and deletes require the token; browsing
sites doesn't. oquick opens the hub with your token handed over automatically via the URL
fragment (fragments never leave the browser).
Roadmap – org mode: Cloudflare Access in front of the hub + sites (free ≤50 users), so anyone on the Cloudflare account just logs in with their identity provider and deploys from the hub with no token at all – the full IAP-style Quick experience.
Anything static – a file is just bytes served back with the right content type. HTML, CSS, JS,
images (png/jpg/webp/avif/svg/gif), video and audio (mp4/webm/mp3 – big files get Range support,
so seeking works), fonts, JSON, WASM, PDFs. Unknown extensions download as files; source files
like .py serve as readable plain text.
What does not work: anything that needs a server to execute. A Python script, PHP file, or
Express app will upload and be served, but nothing runs it – there is no server runtime by
design. The backend is exclusively the quick.js APIs (db, realtime, files, AI, channels).
Client-side code is the loophole: JS and WASM run in the browser, so even Python works if you
load it with Pyodide.
Quick works because it sits behind Shopify's identity proxy – everything is trusted. Your OpenQuick is on the public internet, so the defaults differ:
- Deploys/deletes require a bearer token, generated at setup, stored in
~/.config/openquick/config.jsonand as a Worker secret. Only you can publish sites. - Playground mode (
oquick token open) drops the token for deploys so anyone can publish through your hub – the full Geocities-energy Quick. Deletes keep the token, and tokenless visitors get per-IP daily deploy caps plus a platform-wide site limit (defaults 50/day and 500 sites, tunable via--limits '{"deploy_ip":…,"max_sites":…}').oquick token requirerestores the gate. - Site APIs (db/files/ai/channels) are open to anyone who has a site's URL – that's the zero-config magic, same trade Quick makes. Guardrails: per-visitor daily rate limits (AI is limited hardest), per-site caps, and cross-origin calls are blocked.
- Don't put secrets in documents; don't treat the db as private.
- Private mode (optional): put Cloudflare Access (free up to 50 users) in front of a custom
domain and set
ACCESS_TEAM_DOMAIN+ACCESS_AUDvars on the worker – then sites are IAP-protected exactly like Shopify's, andquick.id()returns verified emails.
Every Cloudflare account – free and paid – gets 10,000 free Workers AI neurons per day. On the free plan AI simply stops when they're spent (no bill possible); on Workers Paid, overage costs $0.011/1k neurons, so OpenQuick adds account-wide ceilings (below) to keep the worst case at pocket change.
Sites pick models per call with an alias or any full catalog id; the platform owner picks the
quick-wide defaults from a curated list of recent models with oquick models:
| alias | model | ≈ free calls/day* |
|---|---|---|
| (default) | @cf/google/gemma-4-26b-a4b-it |
~580 |
fast |
@cf/zai-org/glm-4.7-flash |
~610 |
best |
@cf/moonshotai/kimi-k2.6 |
~50 |
| image | @cf/black-forest-labs/flux-2-klein-4b |
~90 images |
*at ~1k input + 300 output tokens per call (or one 1024px image), within the daily 10k free
neurons. The list also includes Qwen3 30B (~700/day, the cheapest), Nemotron 3 120B, the
gpt-oss pair and FLUX.1 Schnell / FLUX.2 Klein 9B for images – oquick models chat <n> /
oquick models image <n> switches the default and redeploys.
Caps are merged over sensible defaults:
oquick setup --limits '{"ai_chat_platform_site":5000,"ai_chat_ip":250}'Default caps: 100 chat + 30 image calls per visitor/day, 1000 + 300 per site/day,
2000 chat + 300 images account-wide/day (the drain guard – ≈$1–2/day worst case on paid,
$0 on free). The MODELS var can also remap the fast/best aliases.
- 100k requests/day to the worker and 100k DO requests/day (an asset hit costs one of each)
- 5 GB total DO storage across all sites + 10 GB free R2; 95 MB max per file (25 MB without R2); 256 KB per document
- Workers AI free allocation: 10k neurons/day
- All caps reset daily;
$5/mo Workers Paidraises them to 10M+ requests and unlimited storage
Heavy traffic to one site? Workers Paid + a custom domain (which enables edge caching) is the upgrade path.
packages/platform the Worker + SiteDO (Durable Object) – the entire backend
packages/sdk quick.js, the browser SDK (served by the worker at /__quick.js)
packages/cli oquick – setup, deploy, domains, dev server
templates/ what `oquick init` scaffolds (incl. agent docs)
examples/guestbook realtime guestbook with AI – try `oquick deploy examples/guestbook`
Per Quick's philosophy ("we've gotten really good at saying no… the constraints are the whole point"): no custom backends, no cron jobs, no permissions/site owners, no build pipelines. Compose the primitives instead.
Inspired by Quick: An internal hosting platform for the AI era by Daniel Beauchamp & Alex Pilon, and Daniel's thread on how a folder of files, a lightweight API and some trust changed how Shopify builds. MIT licensed; not affiliated with Shopify or Cloudflare.