Skip to main content
Watch: Claude Code Just Killed After Effects

LLM Engineering

Single-File App Generation

Use when prompting an LLM to emit a complete, self-contained HTML app - all HTML, CSS, and JS in one file - that you will drop into a sandboxed iframe and run: an artifact, a preview pane, a generated micro-app, a code playground. Covers the output contract (one file, pinned CDN versions, module scripts, no build step), the iframe sandbox and CSP that make running untrusted output safe, and size caps. Also use when a generated file looks plausible and renders as a blank frame. If model output will execute in a browser, use this skill.

llmhtmliframesandboxartifacts

4 files

Description

Use when prompting an LLM to emit a complete, self-contained HTML app - all HTML, CSS, and JS in one file - that you will drop into a sandboxed iframe and run: an artifact, a preview pane, a generated micro-app, a code playground. Covers the output contract (one file, pinned CDN versions, module scripts, no build step), the iframe sandbox and CSP that make running untrusted output safe, and size caps. Also use when a generated file looks plausible and renders as a blank frame. If model output will execute in a browser, use this skill.

Install
SKILL.md

name: single-file-app-generation description: Use when prompting an LLM to emit a complete, self-contained HTML app (all HTML, CSS, and JS in one file) that you will drop into a sandboxed iframe and run - an artifact, a preview pane, a generated micro-app, a code playground. Teaches the output contract (one file, pinned CDN versions, module scripts, no build step), the iframe sandbox and CSP that make running untrusted output safe, size caps, and the failure modes that turn a plausible-looking file into a blank frame.

Single-File App Generation

A single-file app is a complete program - markup, styles, and scripts - in one .html string you can write to an iframe and run with no build step. It is the right unit whenever a model generates something a user should see run immediately: an artifact, a live preview, a generated tool, a playground. The skill is getting the model to emit output that actually runs, and running that untrusted output without handing it your origin.

When to trigger

  • You prompt an LLM for "an app / widget / visualization" and render its output live.
  • Generated HTML renders as a blank frame, or works in a full tab but breaks in your embed.
  • You need to run model-generated code in the browser without trusting it.
  • You are building an artifacts pane, a preview iframe, or a code-playground feature.

The output contract

Tell the model exactly what to emit. Vague prompts produce multi-file projects, bare npm install instructions, or React with no runtime. Require:

  1. One file, top to bottom. A single <!DOCTYPE html> document with all CSS in a <style> and all JS in <script> tags. No external file references you do not control, no build step, no bundler, no npm install.
  2. Pinned CDN versions for any dependency. Every third-party import names an exact version - https://esm.sh/react@19.0.0, not @latest and not a bare react. Unpinned URLs are the top cause of an app that renders today and 500s next week when the CDN moves. Prefer an import map for readability. See reference/output-contract.md.
  3. ES module scripts for imports. Anything using import must be in <script type="module">; browsers reject bare import in a classic script. Declare bare specifiers in an <script type="importmap"> before the module. See reference/output-contract.md.
  4. Self-contained state and data. No network calls to APIs the frame cannot reach; inline sample data or read from a documented postMessage handshake.
  5. A visible failure path. Render an error into the DOM rather than only console.error, so a broken app is diagnosable from the frame, not just the console.

Running it safely

Generated code is untrusted. Render it in a sandboxed iframe that CANNOT reach your origin:

  • Use sandbox="allow-scripts" and DO NOT add allow-same-origin. The two together let the framed script remove its own sandbox attribute and escape - no safer than no sandbox at all. Without allow-same-origin the frame is an opaque origin: no cookies, no localStorage, no reading the parent.
  • Load the document via srcdoc (or a blob:/data URL), never by writing it to a same-origin route.
  • Add a Content-Security-Policy (a <meta http-equiv> inside the document, or the CSP sandbox directive) as defense in depth on top of the attribute.
  • Cross-frame communication is postMessage only, and you validate every message.

See reference/sandbox-and-safety.md for the exact iframe wiring and CSP.

Core rules

  • Cap the output size. Set a token/byte ceiling in the prompt and reject or truncate oversize output before it hits the frame. See reference/failure-modes.md.
  • Pin every dependency to an exact version. This is the single highest-value rule.
  • allow-scripts yes, allow-same-origin no. Non-negotiable for untrusted output.
  • Give the model a strict skeleton to fill, not a blank "write an app" prompt.

Reference files

  • reference/output-contract.md - the exact document skeleton, import maps vs script tags, pinning, the prompt template.
  • reference/sandbox-and-safety.md - the iframe wiring, sandbox tokens, CSP, and the postMessage handshake.
  • reference/failure-modes.md - blank-frame causes, size caps, and a triage checklist.
AI Development Stack

Get Smarter About AI Dev

New tutorials, open-source projects, and deep dives on coding agents - delivered weekly.

One email per weekReal code, not theoryFree forever