Skip to content
hurl.page/blog
Product

Hurl, you say? Why we built a pastebin for whole websites

Bart PelleChief Hurler

· 5 min read

We kept zipping HTML reports and emailing them around like it was 2009. So we built the dumbest possible deploy button: one endpoint you throw a page at, one live URL back. This is the story, the design rules, and the fine print.

The Friday-afternoon zip file

Every team we've been on produces a steady trickle of disposable HTML. Coverage reports. Lighthouse runs. A Playwright trace viewer. The prototype someone hacked together over lunch and wanted exactly one opinion on. None of it ever had anywhere to live.

So it lived nowhere. The ritual was always the same: build the file, zip it, drop it in Slack, then watch the thread fill up with which file do I open? and screenshots of file:// paths. That's file sharing, not publishing — and nobody is going to provision an S3 bucket and a CloudFront distribution for an artifact with a three-day life expectancy.

A loose whiteboard sketch: a terminal window with a long arrow arcing over to a browser window.
The original sketch, October 2025. The arrow did most of the product thinking.

One endpoint, one URL

hurl.page is a pastebin for whole websites. You POST an HTML file at one endpoint; we host it on its own unguessable subdomain and return the URL in the response. That is the entire integration surface — no config file, no project setup, not even an account.

deploy.sh

curl -X POST https://hurl.page/deploy \  -H "Content-Type: text/html" \  --data-binary @report.html

https://vast-juice-c2dse08p.hurled.page/

The response is a small JSON object with the URL right at the top, so | jq -r .url pipes it into pbcopy or straight into a PR comment. Deploys land in about a second, because there is nothing to build — we store exactly the bytes you sent. Whole build folders work too: send a zip (or a Pages-style JSON manifest) and every file mounts at the subdomain root, so absolute paths like /app.js resolve exactly like on any normal host.

What people actually hurl

  • Coverage and test reports straight out of CI
  • Single-file Storybook builds and Playwright traces
  • Before/after Lighthouse runs for performance reviews
  • One-page proposals that would otherwise have been a PDF

Named drops

Random subdomains are the right default for one-offs, but reviews want stability. Subscribers can pass ?name=pr-42 and get a stable URL that updates in place on every redeploy — the content changes, the link your reviewers bookmarked doesn't. There's a whole post on how named drops work.

No account required

Anonymous drops need no signup at all and live for 7 days — or shorter, via ?ttl=. On a paid plan drops never expire by default, and named drops are included.

The constraints we kept

Half of what makes a tool like this useful is what it refuses to do. Every feature request gets tested against four rules, in order:

  1. One request per deploy. The moment hurl.page needs a config file, we've failed.
  2. The URL is the product. No viewer chrome, no interstitial, no banner injected into your markup. You get back exactly the page you sent.
  3. Static only. If your page needs a server, you've outgrown us — and that's fine.
  4. Boring infrastructure. Object storage, a CDN, and a small router. Nothing exotic enough to page anyone at 3 a.m.

These rules have killed some genuinely tempting ideas (so far: build pipelines, comments, an analytics dashboard). We'd rather stay the tool you never have to think about.

Every drop lands on a subdomain with roughly 62 bits of entropy — a two-word slug plus a random tail, long enough that guessing one is a lottery you cannot win, short enough to read out over a call. There's no public index and no directory page, so drops are unlisted, not public. And user content is served only on *.hurled.page — never on the origin you sign in on.

We did the actual math — collision odds, what 62 bits buys you against a determined scanner — in a separate engineering post. The honest summary: a link is a perfectly good credential for review artifacts, and the wrong one for anything regulated. If a leaked URL would be an incident, put the page behind your SSO and use a different tool. We'd rather be clear about that boundary than blur it.

Limits and the fine print

Pricing follows the same shape as the product: small numbers, no metering, no surprises at the end of the month.

| Plan | What you get | | --- | --- | | Free $0 | Anonymous deploys, 7-day drop lifetime, zips up to 25 MB | | Pro $4/mo | No expiry, any ttl, named drops, 100 MB zips, up to 10,000 files per drop | | Team $19/mo | Everything in Pro, plus a vanity subdomain for your named drops |

Expired means deleted

When a drop's expiry hits, it serves a 410 and an hourly sweep deletes the content from storage. There is no trash folder and no recovery, so keep your own copy of anything you care about.

That's also a feature: the half-finished prototype you hurled in March isn't quietly sitting on the public internet in November.

Where it goes from here

“I replaced a Jenkins job, an S3 bucket, and a Slack bot with one line of curl.”

— beta tester, week two of the private beta

The private beta confirmed the hunch. The first thing most testers built wasn't a workflow — it was an alias. alias hurl=... showed up independently in three different dotfiles repos within a week.

What ships today: the API, the dashboard, and a GitHub Action that posts a preview link on every pull request. Next on the list: tar.gz uploads for big asset trees, a one-time "keep forever" option for anonymous drops, and password-protected drops. If you've got a report rotting in a Slack thread right now, the API docs are its way out.

Written by

Bart Pelle

Chief Hurler

Bart founded Bitgate and crowned himself Chief Hurler — a fancy title for “throws HTML at an API all day and occasionally writes about it.” If a build's on fire, he's the one who lit it. Usually on purpose.

Share

XHacker News