尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Free meme generator on Cloudflare Workers: a drag-and-drop editor for 200+ templates plus a URL-based meme API (every meme is just a link).
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗A free meme generator that runs entirely on Cloudflare Workers: an in-browser editor for 450+ templates, plus a URL-based API where every meme is just a link.
GET /images/{template}/{top}/{bottom}.png renders a meme on the fly, with
fonts, colors, styles, overlays, custom backgrounds, and animated GIF/WebP output.
Interactive docs live at /docs.GET /images/buzz/memes/memes_everywhere.png
GET /images/ds/small_file/high_quality.jpg?style=maga&width=800
GET /images/oprah/you_get/animated_text.gif
POST /images {"template_id": "fry", "text": ["not sure if", "or just"]}
Every template has a human-facing, SEO-friendly editor page rendered by src/views/editor.ts:
| Route | Purpose |
|---|---|
/ | Index of all templates with search (/?q= also works server-side) |
/memes/{slug} | Canvas editor for one template (name-based; old ids and slugs redirect) |
/agents, /llms.txt | Guide for AI agents, as a page and as raw markdown (src/docs/agents.ts) |
/privacy | What the site collects (src/views/privacy.ts); update it when that changes |
/sitemap.xml | Lists the index and every editor page |
/robots.txt | Allows crawling of the pages, disallows the JSON API paths, links the sitemap |
/static/* | Stylesheet and scripts (assets/static/, cache-busted with ?v=<version>) |
/assets/templates/{id}/{f} | Raw template images used by the editor canvas |
/assets/fonts/{file} | Font files loaded by the editor with the FontFace API |
/proxy/image?url= | Fetches a remote image (10 MB max, images only) so the canvas can use it |
The editor (assets/static/editor.js) runs entirely in the browser, imgflip-style:
Each page is server-rendered with a unique title, meta description, canonical URL, Open
Graph and Twitter Card tags (the example meme is the social image), JSON-LD (WebSite
with SearchAction, WebPage, ImageObject, BreadcrumbList), an <h1>, descriptive
copy, the template's source link, keyword links, and related templates. Without JavaScript
a <noscript> form posts to POST /images instead.
The site name in titles and social cards comes from the SITE_NAME variable.
The site is installable: /manifest.webmanifest (icons generated by
npx tsx scripts/build-icons.ts into assets/static/icons/), a service worker at /sw.js
(assets/static/sw.js, its cache name bound to the asset content hash so every deploy
refreshes caches), and an /offline fallback page. The worker serves pages network-first
with an offline fallback, and caches static assets, fonts, template images, and the last
80 rendered memes cache-first. On phones, assets/static/pwa.js shows a closeable
"Install" banner: Chrome/Android use the native prompt, iOS gets "Share → Add to Home
Screen" instructions; dismissal is remembered for 14 days and the banner never shows once
the app is installed.
Every template page explains what the meme is, where it comes from, its alternate names,
and related tags, so people can find a template by describing it rather than knowing its
name. The search on / (and ?q=) matches names, aliases, keywords, tags, example text,
and the description; multi-word queries require every word to match.
data/descriptions.json is fetched from each template's Know Your Meme entry by
npm run fetch:descriptions (short About/Origin excerpts, tags, alternate names). It
only refetches missing or failed entries; pass --force to refresh everything.data/descriptions.manual.json holds hand-written entries for templates without a Know
Your Meme source; these override fetched data. Add an entry here for any new template.scripts/build-templates.ts merges both into the manifest and warns about templates
that still lack a description.Know Your Meme excerpts are short, attributed, and linked; write original copy in the manual file when you want fully unique page text.
Requirements: Node 20+, a Cloudflare account for deployment.
npm install
npm run dev # http://localhost:8787 (runs the template build first)
npm test # vitest inside the Workers runtime
npm run typecheck
npm run deploy # wrangler deploy (uploads the Worker + ~90 MB of template assets)
Cloudflare's free plan limits Workers to 10 ms of CPU per request, which is not enough
to render images. Deploy on the Workers Paid plan; wrangler.jsonc sets a 30 s CPU limit.
Variables are defined in wrangler.jsonc (vars). Secrets go through wrangler secret put
or a local .dev.vars file (see .dev.vars.example).
| Variable | Purpose |
|---|---|
SITE_NAME | Name used on the web pages and social cards (Memegenscript) |
DEBUG | "true" draws text/overlay boxes, enables /test, disables caching |
DOMAIN | Host used in absolute URLs (defaults to the request's own origin) |
DEFAULT_STATIC_EXTENSION | Extension used when none is requested (png) |
DEFAULT_ANIMATED_EXTENSION | Extension for animated templates (gif) |
CACHE_TTL | Seconds to keep rendered images in the edge cache (0 disables) |
REMOTE_TRACKING_URL | Optional memecomplete backend for API keys, tokens, search, tracking |
REMOTE_TRACKING_ERRORS_LIMIT | Errors before request tracking turns itself off (10) |
The API began as a TypeScript port of memegen (Python), whose template library it still uses; the editor, pages, search, and design are original. The table shows what replaced each Python-era dependency:
| Concern | Originally (memegen, Python) | Memegenscript |
|---|---|---|
| HTTP | Sanic | Worker fetch handler + ordered regex router (src/router.ts) |
| Template metadata | templates/*/config.yml via datafiles | Same YAML, compiled to src/generated/templates.json at build |
| Template images, fonts | Local filesystem | Workers Static Assets (assets/, read via the ASSETS binding) |
| Text measurement & glyphs | Pillow + FreeType | opentype.js (src/images/layout.ts) |
| Rasterizing text/overlays | Pillow ImageDraw | SVG built in src/images/layer.ts, rendered by resvg (wasm) |
| Resize, blur, compositing | Pillow | Pure TypeScript (src/images/raster.ts) |
| PNG / JPEG / WebP codecs | Pillow, webp | jSquash wasm codecs |
| GIF | Pillow | gifuct-js (decode) + gifenc (encode) |
| Animated WebP | webp package | Per-frame encode + hand-written ANMF muxer (src/images/webp.ts) |
| Emoji | emoji + pilmoji (Twemoji) | emojilib aliases + Twemoji images (src/utils/emoji.ts) |
style: mock text | spongemock (seeded random) | MT19937 port with CPython seeding (src/utils/mt19937.ts) |
| Rendered image cache | images/ directory on disk | Cache API (caches.default), keyed by request URL |
| Custom backgrounds/overlays | Downloaded to templates/_custom-<sha1>/ | Downloaded on demand, cached with the Cache API |
Request flow for GET /images/{template}/{text}.{ext}:
src/views/images.ts normalizes the slug and handles redirects (style, watermark, tokens).src/views/helpers.ts#renderImageResponse resolves the template, validates every
parameter and picks the status code exactly like the Python view.src/images/render.ts decodes the background, resizes it, renders the foreground layer
(overlays + text) once per distinct animation state, pads/watermarks, and encodes.Drop a directory into assets/templates/<id>/ with a config.yml and a default.png
(or .jpg/.gif), exactly as in the Python project. Extra images in the directory become
style= options. The manifest is rebuilt automatically by npm run dev, npm test and
npm run deploy (or run npm run build:templates).
/meme-characters lists classic meme characters (Doge, Wojak, Pepe, Trollface, …) as
transparent PNG cutouts that visitors can download or copy. Each character lives in
assets/characters/<id>/ as a config.yml (name, aliases, keywords, description, source, and
the templates it appears in) plus a default.png. scripts/build-characters.ts (run by npm run build:templates) compiles
them into src/generated/characters.json and fails the build if a PNG is not a real cutout
(8-bit RGBA with both transparent and opaque pixels). The API exposes them at GET /characters
(?q= searches), GET /characters/{id} and GET /characters/{id}.png?width=400.
The full guide lives in docs/guide.md and the client notes in docs/clients.md. Everything from the original README applies:
.png, .jpg, .gif, .webp (GIF/WebP animate the text on static backgrounds)width / height (both → padded to exact size), layout=top, font=<id|alias>color=<line1>,<line2> (names or hex, # optional), style=<name> or style=<url>[,<url>]background=<url> with template_id=custom, center, scale, frames, start, stop_/- → space, __ → _, -- → -, ~q ~a ~p ~h ~s ~b ~l ~g ~n, '' → ":aliases:DEBUG mode does not write new template config files to disk (there is no disk)./ serves the template index page instead of redirecting to /docs.assets/ templates/, characters/, fonts/, static/ (served by Workers Static Assets)
scripts/ build-templates.ts → src/generated/templates.json
build-characters.ts → src/generated/characters.json
src/index.ts routes + CORS + error handling
src/views/ one module per Sanic blueprint
src/models/ Template, Character, Text, Overlay, Font
src/images/ codecs, raster ops, text layout, SVG layer, render pipeline
src/utils/ slug codec, urls, colors, emoji, remote tracking, sha1, mt19937
src/docs/ OpenAPI document + Swagger UI page
test/ vitest (runs inside workerd via @cloudflare/vitest-pool-workers)
MIT. Portions of the API and the template library come from
memegen by Jace Browning (MIT); see
LICENSE.txt. Template images belong to their respective owners. Font licenses are in
assets/fonts/. Meme descriptions quote short, attributed excerpts from Know Your Meme.