Files
2026-07-26 11:29:19 +01:00

5.2 KiB
Raw Permalink Blame History

Something to Say

URL-based poster maker on Cloudflare Workers. paste text into the URL and get a styled image back.

Prerequisites

  • Node.js 18+
  • A Cloudflare account with Workers enabled
  • (Optional) An Upstash Redis account for PNG caching

Setup

1. Install dependencies

npm install

2. Login to Wrangler (Cloudflare CLI)

npx wrangler login

A browser window opens — authorise the CLI to access your Cloudflare account.

3. Create the D1 database (request tracking)

npx wrangler d1 create image_cache_db

Copy the returned database_id into wrangler.toml under [[d1_databases]].

Then run the migration:

# local dev
npx wrangler d1 execute image_cache_db --local --file=./schema.sql

# production (after first deploy)
npx wrangler d1 execute image_cache_db --remote --file=./schema.sql

4. Set up Upstash Redis (optional, for PNG caching)

PNG generation is slow without caching. SVG is instant. Redis caches generated PNGs so repeat requests are fast.

  1. Go to https://upstash.com and sign up
  2. Create a Redis database (free tier is enough)
  3. Copy the REST URL and REST Token from the dashboard

For local dev: Create .dev.vars in the project root:

UPSTASH_REDIS_REST_URL=https://your-upstash-url.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token

For production:

npx wrangler secret put UPSTASH_REDIS_REST_URL
# paste the URL, press Enter, Ctrl+D

npx wrangler secret put UPSTASH_REDIS_REST_TOKEN
# paste the token, press Enter, Ctrl+D

5. Configure a custom domain

Before you can route a worker to your own domain, the domain must exist in your Cloudflare account as a zone.

If your domain isn't in Cloudflare yet:

  1. Go to the Cloudflare dashboard → Add a Site
  2. Enter your domain (e.g. mydomain.com), pick the free plan
  3. Cloudflare will show two nameserver addresses (e.g. ns1.cloudflare.com, ns2.cloudflare.com)
  4. At your domain registrar, update the nameservers to those Cloudflare-provided ones
  5. Wait for propagation (minutes to hours — Cloudflare checks automatically)
  6. Your domain now appears under Websites in the dashboard

Once the domain is in Cloudflare, you have two options:

Note: Worker custom domains are managed under Workers & Pages in the Cloudflare dashboard (not the DNS section). The dashboard shows each custom domain's status and lets you remove or re-trigger provisioning.

Add to wrangler.toml:

routes = [
  { pattern = "yourdomain.com", custom_domain = true }
]

On deploy (npx wrangler deploy), Cloudflare auto-provisions the DNS record and SSL certificate. No manual DNS changes needed.

Also update PUBLIC_BASE_URL so OG image URLs are correct:

[vars]
PUBLIC_BASE_URL = "https://yourdomain.com"

Option B: manual CNAME record

If custom_domain doesn't work (e.g. the zone isn't fully active yet), create the record manually:

  1. Cloudflare dashboard → your domain → DNS
  2. Add Record:
    • Type: CNAME
    • Name: the subdomain, e.g. say (for say.mydomain.com)
    • Target: your worker's *.workers.dev URL (shown after wrangler deploy, e.g. my-worker.jeancnicolas.workers.dev)
    • Proxy: Proxied (orange cloud)
  3. Remove the routes block from wrangler.toml (the CNAME handles routing instead) or keep it — they can coexist.

Verify

After deploying with either option, visit your domain. If it doesn't resolve, check:

  • Is the domain listed under Websites in your Cloudflare dashboard? If not, add it first (steps above).
  • Did you redeploy after adding the route? Run npx wrangler deploy again.
  • Check route status: npx wrangler triggers shows the current routes for your worker.
  • DNS propagation: dig say.mydomain.com or use an online DNS checker to see if the record resolves.

Local dev

npm run dev

Opens at http://localhost:8787.

Deploy

npx wrangler deploy

First deploy checklist

After the first deploy:

  1. D1 migration (if not done yet):
    npx wrangler d1 execute image_cache_db --remote --file=./schema.sql
    
  2. Redeploy to pick up any config changes:
    npx wrangler deploy
    

How it works

  • / — interactive editor (drag sliders, pick themes, preview live)
  • /say/hello/world?theme=neon-noir — styled poster as SVG (instant)
  • /say/hello/world?theme=neon-noir&png — styled poster as PNG (slower, cached)
  • ?svg / ?png — explicitly request format
  • ?preset=x — platform presets (twitter, linkedin, instagram, etc.)
  • ?vw=N — custom viewport width (px)
  • ?scale — fluid mode (lines fill the container width)
  • ?ir=0.8 — inner content width ratio (0.31.0, default 1.0)
  • Inline markers: **bold**, *italic*, ==highlight==, ~underline~, {accent:text}, {color:text}

Updating secrets

To update an existing secret:

npx wrangler secret put UPSTASH_REDIS_REST_URL

Then redeploy. No code changes needed.

Viewing logs

npx wrangler tail

Cache headers

PNG responses include X-Cache: HIT or X-Cache: MISS so you can verify Redis caching in the Network tab.