Skip to main content

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.

Dispel is built with WXT (a web extension framework), React 19, Zustand for state management, and Tailwind CSS v4. WXT treats each file under src/entrypoints/ as an independent extension context — background service worker, injected content script, side panel, options page, and welcome page — and handles manifest generation, hot module replacement, and browser-specific field differences automatically. This page maps the source tree to the runtime role of each piece so you can navigate the codebase with confidence.

WXT Entrypoints

Each directory under src/entrypoints/ corresponds to one context that WXT compiles and registers in the manifest. The five entrypoints and their runtime responsibilities are:

background

Service worker. Calls setupSidePanel() on startup, wires the toolbar icon click (onBrowserActionClick) and keyboard command (toggle-sidebar / Ctrl+Shift+Y) to toggleSidePanel(), and opens the welcome page in a new tab on first install via onInstalled.

content

Injected into every http/https page. Runs tryApplyLocalStorageFallback() immediately at document_start, then calls applySavedStyles() once the DOM is ready. Tracks viewport HTML size on scroll/mutation (debounced), and handles the full inbound message protocol: APPLY_CSS, CLEAR_STYLES, REFRESH_STYLES, GET_PAGE_HTML, GET_PAGE_META, ACTIVATE_PICKER, and DEACTIVATE_PICKER.

sidepanel

Main side-panel React app. Hosts SidebarPromptInput (prompt entry + model selector), PromptStore (saved prompt history with toggle/edit/delete), CurrentTabBadge (active tab URL display), and the ModeToggle (dark/light/system theme). Syncs its Zustand store with chrome.storage via useSyncSidepanelStore.

options

Options page React app. A three-tab layout (Models, Prompts, Settings) rendered by shadcn Tabs. The Models tab hosts the provider configuration table and the add/edit model form. Settings contains global preferences.

welcome

First-install onboarding page. Opened automatically by the background service worker the first time the extension is installed. Guides new users through adding an API key and making their first prompt.
WXT handles manifest generation, HMR, and browser-specific manifest fields (such as browser_specific_settings for Firefox Gecko). You rarely need to edit the manifest directly — the canonical manifest configuration lives in wxt.config.ts.

Component Layers

React UI components are split into three directories under src/components/, each with a distinct ownership model:

src/components/custom/

Project-specific components. Divided into sidepanel/ (prompt input, prompt store, current-tab badge, debug output, draft controls) and options/ (model form, provider icon, settings fields). All new feature UI belongs here.

src/components/ui/

shadcn components. Primitive, unstyled-first components such as button, input, dialog, tabs, sonner, mode-toggle, and others. Generated by shadcn and generally not edited by hand.

src/components/ai-elements/

Vendored AI chat UI primitives. Pre-built chat-oriented building blocks (message bubbles, code blocks, streaming indicators). Biome linter rules for a11y and security are relaxed for this directory because the vendored components pre-date those checks.

src/lib/

shadcn cn() helper. The lib/utils.ts file exported by shadcn that merges Tailwind class names with clsx + tailwind-merge. Imported throughout custom and ui components.

State Management

Zustand stores live in src/stores/ and own all runtime state that spans component boundaries:
The primary store for the side panel. Holds the active draft (the CSS currently streaming into the page), the prompt list (saved prompt history), streaming status, any elements captured by the element picker, and the currently selected model. All side panel components read from and write to this store.
A sub-directory of stores that manage the controlled form state for the options page — specifically the add/edit model form fields and validation state, kept separate from the side panel store to avoid cross-context pollution.
Exports the useSyncSidepanelStore hook, which is called once at the top of the side panel App. It subscribes to chrome.storage change events and merges remote changes (for example, updates made in the options page) back into the Zustand store, keeping both contexts in sync without a shared message bus.

Services

src/services/ contains one file per user-initiated action. Each service orchestrates multiple utilities and storage calls to complete a workflow end-to-end:

submit-prompt.ts

The main prompt pipeline. Fetches page context (GET_PAGE_META + GET_PAGE_HTML), creates a draft entry in storage, calls streamCSS to request CSS from the AI provider, applies each CSS chunk to the page via APPLY_CSS, and appends the completed turn to the draft.

save-draft.ts

Promotes the current draft to the permanent prompt history. Writes the compiled CSS to storage, removes the draft record, and sends REFRESH_STYLES to the content script so the page reloads from saved state.

discard-draft.ts

Cancels an in-progress or completed draft. Removes the draft from storage and sends CLEAR_STYLES followed by REFRESH_STYLES to revert the page to its last saved style state.

resolve-warning.ts

Handles the external CSS source warning flow. When the content script detects that the page loads styles from an external stylesheet, the user can either dismiss the warning (keep streaming) or revert (discard the draft and restore the page).

Utilities

src/utils/ contains pure, side-effect-free helpers. The most important modules are:
Exports streamChat, the function that calls an AI provider and yields CSS token by token. Also contains a model factory that selects the correct Vercel AI SDK provider package (@ai-sdk/openai, @ai-sdk/anthropic, @ai-sdk/google, @openrouter/ai-sdk-provider, or @ai-sdk/openai-compatible) based on the model’s configured provider type.
Exports STATIC_GUIDELINES (the invariant rules the model must follow when generating CSS) and generateSystemPrompt, which combines the static guidelines with the page’s URL, title, viewport dimensions, and any element-picker context into the final system message sent to the model.
Defines the Vercel AI SDK tool objects passed to the model: generateCss (the primary output tool), reportError (lets the model surface a structured error instead of invalid CSS), and createGetPageHTMLTool (a factory that wraps the GET_PAGE_HTML message round-trip so the model can request a specific element’s HTML).
Wraps chrome.storage.local with Zod-validated typed items. Every key stored by the extension (prompts, drafts, models, settings) has a corresponding typed item definition here, ensuring reads and writes are type-safe at compile time.
Defines ProtocolMap, a TypeScript map of message name → { input, output } pairs covering every message exchanged between the background, content, and side panel contexts. Also exports sendRuntimeMessage and createMessageRouter helpers built on @webext-core/messaging.
Exports extractViewportHTML and measureViewportHTML. The extractor walks the DOM, removes <script>, hidden elements, and most attributes, and returns a compact HTML snapshot of the visible viewport that is safe and small enough to include in an AI prompt.

Platform Splits

Browser differences between Chrome and Firefox (primarily in how the side panel API works) are handled in src/platform/:
src/platform/
  sidepanel.chrome.ts   # Uses chrome.sidePanel API
  sidepanel.firefox.ts  # Uses a popup-based fallback
WXT resolves the @/platform/sidepanel import alias at build time via a Vite resolve.alias in wxt.config.ts: when the build target is firefox, it points to sidepanel.firefox.ts; otherwise it points to sidepanel.chrome.ts. This means the background entrypoint imports @/platform/sidepanel without any runtime branching.

Project Directory Tree

src/
  entrypoints/          # WXT entrypoints
    background/         # Service worker
    content/            # Injected content script
    options/            # Options page (React)
    sidepanel/          # Side panel (React)
    welcome/            # First-install onboarding page
  components/
    custom/             # Project-specific UI (sidepanel/*, options/*)
    ui/                 # shadcn primitives
    ai-elements/        # Vendored AI chat UI primitives
  stores/               # Zustand stores
    form-state/         # Options form state
    sidepanel-store.ts
    sidepanel-store-sync.ts
  services/             # One file per user-action workflow
  utils/                # Pure helpers, LLM, storage, messaging
  hooks/                # React hooks
  platform/             # Chrome / Firefox splits
  lib/                  # shadcn cn() helper
  assets/               # styles.css, icons

Build docs developers (and LLMs) love