Dispel persists all user data toDocumentation 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.
chrome.storage.local using six typed storage items. Each item is validated with a Zod schema on both read and write, with version-1 migration support provided by WXT’s storage.defineItem. The withSchemaValidation wrapper ensures that corrupt or outdated data never surfaces as a runtime type error — invalid values are silently replaced by a defined fallback rather than crashing the UI.
Storage data is encrypted by the browser and scoped to the extension origin. It is not accessible by websites, other extensions, or any script running outside the extension’s own pages.
Storage Keys Overview
| Storage Key | TypeScript Type | Description |
|---|---|---|
local:models | IModelConfig[] | Configured AI model profiles |
local:lastUsedModel | string | ID of the most recently selected model |
local:promptHistory | IPromptEntry[] | Saved prompt + CSS entries, one per styling action |
local:activeDrafts | Record<string, IActiveDraft> | In-progress draft sessions keyed by hostname |
local:apiKeys | ApiKeyConfig | API keys per provider |
local:formState | IFormState | Options page UI state and user settings |
IModelConfig
A model config represents a single configured AI endpoint. The user may add multiple models — for example, a fast cheap model and a high-quality model — and switch between them from the side panel.A stable UUID that uniquely identifies this model configuration record. Used as the value for
local:lastUsedModel.One of
"openai", "openrouter", "local", "anthropic", or "google". Determines which AI SDK provider factory is used when calling streamChat.The model identifier string passed to the provider SDK — for example
"gpt-4o", "claude-opus-4-5", or "google/gemini-2.5-pro".The base URL for the provider API. Pre-populated from
PROVIDER_PRESETS but can be overridden for self-hosted or proxied endpoints.A human-readable display name for this model, shown in the model selector UI.
A URL-safe slug derived from the display name, used for sorting and identification in the UI.
PROVIDER_PRESETS:
IPromptEntry
Every prompt the user submits — along with the CSS it produced — is saved as aIPromptEntry. The prompt history is stored as a flat array sorted by timestamp and filtered by url in the UI to show only entries relevant to the current site.
A UUID generated at the time of saving. Used as the stable key when the user re-applies or deletes a history entry.
The exact text the user typed in the chat input.
The full compiled CSS string that was produced for this prompt. Saved after the stream completes.
The full URL of the page at the time the prompt was submitted, used to scope history display to the current site.
Whether this entry’s CSS is currently injected into the page. The content script checks this flag on
REFRESH_STYLES to determine which entries to re-inject after navigation.Unix epoch milliseconds (
Date.now()) recorded when the entry is saved. Used for chronological ordering.IDraftTurn and IActiveDraft
Draft sessions allow multi-turn refinement within a single page visit. Each turn records the incremental CSS patch produced by one prompt. The session persists across page reloads so the user can continue refining without losing context.local:activeDrafts is a Record<string, IActiveDraft> keyed by hostname (e.g. "github.com"). This means a single draft session spans all pages under the same hostname.
An ordered array of turns in this draft session. Each turn holds the prompt text, the CSS patch it produced, a UUID, and a timestamp. The compiled CSS shown in the side panel is the concatenation of all turn patches.
The hostname of the page where the draft was started, used as the record key in
local:activeDrafts.The full URL at the time the draft was created. Recorded for display purposes.
Unix epoch milliseconds when the first turn was added.
Unix epoch milliseconds of the most recent mutation. Used to detect stale drafts.
ApiKeyConfig
API keys are stored as a flat object keyed by provider name. All fields are optional because the user configures only the providers they intend to use. Thelocal provider (Ollama) accepts any non-empty string as a key or can be used without one.
ISettingsFormState and IFormState
IFormState is the full serialised state of the options page, combining per-section UI state with the user’s persistent settings.
Controls the colour scheme of the side panel and options page.
"system" follows the OS/browser preference via prefers-color-scheme.When
true, the side panel displays the character count of the viewport HTML sent to the AI with each request. Useful for diagnosing context-limit errors.The UUID of the model currently being edited in the model form, or
null when no edit is in progress. Persisting this prevents the form from resetting on accidental panel close.withSchemaValidation wrapper:
modifyStorage Helper
All write operations go throughmodifyStorage, which serialises concurrent writes to the same key using a promise chain stored in a Map.
withStorageLock maintains a storageLocks map from key string to the last in-flight promise. Each new write is chained onto the previous one with .then(fn, fn), so writes always execute in submission order even if the caller does not await them. Once a write settles and is still the tail of the chain, its entry is deleted from the map to prevent unbounded memory growth.
modifyStorage wraps the read-modify-write cycle and returns Ok(next) on success or Err(AppError) with code STORAGE_WRITE_FAILED on failure, so callers get a Result they can inspect without try/catch.
Schema Validation Pattern
Every storage item is wrapped inwithSchemaValidation to provide a validated read path. On getValue, the raw value from chrome.storage.local is run through schema.safeParse. If parsing succeeds, the typed data is returned. If it fails — because the stored value pre-dates the current schema, was written by an older extension version, or is otherwise malformed — the configured fallback is returned silently.
watch callback is also validated: if a storage change event carries an invalid payload (for example due to an out-of-order write from another extension context), the watcher receives the fallback rather than a partial or corrupted object.