Turn an agent's answer into rich, styled HTML cards: safe rendering of model-generated content (escape + sanitize), reusable card templates, responsive grids, and dark-mode theming with CSS tokens. Triggers on 'answer in HTML', 'render as a card', 'HTML answer', 'answer card template', or when agent output needs to be shown as styled HTML.
./install.sh html-answer-cardsname: "html_answer_cards" description: "Turn an agent's answer into rich, styled HTML cards: safe rendering of model-generated content (escape + sanitize), reusable card templates, responsive grids, and dark-mode theming with CSS tokens. Triggers on 'answer in HTML', 'render as a card', 'HTML answer', 'answer card template', or when agent output needs to be shown as styled HTML."
Make agent answers look good as HTML without shipping XSS. The pattern: structured answer data goes through a fixed card template, every model-generated string is escaped or sanitized before it reaches the DOM, and one token-based stylesheet handles light/dark mode and responsiveness. The result is a self-contained HTML answer a chat surface, page, or email client can drop in as-is.
assets/card.html owns the markup; the agent only fills the fields. If the answer needs rich text, the pipeline is: markdown -> sanitize -> insert. Never raw innerHTML of model text.html.escape (Python) or template auto-escaping; never mark model content safe. Client-side: run the markdown-converted HTML through DOMPurify with explicit allow-lists, configured AFTER conversion, not before (see references/sanitization.md). Links get a https?/mailto URI allow-list; kill javascript:, event handlers, and style attributes.assets/card.html. Use the semantic slots: <article class="card"> with .card-kicker, .card-title, .card-summary, .card-facts (a <dl>), .card-points (a <ul>), .card-actions (links). Do not invent new class names; new visual needs go through modifiers (.card--accent, .card--compact).assets/cards.css custom properties (--card-bg, --card-text, --card-muted, --card-line, --card-accent). Dark mode is a single override block keyed to prefers-color-scheme: dark plus an optional [data-theme] manual override. Set color-scheme: light dark so native controls follow the theme.repeat(auto-fill, minmax(min(280px, 100%), 1fr)), which adapts with no breakpoints. Cards reused in sidebars or panels can opt into container queries (container-type: inline-size) so they respond to their box, not the viewport.references/qa-checklist.md: no horizontal scroll at 320px, light and dark both readable (4.5:1 text contrast), no raw <script>/on* in the final HTML, keyboard focus visible on all links, prefers-reduced-motion respected.An agent applying this skill produces a self-contained HTML answer:
assets/card.html structure and assets/cards.css tokens, with no external CSS/JS/fonts unless the host page already provides them.javascript: URIs, event-handler attributes, or <script>/<style> elements from model content.article, headings, dl/ul where they fit)..card-grid wrapper; every card is self-contained so cards can be reordered, filtered, or rendered individually.ALLOWED_TAGS, ALLOWED_ATTR, and ALLOWED_URI_REGEXP; tighten the URI list to what the answer actually needs and re-audit it whenever the library bumps (see references for the rationale and a verified config).style attributes and <style> tags from model content are always stripped. If a card needs custom styling, add a named modifier class to the template; never honor inline styles from the model.prefers-reduced-motion, keep link text descriptive (never "click here"), and give every image alt text or alt="" when decorative.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.