AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Web Visual Assets

skill-kevintsai1202-teaching-site-skills-web-visual-assets · by kevintsai1202

Use this skill when a content-complete website has missing/placeholder images and needs visual assets — scenario illustrations, tool screenshots, instructor cards, conceptual diagrams, classroom location maps, QR codes. Triggers on phrases like "插圖", "工具截圖", "QR", "講師卡", "地圖", "示意圖", "Playwright 爬蟲", "AI 生圖", "visual assets", "screenshots", "illustrations", "QR codes", "instructor cards". This sk…

No reviews yet
0 installs
23 views
0.0% view→install

Install

$ agentstack add skill-kevintsai1202-teaching-site-skills-web-visual-assets

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-kevintsai1202-teaching-site-skills-web-visual-assets)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Web Visual Assets? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Web Visual Assets

> Schema authority: the Illustration primitive shape ({name, kind, alt, spec} and {kind: 'waived', reason}) and the per-unit illustrations[] Coverage Floor are defined in [_shared/domain-primitives.md](../_shared/domain-primitives.md) §11.

This skill produces the visual layer of a teaching site. Four asset sources cover virtually every need, each with different tradeoffs.

Asset Source Decision Tree

What do you need?
├── Screenshot of a real product/website     → Source 1: Playwright scraping
├── A conceptual scene (workflow, metaphor)  → Source 2: AI image generation
├── A simple diagram (boxes, arrows, labels) → Source 3: Hand-drawn SVG
└── A scannable code / functional artifact   → Source 4: Code generator (QRCode, etc.)

Source 1: Playwright Scraping

Use for screenshots of tools, websites, profile cards. The example workshop scrapes 6 AI tool homepages and a YouTube instructor channel.

Standard headless flow

// scripts/scrape-tools.mjs
import { chromium } from 'playwright';

const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto(url, { waitUntil: 'networkidle' });
await page.screenshot({ path: `data/tools/${id}.png`, fullPage: false });
await browser.close();

When anti-bot blocks you (CDP mode)

Some sites (Cloudflare, modern OpenAI properties) detect headless Chromium and block. Workaround: connect to a real Chrome via CDP:

# scripts/start-cdp-chrome.ps1
Start-Process chrome.exe -ArgumentList '--remote-debugging-port=9222', '--user-data-dir=C:\tmp\cdp-profile'
const browser = await chromium.connectOverCDP('http://localhost:9222');
const page = (await browser.contexts()[0].pages())[0];
// ... drive an existing real-browser session

Run with --cdp --pause flags so the human can complete any CAPTCHA, then press Enter to continue.

Subset-merge pattern (don't overwrite siblings)

When re-scraping one item out of many, merge with existing data instead of overwriting:

async function writeMerged(jsonPath, updates) {
  const existing = JSON.parse(await fs.readFile(jsonPath, 'utf8').catch(() => '{}'));
  await fs.writeFile(jsonPath, JSON.stringify({ ...existing, ...updates }, null, 2));
}

CLI: node scrape-tools.mjs --ids codex,notebooklm only touches those two.

YouTube channel quirks

  • The channel page is a SPA. URL query strings like ?sort=p&view=0 are stripped. Sort client-side after fetching the latest N videos.
  • Virtual scrolling strips src from out-of-view `. Derive thumbnail URLs from videoId: https://img.youtube.com/vi/{videoId}/hqdefault.jpg. Don't rely on DOM src`.

Source 2: AI Image Generation

Use for scenario illustrations, day heroes, conceptual scenes. The example workshop uses Gemini's image generation; any text-to-image API works.

Prompt design rules

  1. Specify a consistent visual style across the whole course (e.g. "flat illustration, soft pastel palette, no text, no people"). Inconsistent illustrations look amateurish.
  2. Avoid faces and brand logos — AI image generators struggle with both and produce uncanny results.
  3. Store prompts alongside the images:
assets/illustrations/
├── day1-token-prediction.png
├── day1-token-prediction.prompt.md   ← regenerate-ready prompt
└── ...

This lets you regenerate at higher quality later or tweak style.

PNG + SVG fallback render

AI generation occasionally fails (rate limits, content filters, model issues). Pair every AI PNG with a hand-drawn SVG fallback at the same path stem:

function renderIllustration(name) {
  const img = el('img', { src: `assets/illustrations/${name}.png`, alt: '' });
  img.onerror = () => { img.src = `assets/illustrations/${name}.svg`; img.onerror = null; };
  return img;
}

The browser tries PNG; on 404 swaps to SVG. The fallback ships even if you never use it — defensive against link rot.

Source 3: Hand-drawn SVG

Use for diagrams that benefit from precise control: arrows between named boxes, step-by-step flows, labelled UI mockups, the classroom map.

Hand-coded SVG (or exported from Figma/Excalidraw) is preferable to AI for:

  • Text labels (AI can't reliably render Chinese text inside images)
  • Arrow + box flows (AI gets layout wrong)
  • Anything that needs to update when course details change

Style hint: wrap in a translucent container + drop-shadow filter to match the site's overall aesthetic, even if the SVG itself is line-art.

Source 4: Generated Codes (QR)

import QRCode from 'qrcode';
await QRCode.toFile('assets/qr/workshop-url.png', 'https://your-workshop.example/', {
  width: 512,
  margin: 1,
  color: { dark: '#000000', light: '#FFFFFF' }
});

For dark-themed sites, generate a dark-on-white code, not white-on-dark — most QR scanners require dark foreground on light background.

Asset Folder Convention

assets/
├── tools/             ← Source 1: scraped tool/product screenshots
├── illustrations/     ← Source 2 (PNG) + Source 3 (SVG fallback)
├── scenarios/         ← Source 2: per-unit scene illustrations
├── cases/             ← Source 2: shared case visuals
├── characters/        ← Source 2: persona portraits
├── qr/                ← Source 4: QR codes
└── maps/              ← Source 1 (screenshot) or Source 3 (SVG)

Wiring Assets into the SPA

In course-data.js, every unit carries an illustrations[] array (1–3 entries) populated from the 圖片需求 blocks written in Stage 2:

{
  id: 'u-3',
  title: '...',
  illustrations: [
    { name: 'day1-u3-hero.png',    kind: 'hero',       alt: '...', spec: '...' },
    { name: 'day1-u3-flow.svg',    kind: 'diagram',    alt: '...', spec: '...' },
    { name: 'day1-u3-example.png', kind: 'screenshot', alt: '...', spec: '...' }  // optional 3rd
  ],
  // ...
}

renderUnit iterates unit.illustrations and calls renderIllustration(entry), which handles PNG-first / SVG-fallback per entry. Render hero first (above the fold), then diagram, then screenshot — in that order.

Legacy single-illustration field: older course-data.js files use illustration: 'foo.png' (single string). Treat it as illustrations: [{ name: 'foo.png', kind: 'hero' }] and migrate to the array form when convenient. Don't rely on the legacy shape for new sites.

Coverage Floor (Hard Rule — 1–3 illustrations per unit)

A teaching site that ships with only a cover image looks like an unfinished draft — Stage 5 must hit a minimum coverage before declaring the site feature-complete:

  • [ ] Every unit in course-data.js has illustrations.length >= 1 (and `` requests automatically.

Run both before each deployment. The audit catches references to files that don't exist; the verify catches assets that exist but are mis-pathed in the rendered HTML. They fail in different ways and need different scripts.

Anti-Patterns

  • Generating images one-by-one without style consistency — write the style spec once, paste it as prefix for every prompt.
  • AI-generated text in images — almost always broken; use SVG for any image that needs accurate text.
  • No SVG fallback for AI PNGs — when the PNG link breaks (file deletion, rename mistake), the site shows broken-image icons; SVG fallback degrades gracefully.
  • Storing screenshots without a re-scrape script — six months later someone wants fresh screenshots and there's no record of how the originals were taken.

Hand-off

Tell the user: "visual assets in place. Run node scripts/verify-assets.mjs to confirm nothing's missing. The site is now feature-complete. Next stage (course-ebook-publishing) can turn the same content into a PDF/DOCX deliverable — invoke that only when the web version is stable."

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.