MCPInstall

stitch::extract-static-html

Extract self-contained static HTML from a built web application or React components by inlining CSS and images. Use this skill whenever you need to capture a specific UI state, share a static version of a page, or prepare assets for Stitch upload, even if the user just asks to 'save the HTML' or 'mock the view'.

Installs
10K
Last 24h
+60
Trending rank
#2947
Security
Fail

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/google-labs-code/stitch-skills --skill stitch::extract-static-html
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads stitch::extract-static-html automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

Security audits

Independent scans of the skill's instructions and bundled files.

Gen Agent Trust Hub FailHIGH ·The skill includes high-risk functionality allowing for the dynamic execution of arbitrary local scripts via an authentication hook. It also performs unrestricted filesystem access when bundling assets into HTML files and executes a headless browser without a sandbox.
Socket PassNo alerts
Snyk PassLOW ·Risk: LOW · No issues

SKILL.md

The instructions your agent reads when the skill is triggered.

Extract Static HTML

Extract a self-contained static HTML file from any web application.

Which Strategy to Use

You MUST ask the user to choose which strategy to use before proceeding. Present the options clearly, recommend Strategy A as the preferred default, and provide a brief pros/cons summary for each option to help them make an informed decision.

Strategy A (Puppeteer)Strategy B (Browser Subagent)
WhenApp runs locally, no auth wallNeed to interact with page first (click, fill forms)
FidelityHighest — computed styles resolvedHigh — rendered DOM
SetupZero — no mock neededZero — no mock needed
FrameworkAnyAny
OutputWrites to file — no size limitMay truncate in agent context

[!WARNING] Checkpoint — User Confirmation Required. You MUST ask the user which strategy they prefer before proceeding. Present the comparison table above, recommend Strategy A as the default, and wait for explicit approval. Do NOT make the decision yourself or proceed until the user confirms.


Strategy A: Puppeteer Snapshot (Recommended)

Launches headless Chrome, captures the fully rendered DOM, and produces a self-contained HTML file with all CSS inlined and images as base64. Works with any framework — no MockPage.jsx needed.

Prerequisites

  • App running locally (e.g., npm run dev)
  • Node.js with puppeteer available (check: node -e "require('puppeteer')")

Workflow

  1. Start the App and note the port.

    [!WARNING] Checkpoint — User Confirmation Required. After starting the local server, you MUST pause and ask the user for confirmation before running the snapshot script or launching a browser subagent. Report the URL and port to the user so they can verify the app is running and rendering correctly. Do NOT proceed to the snapshot step until the user confirms.

  2. Run the Snapshot Script:

    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173 \
      --output .stitch/home.html \
      --wait 2000
    
  3. Multiple pages — run once per route:

    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173 --output .stitch/home.html --wait 2000
    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173/pricing --output .stitch/pricing.html --wait 2000
    npx tsx <SKILL_DIR>/scripts/snapshot.ts \
      --url http://localhost:5173/dashboard --output .stitch/dashboard.html --wait 2000 --html-class dark
    
  4. Clean Up Dev Server: If a local dev server was started specifically for snapshot extraction, make sure to stop the server process or terminate the background task once extraction is completed.

Script Flags

FlagDefaultDescription
--url(required)URL to capture
--output(required)Output file path
--wait1000Extra wait (ms) after network idle. Increase for lazy-loading apps.
--viewport1280x800Viewport size as WIDTHxHEIGHT
--html-class—Class(es) for <html> element (e.g., dark)
--remove-fixedfalseRemove fixed/sticky elements (cookie banners, chat widgets)
--full-heightfalseResize viewport to full scroll height
--title—Override page title (set to the route path, e.g. /dashboard or /settings/profile)
--auth-script—Path to a JS/TS module that exports a default async (page) => void function for authentication
--inline-canvasfalseConvert <canvas> elements (ECharts, Chart.js, D3) to base64 <img> tags

What It Does Automatically

  • Captures all CSSOM rules from document.styleSheets (preserves dynamic Vite/Tailwind dev styles and CSS-in-JS)
  • Inlines all <link rel="stylesheet"> → <style> blocks
  • Converts <img> src and srcset → base64 data URIs (skips external fonts)
  • Inlines same-origin and relative icon font files (@font-face) as base64 data URIs so ligatures never render as ASCII text
  • Inlines <source srcset> URLs as base64
  • Removes failed/dead srcset entries so the browser falls back to the inlined src
  • Removes <script> tags, Vite HMR dev style blocks (createHotContext, import.meta.hot), and dev overlays
  • Resolves relative CSS url() paths before inlining

Framework Notes

FrameworkNotes
React + ViteWorks out of the box. --wait 1000.
Next.js--wait 3000 for SSR hydration. URL: http://localhost:3000. <img srcset> from /_next/image is auto-inlined as base64.
Angular (@angular/cli / v17+)Works out of the box with ng serve (default URL: http://localhost:4200). --wait 2000 for Angular Material / PrimeNG animation hydration and lazy-loaded routes.
Vue / NuxtWorks out of the box.
Svelte / SvelteKitWorks out of the box.
StorybookUse story URL: --url http://localhost:6006/?path=/story/...
SSR (Webpack)May need longer --wait.

Troubleshooting

IssueSolution
Images missingIncrease --wait
Images show as broken after server stopsVerify srcset was inlined — check log for "Inlined N images". If srcset URLs failed, they are auto-removed so src (inlined) is used.
Icons display as text / Serif unstyled fontEnsure snapshot.ts captures CSSOM from document.styleSheets (step 0) and same-origin icon fonts (@font-face) are inlined as base64 data URIs.
Next.js /_next/image not inlinedEnsure the dev server is running when snapshot runs — the script fetches optimized images from the running server.
Dark mode not applied--html-class dark
Cookie banner in output--remove-fixed
Page requires loginUse --auth-script ./auth.ts (see Auth-Gated Pages below)
Charts/graphs show as blank boxesUse --inline-canvas to serialize <canvas> to base64 <img>
Cannot find module 'puppeteer'npm install -g puppeteer

Auth-Gated Pages

For apps with login guards (Vue Router beforeEach, React ProtectedRoute, etc.), create a small auth script that runs in the Puppeteer session:

// auth-myapp.ts
import type { Page } from 'puppeteer';

export default async function authenticate(page: Page) {
  // Example 1: Fill and submit a login form
  await page.type('#username', 'admin');
  await page.type('#password', 'password123');
  await page.click('#login-button');
  await page.waitForNavigation({ waitUntil: 'networkidle2' });

  // Example 2: Inject cookies/localStorage directly
  // await page.evaluate(() => {
  //   localStorage.setItem('token', 'mock-jwt-token');
  // });

  // Example 3: Call the app's own login API via module injection (Vue/Vite)
  // await page.evaluate(() => {
  //   return new Promise((resolve) => {
  //     const script = document.createElement('script');
  //     script.type = 'module';
  //     script.textContent = `
  //       import { useUserStore } from '/src/store/modules/user.ts';
  //       import { fetchLogin } from '/src/api/auth.ts';
  //       const res = await fetchLogin({ userName: 'Admin', password: '123456' });
  //       useUserStore().setToken(res.token, res.refreshToken);
  //       window.dispatchEvent(new CustomEvent('auth-done'));
  //     `;
  //     document.head.appendChild(script);
  //     window.addEventListener('auth-done', () => resolve(true), { once: true });
  //   });
  // });
}

Then use it:

npx tsx <SKILL_DIR>/scripts/snapshot.ts \
  --url http://localhost:5173/#/dashboard \
  --output .stitch/dashboard.html \
  --auth-script ./auth-myapp.ts \
  --inline-canvas \
  --wait 5000

The script navigates to the --url first (which may redirect to login), runs your auth function, then re-navigates to the original --url with the authenticated session.


Strategy B: Browser Subagent Capture

Use when you need to interact with the page (click buttons, fill forms, navigate tabs) before capturing. The browser subagent gives you full control but output may truncate for large pages.

Workflow

  1. Start the App locally.

  2. Navigate using a browser subagent.

  3. Interact as needed (click, scroll, fill forms).

  4. Extract DOM: document.documentElement.outerHTML

    [!WARNING] Large pages may truncate. To handle this:

    • Remove <style> tags before extraction: document.querySelectorAll('style').forEach(el => el.remove())
    • Re-add styles statically (Tailwind CDN link, source CSS)
  5. Save to file.


Appendix: Static Fallback (MockPage.jsx)

[!NOTE] This method is a last resort for when the app cannot run locally (broken deps, missing backend, auth walls with no bypass). It requires manually flattening React components into a single JSX file. Prefer Strategy A whenever possible.

When to Use

  • App can't run locally at all
  • Page requires auth with no mock/bypass
  • You need a specific UI state that's impossible to reach by navigation (error screens, empty states)

Quick Reference

npx tsx <SKILL_DIR>/scripts/extract_inline_html.ts \
  --index-css src/css/App.css \
  --extra-css index.html \
  --outdir .stitch \
  --page src/MockPage.jsx:Page.html:"Page Title"

Key flags: --no-tailwind (non-Tailwind apps), --html-class dark (dark mode), --css-files (extra CSS files).

Auto-detection: Tailwind config is auto-detected. @apply directives automatically use <style type="text/tailwindcss">.

MockPage.jsx Rules

  1. Include the full layout — header, sidebar, footer (read App.js first)
  2. Flatten all conditionals — pick one state, remove all ternaries and && guards
  3. Hardcode all data — replace {variable} with concrete values, unroll .map() loops
  4. Preserve logos — use <img> with local paths (post-process will inline them)
  5. Remove floating elements — cookie banners, chat widgets, feedback buttons

Post-Processing

Inline local images:

npx tsx <SKILL_DIR>/scripts/post_process.ts \
  .stitch/Page.html --base-dir <app-directory>

FAQ

What does the stitch::extract-static-html skill do?

Extract self-contained static HTML from a built web application or React components by inlining CSS and images. Use this skill whenever you need to capture a specific UI state, share a static version of a page, or prepare assets for Stitch upload, even if the user just asks to 'save the HTML' or 'mock the view'.

How do I install stitch::extract-static-html?

Run npx skills add https://github.com/google-labs-code/stitch-skills --skill stitch::extract-static-html in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/stitch::extract-static-html/ (personal) or .claude/skills/stitch::extract-static-html/ (project).

Which AI agents can use stitch::extract-static-html?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is stitch::extract-static-html safe to install?

Security partners have reviewed it: Gen Agent Trust Hub flagged risks; Socket passed; Snyk passed. As with any skill, read the SKILL.md and bundled scripts before installing.

Who maintains stitch::extract-static-html?

It is published by google-labs-code in google-labs-code/stitch-skills. It has 10,022 recorded installs.

More from google-labs-code/stitch-skills

View all →

design-md

google-labs-code/stitch-skills

Analyze Stitch projects and synthesize a semantic design system into DESIGN.md files

OfficialFrontend & Design64.9K installs

enhance-prompt

google-labs-code/stitch-skills

Transforms vague UI ideas into polished, Stitch-optimized prompts. Enhances specificity, adds UI/UX keywords, injects design system context, and structures output for better generation results.

OfficialAI & Agents58.4K installs

stitch-loop

google-labs-code/stitch-skills

Teaches agents to iteratively build websites using Stitch with an autonomous baton-passing loop pattern

Official56.5K installs

shadcn-ui

google-labs-code/stitch-skills

Expert guidance for integrating and building applications with shadcn/ui components, including component discovery, installation, customization, and best practices.

OfficialFrontend & Design53.5K installs

react:components

google-labs-code/stitch-skills

Converts Stitch designs into modular Vite and React components using system-level networking and AST-based validation.

Frontend & Design50.4K installs

remotion

google-labs-code/stitch-skills

Generate walkthrough videos from Stitch projects using Remotion with smooth transitions, zooming, and text overlays

OfficialMedia & Creative41.4K installs

Popular frontend & design skills

View category →

setup-matt-pocock-skills

mattpocock/skills

Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.

Frontend & Design1.1M installs

frontend-design

anthropics/skills

Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.

OfficialFrontend & Design1M installs

hyperframes-animation

heygen-com/hyperframes

All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.

prototype

mattpocock/skills

Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.

Frontend & Design999.2K installs

hyperframes-core

heygen-com/hyperframes

The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.

Frontend & Design930.5K installs

vercel-react-best-practices

vercel-labs/agent-skills

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

OfficialFrontend & Design843.1K installs