This page describes the internal pipeline that runs every time you submit a prompt in Dispel — from the moment you press Enter to the moment the styled page updates in front of you. Understanding this pipeline helps you write more effective prompts, troubleshoot unexpected output, and know exactly what data leaves your browser.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/thePrnvBot/dispel-web-stylist/llms.txt
Use this file to discover all available pages before exploring further.
The Request Pipeline
Side Panel Reads Tab Context
Before any prompt is sent, the side panel queries the currently active tab to build a
IPageContext object. This consists of two parts:- Meta — the tab’s full URL and page title, sourced from the browser’s tab API.
- Viewport — the current inner width, height, and scroll position (
scrollX,scrollY), retrieved by messaging the content script running in the tab via aGET_PAGE_METAmessage.
Content Script Extracts Visible HTML
When you submit a prompt, Dispel’s content script runs
extractViewportHTML() on the live page. This function walks document.body, collects only the elements that are currently visible in the viewport, and returns a sanitized HTML string. The extraction:- Strips entire tag families —
<script>,<style>,<noscript>,<meta>,<link>,<iframe>,<canvas>,<svg>,<head>,<base>,<template>,<path>,<mask>, and<defs>are removed entirely. - Removes hidden elements — elements with
display: none,visibility: hidden,opacity: 0,hidden, oraria-hidden="true"are pruned from the clone before serialization. - Strips most attributes — only the following 13 attributes are kept on any element:
id,class,style,href,role,data-testid,data-qa,type,name,placeholder,src,alt, andtitle. All others are removed. - Collapses whitespace — text nodes have leading/trailing whitespace trimmed and internal runs collapsed to a single space.
Prompt, HTML, and Context Sent to AI Provider
The background service worker assembles the full request and calls
streamChat(). The AI provider receives:- A static system prompt (
STATIC_GUIDELINES) covering selector strategy, scoping rules, modern CSS practices, and the shadow DOM constraint — this is sent verbatim on every request. - A dynamic system prompt built from the
IPageContext(URL without query string, page title, viewport dimensions and scroll position), any elements picked with the element picker, and the accumulated CSS from previous turns in this draft session. - The user’s message as the first and only
userturn. - The set of agent tools the model may call (see the next section).
Provider Streams CSS; Dispel Applies It Live
streamChat() uses the Vercel AI SDK’s streamText() to open a streaming connection to the provider. As tool-result chunks arrive, toStreamChunk() maps them to typed StreamChatChunk objects:- A chunk from the
generateCsstool becomes{ type: "css", css: "..." }. - A chunk from the
reportErrortool becomes{ type: "error", code: "...", message: "..." }.
streamCSS() function accumulates CSS chunks into a growing string. After each new chunk, if the accumulated CSS has changed, it calls applyCssToTab(), which sends an APPLY_CSS message to the content script in the target tab. The content script inserts or replaces a <style> element in the page’s <head>, so styles appear — and update — in real time as the model is still writing.Draft Turn Appended to Storage
Once the stream completes (or errors), the final CSS string is returned to the service that initiated the request. The caller appends the completed turn — including the prompt text and the generated CSS — to the active draft in local extension storage. This draft accumulates across turns for the current session until you either save it (moving it to the permanent per-site prompt store) or discard it.
The AI Agent
Dispel does not send a bare chat request to the provider. It uses a tool-calling agent loop powered bystreamText() from the Vercel AI SDK, with up to four steps per request. The model is given three tools and must use one of the terminal tools to produce output — it may never respond with plain text.
generateCss — the primary output tool
generateCss — the primary output tool
Description (from source): “Generate CSS styles to the page. Return only valid CSS rules with no markdown, explanations, or comments.”The model calls this tool with a single
css string argument containing raw CSS rules targeting specific selectors on the page. The tool’s execute function simply returns the CSS string as-is, which becomes the tool-result chunk that streamChat() maps to a { type: "css" } chunk and streams to the page.reportError — the terminal error tool
reportError — the terminal error tool
Description (from source): “Report why the CSS request cannot be fulfilled with a specific error code and message.”When the model determines that the request cannot be fulfilled — for example, when the target element is inside a Shadow DOM, or the prompt is ambiguous — it calls
reportError with a typed code from the LLM_ERROR_CODES enum and a human-readable message. This becomes an { type: "error" } chunk that the UI surfaces to the user.getPageHTML — the DOM inspection tool
getPageHTML — the DOM inspection tool
Description (from source): “Fetch cleaned HTML of the current viewport. Call with no selector to see all visible top-level elements. Call with a selector to inspect a specific element. Returns the HTML string, or ‘Element not found in current viewport’ if the selector does not match a visible element.”This tool lets the model request a fresh snapshot of the page’s visible HTML mid-run when it needs more DOM context to generate accurate selectors. It accepts an optional CSS
selector to scope extraction to a single element. Importantly, getPageHTML may only be called once per request — the prepareStep hook in streamText() removes it from the available tool list after the first time it has been used in any step, forcing the model to proceed to generateCss or reportError with the information it has gathered.The agent loop is bounded by
stopWhen conditions passed to streamText(): the stream terminates immediately after the model calls either generateCss or reportError, or after four steps have elapsed — whichever comes first. This prevents unbounded tool-call loops and keeps latency predictable.CSS Scoping Guidelines
Every request includesSTATIC_GUIDELINES, a fixed system-prompt section that instructs the model on how to write safe, precise, and maintainable CSS. The key rules are:
Selector strategy — prefer stable, minimal selectors in this order:
idselectors (#id)data-testid,data-test,data-qaattributes- Class selectors (
.class) - Structural selectors (
tag,:nth-child, descendant combinators)
- Scope every rule to the smallest relevant element or container.
- Never affect unrelated parts of the page.
- Never modify global layout unless the prompt explicitly requests it.
- Forbidden patterns: universal selectors (
*) except when strictly required;all: unsetorall: initial; stylinghtmlorbodywithout an explicit request; excessive use of!important;position: fixedorposition: absoluteon major layout elements without justification.
- Use
flexbox,grid,gap,clamp(), and other modern layout and sizing primitives. - Prefer responsive units (
%,rem,vw,vh) over fixedpxwhere appropriate. - Use shorthand properties where they improve readability.
- Use CSS variables only if they genuinely improve clarity and reuse.
- Do not include remote fonts,
@importURLs, CDN-hosted assets, or external images unless the prompt explicitly asks for them. - Prefer pure CSS solutions and system fonts.
Dispel’s CSS is injected into the main document’s
<head>. It cannot reach elements that live inside a Shadow DOM — the browser’s style encapsulation boundary prevents injected stylesheets from crossing into shadow roots. If you target an element inside a Shadow DOM, the model is instructed to call reportError rather than generate CSS that would silently have no effect.Data Flow: Local vs. Provider
Understanding what stays on your device and what is transmitted helps you use Dispel with confidence. Stays entirely local (browser extension storage):- Your API keys for all configured providers.
- All saved prompts and their generated CSS.
- Active draft turns for the current session.
- Extension settings (theme preference, selected model, etc.).
- The static
STATIC_GUIDELINESsystem prompt (fixed text, no personal data). - The dynamic system prompt section containing the stripped page URL (no query string), page title, viewport dimensions, any element picker HTML, and the accumulated CSS from this draft session.
- Your prompt message text.
- Tool call results (cleaned viewport HTML returned by
getPageHTML, if the model invokes it).