The Shield API
A single GET endpoint returns a fresh SVG rendered on the Cloudflare edge — no client-side JavaScript, no third-party CDN, no stale cache.
Every badge is built from four simple query parameters, validated at the edge, and returned as an immutable image/svg+xml response in under 40ms p99.
GET https://newshields.vercel.app/api/badge.svg?label=…&title=…&icon=…&theme=…
Quick start
Drop this one-liner into any README, blog post, or HTML page and you're done:
 Or embed it as an <img> tag in any HTML document:
<img src="https://newshields.vercel.app/api/badge.svg?label=Built+with&title=Svelte&icon=svelte&theme=aurora" alt="Built with Svelte" /> Endpoint
There is one public endpoint. All parameters are passed as query strings.
The endpoint is served from Cloudflare's global edge network. Requests are rate-limited to 60 per minute per IP. Responses are cached with Cache-Control: public, max-age=31536000, immutable.
Parameters
All parameters are optional — sane defaults are applied when omitted.
| Name | Type | Default | Max length | Description |
|---|---|---|---|---|
label | string | Powered by | 28 chars | Upper-line text displayed above the title. |
title | string | New Shields | 36 chars | Lower-line bold text — the main badge name. |
icon | string | svelte | — | Any SVGL slug. Unknown slugs render a placeholder. |
theme | enum | aurora | — | One of the 8 preset themes. See Themes. |
Validation rules
- Strings are URL-decoded and trimmed before validation.
- Parameters exceeding max length return
400 Bad Request. - Unknown
themevalues silently fall back toaurora. - Unknown
iconslugs render an empty placeholder rectangle.
Themes
Eight hand-tuned presets are available. Each defines a surface gradient, accent border, glow color, and text colors for label and title.
Pass the theme name as the theme query parameter. Full palette definition in src/content/themes.ts.
Response
A successful request returns 200 OK with the following headers:
HTTP/1.1 200 OK
Content-Type: image/svg+xml; charset=utf-8
Cache-Control: public, max-age=31536000, immutable
Vary: Accept-Encoding The body is a fully self-contained <svg> — embedded gradients, inline icon <path> data, no external font or image requests.
Errors
Error responses are plain text with an appropriate HTTP status code.
| Status | When |
|---|---|
400 | A parameter exceeds its maximum length or is otherwise invalid. |
429 | Rate limit exceeded — more than 60 requests per minute from the same IP. |
500 | Renderer error. Edge-cached responses may still be served. |
GitHub READMEs
GitHub proxies all <img> tags through camo, a server-side image proxy. This means the badge is fetched once by camo and cached — individual visitors don't hit the edge directly.
To bust GitHub's camo cache and force a re-fetch, append a version query string:
 Increment v whenever you want GitHub to pull a fresh version.
Self-host
New Shields is MIT-licensed. Deploy your own instance to Cloudflare Pages in three commands:
git clone https://github.com/konlyzx/newshields
cd newshields && pnpm install
pnpm deploy The API lives in src/routes/api/badge.svg/+server.ts and only depends on the Cloudflare Workers runtime — no Node-specific APIs required.