create-web-manifest
Skill0 starsChanged 2 months agoMITView on GitHub
Give a web app a complete install identity — favicon set, PWA and home-screen icons, web app manifest, and the <head> meta that iOS, Android and link-preview crawlers read. Use when shipping or deploying a web app, or when the user mentions favicon, app icon, apple-touch-icon, web manifest, PWA, "add to home screen", install prompt, theme color, a stock scaffold title, or icons that look wrong, blurry, black, or cropped on a phone.
In this repository6 other files it gives its agents.
- AGENTS.mdAGENTS.md
- design-critiqueSkill
- md2htmlSkill
- optimize-skillSkill
- research-codebaseSkill
- search-skillSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 87
Before the first edit the original HTML is copied to <file>.bak and the path is reported — tell the user, since that is their undo if the …
- Very specific: line 97
No mark? Author one first: Write a 512×512 SVG to the project, then pass --source.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
create-web-manifest
One source mark in, a shippable install identity out: every icon size, a complete
manifest.webmanifest, and a <head> block — then an audit that proves it.
Run
Determine this SKILL.md's own directory as {baseDir}. Dry-run first, always:
node "{baseDir}/create-web-manifest.mjs" <project-dir> --dry-runIt prints the framework it found, the mark it will use, the colours it inferred,
every file it would write, and every tag it would remove from your HTML. Show
that plan to the user and get approval before re-running without --dry-run.
Useful flags: --source <file> · --name · --short-name · --description ·
--theme-color / --theme-color-dark / --bg-color · --start-url · --scope ·
--display · --site-url (needed for absolute og:image) · --og (render a
1200×630 share image) · --no-head (assets only) · --verify-only (audit, change
nothing — exits non-zero on failures, so it works in CI).
--base — required for any app not served at the domain root. Asset paths default to
the domain root, so an app at example.com/my-app/ would emit /icon-192.png and resolve
it against example.com, silently picking up whatever lives there instead. Pass
--base ./ for relative paths, which work at any mount point, or --base /my-app/ to
hard-code the subpath. --verify-only takes the same flag, so an audit resolves the icons
the way the manifest actually names them.
--lang and --dir are read from the <html> element when not passed, so an
<html lang="he" dir="rtl"> document produces an RTL manifest without being told.
How it works — env tools, never bundled libraries
Rasterising is the only step that needs anything installed. Manifest, <head>,
the padded SVG derivatives, .ico assembly and the whole verify pass are pure
Node built-ins and always run.
| Capability | Tools tried in order | If none found |
| SVG source → PNG | rsvg-convert · magick · inkscape · sharp (npx cache) | manifest + <head> still written; PNG/ICO skipped, install hint printed |
| raster source → PNG | magick · sharp (npx cache) · sips (macOS) | same |
| padding a raster source | magick only | maskable + apple icons skipped, loud warning |
| flattening (removing alpha) | magick · rsvg-convert · inkscape | icon written with its alpha channel and a warning saying so — never silently |
An SVG source is materially better: padding is baked into a generated derivative SVG, so every rasteriser yields a correct maskable icon.
What it produces
favicon.svg · favicon.ico (16/32/48) · favicon-96x96.png ·
apple-touch-icon.png (180, flattened onto a solid colour) ·
icon-192/512.png (purpose: any, transparent) ·
icon-maskable-192/512.png (separate files, mark inset to the central 80%) ·
optional og-image.png (--og, SVG source only — a raster source is warned and skipped,
not silently promised) · the manifest · the <head> block.
Manifest covers id, name, short_name, description, lang, dir,
start_url, scope, display, display_override, orientation, theme_color,
background_color, icons, categories, launch_handler, and screenshots
(auto-picked up from screenshot-*.png, with form_factor from their aspect ratio).
Head covers title, description, canonical, light/dark theme-color, icon links,
apple-touch-icon, apple-mobile-web-app-*, mobile-web-app-capable,
application-name, rel=manifest, Open Graph and Twitter card.
Two rules it enforces that hand-written manifests routinely break:
a maskable icon is never the same file as an any icon (declaring one file
"any maskable" gets its edges cropped on Android), and apple-touch-icon.png
never carries transparency (iOS paints transparent pixels black). The verify pass
fails on both, and only excuses an alpha channel when the run actually flattened the icon —
not merely because it produced it.
Agent duties
- Gate the write. The tool rewrites
<head>. It removes only tags it re-emits (plus stale icon rels) — an author'sog:locale,twitter:site,article:*or a hand-set canonical are left alone. Run--dry-run, show the removal list, get approval. Re-runs are idempotent: the block sits between sentinel comments and is replaced. Before the first edit the original HTML is copied to<file>.bakand the path is reported — tell the user, since that is their undo if the project is not under git. - Read stderr. Degradation and install hints land there; exit stays 0 when the manifest was written. Surface them and offer the install as a question — never install anything silently.
- Make the judgment calls the script won't. It infers
namefrom package.json andtheme_colorfrom the project's own CSS, and says so in anote. Confirm with the user: a realdescription(it shows in the install dialog), ashort_name≤ 12 chars, and the right brand colour. UseAskUserQuestionwhen more than one reading is plausible. - No mark? Author one first. Write a 512×512 SVG to the project, then pass
--source. It must be legible at 16px: one shape or 1–2 bold letters, no thin strokes, no fine detail, high contrast on both light and dark tab bars. - Offer screenshots. Without
screenshots[]Chrome shows the plain install prompt instead of the rich card. Capturing 1 wide + 1 narrow PNG into the static dir asscreenshot-*.pngis usually worth it — re-run to pick them up. - Frameworks that don't own an
index.html(Next, Nuxt, Astro, SvelteKit, Hugo, Jekyll) gethead-snippet.htmlwritten to the static dir instead; merge it into that framework's head or metadata export yourself. - Relay the verify block verbatim.
FAILlines mean the app will not install or will display wrong — fix them before calling the task done.
See references/manifest-spec.md for field-by-field detail, the platform size
matrix, and the traps behind each enforced rule.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

