ZL-Asica/Gravatar-Worker
A fast, modern, and cache-friendly Gravatar CDN proxy — built with Cloudflare Workers and Hono.
Gravatar Worker
A fast, modern, and cache-friendly Gravatar CDN proxy — built with Cloudflare Workers and Hono.
Supports:
- MD5 / SHA-256 hash or raw email lookups
- Smart caching (Edge + Browser)
- Auto image format conversion to AVIF or WebP based on
Acceptheader - Customizable via environment variables
- Lightweight and fast (powered by Cloudflare Workers + Hono)
🧩 Customization
See CUSTOMIZATION.md for a 5-minute after-fork checklist and detailed guidance.
Environment Variables
| Name | Purpose | Default |
|---|---|---|
SITE_NAME |
Site/brand name shown in titles and UI | ZLA Gravatar CDN |
SITE_TAGLINE |
Optional tagline appended to the title | (see defaults) |
SITE_DESCRIPTION |
Meta description and OG description | (see defaults) |
SITE_URL |
Canonical origin (used for OG/canonical/sitemap) | https://gravatar.zla.app |
OG_IMAGE_URL |
OG image path or URL | /og.png |
FAVICON_PATH |
Favicon path | /favicon.ico |
ROBOTS_ALLOW |
true/false/1/0 or custom meta value |
true |
FOOTER_TEXT |
Footer label (linked if CONTACT_URL is set) |
ZL Asica |
CONTACT_URL |
Footer contact link | https://zla.pub/ |
ME_EMAIL |
Email for /avatar/me (hashed server-side) |
unset |
ME_HASH |
Precomputed MD5/SHA-256 for /avatar/me |
unset |
ALLOW_RAW_EMAIL |
Allow /avatar?email= endpoint |
true |
DEFAULT_SIZE |
Default avatar size | 200 |
MAX_SIZE |
Maximum avatar size | 2048 |
CACHE_TTL_BROWSER |
Browser cache TTL for 200 responses (seconds) | 259200 |
CACHE_TTL_EDGE |
Edge cache TTL for 200 responses (seconds) | 604800 |
HASH |
Legacy hash env for /avatar/me |
unset |
🌐 Endpoints
🔹 GET /avatar/me
Fetches the maintainer's Gravatar avatar with no params needed.
Example:
GET /avatar/me🔹 GET /avatar/:hash
Fetches the Gravatar avatar via precomputed MD5 or SHA-256 hash.
Example:
GET /avatar/205e460b479e2e5b48aec07710c08d50?s=128🔹 GET /avatar?email=<email>
Fetches the avatar by raw email (safely hashed server-side). If the email is invalid, it falls back to email@example.com.
Example:
GET /avatar?email=email@example.com&size=256⚙️ Query Parameters
| Param | Description | Default |
|---|---|---|
s or size |
Image size in pixels (square, e.g. 128x128) | 200 |
d or default |
Default fall back option (e.g. a URL, or 404) | 404 |
🎨 Format Negotiation
Automatically returns the most optimized format:
image/avif(if supported)image/webp(fallback)- Original JPEG (fallback fallback 🙃)
Based on the browser’s Accept header:
Accept: image/avif,image/webp,image/*,*/*📦 Caching Strategy
| Response | Browser TTL | Edge TTL | Stale-While-Revalidate | Notes |
|---|---|---|---|---|
200 OK |
3 days | 7 days | 7 days | Long-term caching with background refresh |
404 |
5 minutes | 1 hour | 1 hour | Allows retry for new users |
Built-in Cloudflare CDN handles global delivery and bandwidth optimization. The cache strategy uses:
Cache-Controlfor browser cachingCDN-Cache-Controlfor edge caching (longer TTL)Vary: Acceptfor proper content negotiationETagfor efficient cache validation
🧪 Tech Stack
- Cloudflare Workers – fast and global by design
- Hono – lightweight routing framework (also Hono JSX for API doc)
- @jsquash – AVIF/WebP encoding via WASM
- TypeScript – strong typing, strict mode
- Pure CSS – custom theme 💮
🧾 License
This project is licensed under the MIT License.