Pastebin on Cloudflare worker, with friendly CLI usage and rich features
See the codeThis is a pastebin running on Cloudflare workers. Try it on shz.al.
Philosophy: effortless deployment, friendly CLI usage, rich functionality.
Features:
Content-Type and Content-Disposition.You can post, update, delete your paste directly on the website (such as shz.al).
It also provides a convenient HTTP API to use. See API reference for details. You can easily call API via command line (using curl or similar tools). Note that a single request body is capped at 100 MB by Cloudflare (the platform returns HTTP 413 for larger bodies before the worker runs) — for larger files, use the website or the pb CLI below, which transparently chunk the upload.
pb is a Python script (requires Python 3.9+ with the requests package) to make it easier to use on command line; it automatically switches to multipart upload above 5 MiB and shows a progress bar.
doc/skill.md is a concise, AI-agent-oriented packaging of the API. Make it available to your coding agent so it can upload, fetch, and manage pastes via this service.
You are free to deploy the pastebin on your own domain if you host your domain on Cloudflare.
Install node and pnpm.
Clone the repository and enter the directory.
Create a KV namespace and R2 bucket, fill the KV namespace ID and R2 bucket name in wrangler.toml.
$ pnpm wrangler kv namespace create PB
$ pnpm wrangler r2 bucket create <name>
Modify entries in wrangler.toml. Its comments will tell you how.
Login to Cloudflare and deploy with the following steps:
$ pnpm install
$ pnpm wrangler login
$ pnpm build:frontend
$ pnpm deploy
The service runs on Cloudflare Workers, Workers KV, and R2. Each has a free tier; beyond it you pay only for what you use. Figures below are accurate as of writing — prices change, so confirm against the official pricing pages before relying on them:
R2_THRESHOLD. Egress is free. Class A op = upload (PutObject); Class B op = fetch (GetObject). Cloudflare rounds storage up to the next GB-month.
wrangler.toml.
Costs scale primarily with: large file traffic (R2 ops + storage), high-volume reads (Workers requests + KV reads), and verbose logging (Workers Logs events).
Bottom line — what each tier comfortably handles:
[!NOTE] Small pastes go to KV (not R2) to keep garbage collection cheap. KV honors per-key expiration natively, so expired pastes vanish on their own. R2 has no built-in expiration, so cleaning up expired objects would require periodically listing and scanning every object in the bucket — costly in Class A/B ops as the bucket grows.
If you want a private deployment (only you can upload paste, but everyone can read the paste), add the following entry to your wrangler.toml.
[vars.BASIC_AUTH]
user1 = "$2b$08$i/yH1TSIGWUNQVsxPrcVUeR0hsGioFNf3.OeHdYzxwjzLH/hzoY.i"
user2 = "$2b$08$KeVnmXoMuRjNHKQjDHppEeXAf5lTLv9HMJCTlKW5uvRcEG5LOdBpO"
Passwords here are hashed by bcrypt2 algorithm. You can generate the hashed password by running ./scripts/bcrypt.js.
Now every access to POST request, and every access to static pages, requires an HTTP basic auth with the user-password pair listed above. For example:
$ curl example-pb.com
HTTP basic auth is required
$ curl -Fc=@/path/to/file example-pb.com
HTTP basic auth is required
$ curl -u admin1:wrong-passwd -Fc=@/path/to/file example-pb.com
Error 401: incorrect passwd for basic auth
$ curl -u admin1:this-is-passwd-1 -Fc=@/path/to/file example-pb.com
{
"url": "https://example-pb.com/YCDX",
"admin": "https://example-pb.com/YCDX:Sij23HwbMjeZwKznY3K5trG8",
"isPrivate": false
}
Delete a paste:
$ pnpm delete-paste <name-of-paste>
List pastes:
$ pnpm -s wrangler kv key list --binding PB > kv_list.json
Note that the frontend and worker code are built separatedly. To start a Vite development server of the frontend,
$ pnpm dev:frontend
To develop the backend worker, we must build a develop version of frontend,
$ pnpm build:frontend:dev
Then starts a local worker,
$ pnpm dev
The difference between build:frontend:dev and build:frontend is that the former will points the API endpoint to your deployment URL, while the later points to http://localhost:8787, the address of a local worker.
Run tests:
$ pnpm test
Run tests with coverage report:
$ pnpm coverage
Remember to run eslint checks and prettier before commiting your code.
$ pnpm fmt
$ pnpm lint
$ pnpm typecheck
105 followers · starred May 2026
6 followers · starred Dec 2023
400 followers · starred Apr 2023
19 followers · starred Jul 2025
Pastebin on Cloudflare worker, with friendly CLI usage and rich features
See the codeThis is a pastebin running on Cloudflare workers. Try it on shz.al.
Philosophy: effortless deployment, friendly CLI usage, rich functionality.
Features:
Content-Type and Content-Disposition.You can post, update, delete your paste directly on the website (such as shz.al).
It also provides a convenient HTTP API to use. See API reference for details. You can easily call API via command line (using curl or similar tools). Note that a single request body is capped at 100 MB by Cloudflare (the platform returns HTTP 413 for larger bodies before the worker runs) — for larger files, use the website or the pb CLI below, which transparently chunk the upload.
pb is a Python script (requires Python 3.9+ with the requests package) to make it easier to use on command line; it automatically switches to multipart upload above 5 MiB and shows a progress bar.
doc/skill.md is a concise, AI-agent-oriented packaging of the API. Make it available to your coding agent so it can upload, fetch, and manage pastes via this service.
You are free to deploy the pastebin on your own domain if you host your domain on Cloudflare.
Install node and pnpm.
Clone the repository and enter the directory.
Create a KV namespace and R2 bucket, fill the KV namespace ID and R2 bucket name in wrangler.toml.
$ pnpm wrangler kv namespace create PB
$ pnpm wrangler r2 bucket create <name>
Modify entries in wrangler.toml. Its comments will tell you how.
Login to Cloudflare and deploy with the following steps:
$ pnpm install
$ pnpm wrangler login
$ pnpm build:frontend
$ pnpm deploy
The service runs on Cloudflare Workers, Workers KV, and R2. Each has a free tier; beyond it you pay only for what you use. Figures below are accurate as of writing — prices change, so confirm against the official pricing pages before relying on them:
R2_THRESHOLD. Egress is free. Class A op = upload (PutObject); Class B op = fetch (GetObject). Cloudflare rounds storage up to the next GB-month.
wrangler.toml.
Costs scale primarily with: large file traffic (R2 ops + storage), high-volume reads (Workers requests + KV reads), and verbose logging (Workers Logs events).
Bottom line — what each tier comfortably handles:
[!NOTE] Small pastes go to KV (not R2) to keep garbage collection cheap. KV honors per-key expiration natively, so expired pastes vanish on their own. R2 has no built-in expiration, so cleaning up expired objects would require periodically listing and scanning every object in the bucket — costly in Class A/B ops as the bucket grows.
If you want a private deployment (only you can upload paste, but everyone can read the paste), add the following entry to your wrangler.toml.
[vars.BASIC_AUTH]
user1 = "$2b$08$i/yH1TSIGWUNQVsxPrcVUeR0hsGioFNf3.OeHdYzxwjzLH/hzoY.i"
user2 = "$2b$08$KeVnmXoMuRjNHKQjDHppEeXAf5lTLv9HMJCTlKW5uvRcEG5LOdBpO"
Passwords here are hashed by bcrypt2 algorithm. You can generate the hashed password by running ./scripts/bcrypt.js.
Now every access to POST request, and every access to static pages, requires an HTTP basic auth with the user-password pair listed above. For example:
$ curl example-pb.com
HTTP basic auth is required
$ curl -Fc=@/path/to/file example-pb.com
HTTP basic auth is required
$ curl -u admin1:wrong-passwd -Fc=@/path/to/file example-pb.com
Error 401: incorrect passwd for basic auth
$ curl -u admin1:this-is-passwd-1 -Fc=@/path/to/file example-pb.com
{
"url": "https://example-pb.com/YCDX",
"admin": "https://example-pb.com/YCDX:Sij23HwbMjeZwKznY3K5trG8",
"isPrivate": false
}
Delete a paste:
$ pnpm delete-paste <name-of-paste>
List pastes:
$ pnpm -s wrangler kv key list --binding PB > kv_list.json
Note that the frontend and worker code are built separatedly. To start a Vite development server of the frontend,
$ pnpm dev:frontend
To develop the backend worker, we must build a develop version of frontend,
$ pnpm build:frontend:dev
Then starts a local worker,
$ pnpm dev
The difference between build:frontend:dev and build:frontend is that the former will points the API endpoint to your deployment URL, while the later points to http://localhost:8787, the address of a local worker.
Run tests:
$ pnpm test
Run tests with coverage report:
$ pnpm coverage
Remember to run eslint checks and prettier before commiting your code.
$ pnpm fmt
$ pnpm lint
$ pnpm typecheck
105 followers · starred May 2026
6 followers · starred Dec 2023
400 followers · starred Apr 2023
19 followers · starred Jul 2025