A re-implementation of Shopify's internal Quick hosting platform (shopify.engineering/quick) built with Go, nginx, and AWS S3.
Project status: alpha. The CLI and the platform are usable, but the APIs and the UX still change. Expect breaking changes and rough edges.
Deploy any folder of static files. It is live on its own subdomain seconds later:
$ click deploy examples/hello --name hello
↑ index.html
↑ style.css
↑ app.js
↑ docs/index.html
✔ hello deployed: 4 uploaded, 0 unchanged, 0 deleted
http://hello.click.localhost:8080/No frameworks, no pipelines, no configuration files — "feels like the good old days of FTP."
Each deployed site is served on its own origin, behind employee sign-in. Each
site also gets a set of platform APIs without extra work: who is viewing
(/api/identity), a per-site document database (/api/db/*), a
realtime change stream, and read-only SQL. A folder of static files
can therefore be a real app with no server to run. Read
Building a site.
To understand or work on the platform itself, read ARCHITECTURE.md. It covers the architecture, how to run the platform locally, the authentication and ownership model, and how to deploy to production.
Get the binary for your operating system and architecture from the repository
Releases. Unpack it, then put
click on your PATH:
tar -xzf click_*_$(uname -s | tr A-Z a-z)_*.tar.gz click
sudo mv click /usr/local/bin/
click versionFrom then on, click update keeps the binary current. It verifies each
download against the release checksums before it swaps the binary. To build
from source instead, clone the repository and run make build. The binary
lands in bin/click.
click new <dir> --prompt "..." [--name <site>] [--deploy] generate a site with AI, optionally deploy it
click new <dir> --docs-only [--name <site>] write just AGENTS.md/CLAUDE.md into an existing folder
click deploy [dir] [--name <site>] [--keep-deleted] sync a folder to a site (default dir ".")
click list list deployed sites
click delete <site> [--keep-data] delete a site (files + database data)
click login sign in for authenticated platform calls
click logout forget the cached credentials
click access <site> show a site's owner and collaborators
click share <site> <email> grant someone deploy access (owner only)
click unshare <site> <email> revoke deploy access (owner only)
click version print the CLI version
click update update to the latest release
click deploy [dir] [--name <site>] — syncs a folder to the storage of
the site, the way gcloud rsync does. It uploads only the files whose
contents changed, and it deletes the remote copies of files that you deleted
locally. --keep-deleted keeps those remote copies. The site name defaults to
the directory name, sanitized to a DNS label ([a-z0-9-]). On an
authenticated platform the first deploy claims the site name for you.
click new <dir> --prompt "..." [--name <site>] [--deploy] — generates a
complete site from a natural-language prompt and writes it to <dir>. Add
--deploy with --name to publish the site in the same command. It also
writes an AGENTS.md and a CLAUDE.md into the folder, so a coding agent can
keep working on the site afterwards. Each generation takes a few minutes.
Generation runs on the platform when you are signed in. If you are not signed
in, it falls back to your local ANTHROPIC_API_KEY.
click new <dir> --docs-only [--name <site>] — writes only that
AGENTS.md and CLAUDE.md pair: the iteration rules plus the full platform
API guide. There is no AI call, no API key, and no other file is touched. Use
it to make a hand-written or existing site self-describing for a coding agent.
--prompt is optional here and only fills in the "what this site is" note.
The command refuses to overwrite agent docs that are already there, unless you
pass --force.
click delete <site> [--keep-data] — deletes the files of the site and
purges its database documents. It also releases the name, so that anyone can
claim the name again. --keep-data keeps both the documents and the claim,
for example before you redeploy under the same name.
click login / logout — sign in once through your browser. Tokens are
cached under your OS configuration directory and refreshed automatically. You
need this only on platforms that enforce authentication (read
deploying to a hosted platform). On a headless
machine, CLICK_NO_BROWSER=1 click login prints the URL for you to open.
click share / unshare / access — the owner of the site grants or
revokes deploy access for teammates, and sees who has access now.
click help <command> (or --help) documents the flags of any command. And
click completion bash|zsh|fish|powershell prints a shell-completion script —
for example source <(click completion zsh) in your shell rc file.
| Variable | Purpose |
|---|---|
CLICK_API_URL |
Platform URL for API calls (default http://<CLICK_DOMAIN>) |
CLICK_DOMAIN |
Domain that sites are served under (default click.localhost:8080) |
CLICK_BUCKET |
S3 bucket name (default click-sites) |
CLICK_S3_ENDPOINT |
Custom S3 endpoint, for example MinIO. Empty means real AWS S3 |
CLICK_OIDC_ISSUER |
OIDC provider for click login. Unset means no CLI authentication |
CLICK_OIDC_CLIENT_ID / CLICK_OIDC_CLIENT_SECRET |
The OIDC client of the CLI (public client, so the secret is not sensitive) |
CLICK_AUTH_TOKEN |
Bearer token to send as it is, instead of a login (CI) |
CLICK_NO_BROWSER |
1 makes click login print the URL instead of opening a browser |
CLICK_CA_FILE |
PEM bundle of extra CAs to trust for HTTPS, merged with the system roots (default: ca.pem in the configuration directory of the CLI, if present) |
ANTHROPIC_API_KEY |
Claude API key for the local fallback of click new (not needed when you are signed in to a platform that generates) |
CLICK_AI_MODEL |
Model for click new (default: the choice of the platform, or claude-opus-5 locally) |
CLICK_UPDATE_REPO / CLICK_UPDATE_API |
Override the source that click update pulls releases from (forks, testing) |
AWS_* |
Standard AWS credential chain (used only when the platform does not vend scoped credentials) |
To point the CLI at a deployment of the platform instead of your local stack, export the domain and the identity provider of that deployment. DEPLOY.md shows how to stand one up.
export CLICK_DOMAIN=click.example.com
export CLICK_API_URL=https://click.example.com
export CLICK_OIDC_ISSUER=https://dex.click.example.com/dex
export CLICK_OIDC_CLIENT_ID=click-cli
export CLICK_OIDC_CLIENT_SECRET=click-cli # public client; not a secret
export CLICK_BUCKET=my-click-sites # the platform's S3 bucket
export AWS_REGION=us-west-2 # that bucket's region
click login
click deploy ./site --name my-appLeave CLICK_S3_ENDPOINT and any AWS_ACCESS_KEY_* from local testing
unset. No AWS credentials are necessary: each deploy writes with the
per-site scoped credentials that the platform mints for you.
A deployment can serve a certificate that your system roots do not trust
already. Two examples are a private corporate CA, and Let's Encrypt
staging on a
pre-production environment. In that case, put the issuing root into the
configuration directory of the CLI once. Every click command then trusts it
from then on:
# macOS (Linux: ~/.config/click)
mkdir -p "$HOME/Library/Application Support/click"
cp issuing-root.pem "$HOME/Library/Application Support/click/ca.pem"
click loginThe CLI merges ca.pem (or a file named by CLICK_CA_FILE) into the
system roots. SSL_CERT_FILE replaces them instead, and it cannot satisfy
a deploy that talks to the staging-certificate platform and to real-certificate
AWS S3 in the same run. The extra trust applies only to the click process.
Nothing on the machine changes.
A platform with publicly-trusted certificates needs none of this.
A deployed site is only static files (HTML, CSS, and JS — no build step). On
its own origin, the platform gives every page a shared API, so plain fetch()
is the whole integration. There is no server, no CORS, and no API key in your
code:
GET /api/identity— who is viewing the page (email, name)./api/db/{collection}— a per-site document database (schemaless JSON, CRUD), isolated so that other sites can never read it.GET /api/db/events— a Server-Sent Events stream, so open tabs update live when data changes.GET /api/db-token— a read-only, site-scoped token for direct SQL reads (when the platform runs the libSQL backend).
The complete author-facing guide is docs/site-api.md:
every endpoint, the rules, and worked examples. It is written to double as
context for an LLM or an agent. The examples/ folder holds working sites:
hello (identity), guestbook (documents and realtime), and demo (the
whole API surface). You can also let click new write one for you.
Start at ARCHITECTURE.md for the component map, the
request path, and the repository layout. From there:
DESIGN.md covers the document database, the authentication
and ownership model, and per-site data isolation.
DEPLOY.md covers the local stack, the test suites, and the
production blueprint for EKS and Terraform, whose Kubernetes manifests are
checked in under kubernetes/.