← getloupe.org
Changelog
Every release, straight from the repo — current version 0.9.2, page generated 2026-09-23.
All notable changes to Loupe. Versions match the Chrome Web Store releases;
the manifest version is generated from package.json.
0.9.2 — 2026-09-23
Fixed
- Figma compare explains itself when things go stale. An expired or revoked Figma token used to silently show the pristine connect form — it now says so. Pressing Esc while "Anchor to element" was armed left the "Click an element…" hint stuck — it now resets. "Re-run diff" after the anchored element left the page did nothing — it now tells you to re-anchor. And reopening the panel mid-session no longer strands you: the frame URL comes back prefilled with a note that one Fetch re-arms anchoring.
0.9.1 — 2026-09-22
Fixed
- Measuring nested elements shows the four edge gaps (inner edge → container edge, arrows and values on each side) instead of "overlap" extents — which for a contained element were just its own size. Asking "how far is this dropdown from the right edge of its card" now gets a direct answer; partially overlapping elements keep the overlap reading.
0.9.0 — 2026-09-21
Fixed
- Xray no longer outlines Loupe's own UI, and — the bigger one — **the Page inventory no longer records Loupe's injected styles as the page's design**: with Xray active, the entire outlines group used to be Loupe's own overlay palette (Find highlights polluted it the same way). The inventory now disables Loupe's injected stylesheets for the duration of the scan — and the same guard protects the DS lint, dark-mode diff and accessibility-contrast audits, which sampled the same polluted styles.
- Layout-grid settings survive a browser restart. Colour, opacity, columns and margins lived only in session storage and silently reset; they now mirror to durable prefs like the dock position.
- The Element tab's "CSS" copy button confirms ("Copied"/"Failed") instead of giving no feedback at all.
- Tailwind Xray says so when a page has no utilities instead of entering silently with nothing painted — the mode looked dead on non-Tailwind sites.
- Find highlights follow your overlay-style colours (Settings → Overlay appearance) instead of staying hardcoded red/amber, and the match counter no longer counts elements a SPA rerender removed.
- The colour picker can no longer show stale colours: if the post-scroll recapture fails (rate limit, window blur), the old snapshot is dropped and the bubble stays hidden until a fresh capture lands — previously it confidently sampled the pre-scroll screenshot at the new position.
- Find also stops scanning the document twice per keystroke (the dock input and the store sync both triggered the same search).
0.8.9 — 2026-09-20
Fixed
- "Copy AI prompt" actually copies on the in-page panel. The panel iframe lacked the clipboard-write permission policy, so every copy button silently failed there (the native side panel was fine) — and the failure was swallowed, so the button just looked dead. The iframe now grants clipboard-write, a legacy fallback covers the rest, failures say "Copy failed", and success reads "Copied — paste into your agent". The button is also renamed from "AI fix prompt" to Copy AI prompt with a tooltip clarifying no API key is needed — it writes a prompt for YOUR agent, it doesn't call an API.
- The AI explainer now says why it isn't working. Without an API key the "Explain with Claude" feature was simply invisible on FixCards — it now shows "AI explanations need your Anthropic API key" with an Add-API-key button that opens the key form and scrolls it into view. Key-rejection errors say so plainly with the same shortcut, and the raw
pro_required sentinel now reads "AI explanations are part of Loupe Pro."
Changed
- Design-system profiles import in one pick, right from Checks. The Components, Lint and Dark-diff checks now offer "Import profile JSON" directly (importing also binds the profile to the current site), with a link to the authoring guide — no trip through Settings. Once a profile is bound, each check shows which profile is active with an Update button that takes a replacement JSON in one pick. The full manager (URL fetch, paste, multiple profiles, unbind/delete) stays in Settings.
0.8.8 — 2026-09-20
Added
- Edit text in Nudge mode. Double-click any element to rewrite its text in place (plain-text only — pasted formatting is stripped); Enter or clicking away commits, Esc cancels. Edited elements get a ✎ badge (moved + edited shows both), text changes ride the same ⌘Z undo/redo stack as moves, appear in the Checks list, and the Copy-AI-prompt handoff asks for the copy change alongside the layout changes. Backspace/Clear-all revert text too.
0.8.7 — 2026-09-19
Added
- Customizable overlay appearance. Settings → Overlay appearance opens an editor for how Loupe annotates the page: label size and weight, plus a colour per named role — Selection, Hover target, Measure anchor, Measurements, Crosshair, Guides, Nudge, Nudge ghost — each showing its default and a one-tap reset. Reset-all, Export (JSON to clipboard) and Import (paste or file, validated) included; every edit applies live on the page and persists across browser restarts. Semantic colours stay fixed on purpose: Figma severity bands and Tailwind Xray categories must read the same in every exported report.
- Ruler bars adapt to the page. On dark sites the bars flip to a light tint with dark ticks (the dark bars used to disappear); light sites keep the original look. Automatic, based on the page's own background.
Changed
- Ruler bars push the page out of their way. Entering Rulers insets the page by the bar thickness (margin on the root), DevTools-style, so the bars overlap nothing — and the tick scale now aligns exactly with page coordinates (it was previously drawn 18px offset from the content). Hiding the bars (
R again) or exiting restores the page precisely; position:fixed page elements can't be shifted by margins, so the bars stay translucent as the fallback for sticky headers. - Measurement lines got the classic dimension-line look. Distance lines now end in double-headed arrows, and the value sits in a light pill with a cyan border and cyan text — legible on any page background — instead of a solid colour block. Sans-serif with tabular numerals.
0.8.6 — 2026-09-18
Added
- More devices. The responsive device list grows from 9 to 21 presets — recent and legacy iPhones (17 Pro, 15 Pro Max, 11/XR, 13 mini), common Androids (Galaxy A51/71, S8+, Z Fold folded), more tablets (iPad Air, iPad Pro 12.9", Surface Pro 7) and larger desktops (15" laptop, QHD) — grouped into Phones / Tablets / Laptops & desktops in the dropdown. Viewport values match Chrome DevTools' device list.
0.8.5 — 2026-09-18 (uploaded, superseded by 0.8.6 before publish)
Added
- Centered responsive preview.
M now opens the page in a centered, device-sized frame on a dark stage — the DevTools look — instead of emulating in place at the tab's top-left corner. No debugger attachment, so Chrome's "started debugging this browser" banner is gone from the default path. The popover's new Engine switch drops to the old in-place emulation ("Device") when you need real mobile UA, touch and DPR; sites that refuse to load in a frame get a notice with a one-click switch. The Fit-window button now only appears for the Device engine, where it's still the only cure for the corner anchor. - Inspection tools work inside the centered preview. Rulers, Measure, Inspect, Nudge, grid and the rest now operate on the mobile layout in the stage frame itself — the dock's buttons drive overlays injected into the preview (new
scripting permission, scoped to Loupe's own frame). While the stage is up, top-frame overlays yield to it and reclaim the page when it closes. - The Responsive card floats beside the preview and is draggable. In the centered engine it places itself next to the device frame instead of over it, and its header is a drag handle — park it anywhere; the spot is kept while you stay on the page.
0.8.4 — 2026-09-18
Changed
- Inspect, Measure and Rulers are separate modes again. The 0.8.3 unification put every annotation on screen at once — selector label, size badge, X/Y/W/H readout and distance chips all crowding the same corner on dense pages. Each mode now shows only its own annotations: Inspect (
I) hover-highlights and selects, Measure (D) does anchor-and-hover distances, Rulers (R) does bars, crosshair and the X/Y/W/H readout. Measure and Rulers get their dock buttons back. R inside Rulers mode hides the bars — crosshair, guides and readout stay, so nothing covers the page's top-left corner; a third press exits.
Fixed
- Unpacked builds are now labeled "(dev)" in chrome://extensions. The store install and a local dist/ load otherwise show the same name, icon and (between releases) version, and running the store copy while iterating locally produced a day of ghost bug reports.
pnpm package builds the clean-named release; plain pnpm build marks itself dev. - Annotations no longer stack on top of each other. Every chip goes through one shared placer: it takes the first free anchor, dodges chips already on screen and the ruler gutter, and walks downward when a tight cluster leaves no free anchor. Long selector labels — Tailwind arbitrary variants like
[&:has([role=checkbox])]:pr-0 — are truncated instead of banner-width, and the X/Y/W/H readout sits below the element. - Ruler bars no longer hide the page underneath them. They now fade from a readable tint at the outer edge to nearly clear at the inner edge, with haloed ticks and numbers, instead of painting an opaque strip over content.
Changed
- Responsive mode reworked. The device controls move from a strip injected into the previewed page — which could never be wider than the phone it was previewing, and covered the site's own header — into a dock popover with a device picker, size fields, rotate, and a zoom control. The preview now scales to fit the window by default (Fit / 50% / 100% / 150%), so a 390px phone fills the space instead of sitting in a black corner; the page still computes at its real CSS width, so breakpoints stay exact. The dock auto-compacts when the previewed viewport is too narrow for it, keeping the responsive control reachable. The area beside the preview is now a neutral stage colour that follows your theme, and a Fit window to device button resizes the browser window around the preview to close the gap entirely (exiting restores your previous window bounds). Chrome always paints the emulated viewport from the top-left of the tab — an extension cannot centre it the way DevTools does — so the backdrop and the optional window fit are what make the empty space read as deliberate.
0.8.3 — 2026-09-17
Changed
- Inspect, Measure and Page Rulers are now one mode. Inspect gained the other two as behaviors: with an element selected, hovering any other element draws live pixel distances between them (the old Measure flow, minus the mode switch), and the rulers layer — bars + crosshair over empty space, edge-snap guides over elements — is on by default (
R hides it). Distance lines and labels draw in their own cyan so a measurement never blends into the selection it starts from. D and R still work (D jumps into Inspect; R toggles the layer from anywhere), ⌘K keeps "Measure distances" and "Toggle page rulers" searchable by name, and the dock slims from three buttons to one.
Added
- Nudge rides on Inspect — entering Nudge keeps the whole inspection instrument live: hover highlight, pinned selection, rulers, and live distances. Select a reference element, drag another, and the gap between them updates in real time while you drag.
- Nudge mode (
N, free) — move elements on the live page by dragging or with arrow keys (Shift = 10px) and compare against a ghost of the original position with a Δ badge. Full undo/redo (⌘Z/⇧⌘Z, arrow bursts count as one step), Backspace resets the selected element, and the on-page pill carries undo/redo/Clear-all. Leaving the mode keeps the moves so the page can be browsed as-adjusted. Adjustments are inline translate only — non-destructive and gone on reload. - Checks → Nudges — every moved element listed with its Δ and selector, per-row locate/reset, Copy AI prompt (a change list asking for real layout fixes, not translate hacks), and Screenshots — two PNGs: the adjusted page clean, and the comparison view with ghosts and Δ badges — ready to hand to a developer or coding agent.
0.8.2 — 2026-09-16
Added
- System theme — Settings → Theme gains a third option that follows the OS colour scheme live (panel and dock both), alongside Dark and Light. The ⌘K theme toggle still flips explicitly between dark and light.
0.8.1 — 2026-09-16
Fixed
- "Move to Chrome's side panel" works on first click — the header button saved the preference but never opened the side panel or closed the in-page one, so nothing visibly happened until the panel was closed and reopened.
0.8.0 — 2026-09-13
Changed
- Complete visual redesign — one token system (warm plum dark / warm paper light, a single violet accent, semantic colour families, a real elevation ramp) drives the panel, dock, and overlays; every hover/press springs; the panel slides in and out with the dock moving in lockstep; light mode no longer flashes dark on open. Reduced-motion is respected everywhere.
- Three tabs instead of five —
Element · Page · Checks. The new Checks tab is one index for every audit: Tailwind Xray, DS Components, DS Lint, Dark-mode diff, Accessibility, and Figma compare (with breakpoints and QA export inside), free and Pro side by side. No feature was renamed or removed — only the containers changed. - Page tab flattened — the landing screen is a collection index with live counts (Typography, Text colors, Backgrounds, Shadows, Gradients & outlines, Spacing, Borders & radii, Assets, Tech & meta); one click to any inventory, back restores your exact scroll position. Picked colors + the WCAG contrast checker are pinned at the top.
- One-row header — the marketing title is gone; in its place a live context line (the page's hostname, or the selected element's clickable ancestry breadcrumb, which replaces the old Document section). The mark / PRO badge opens a new Settings sheet holding theme, text size, the design-system profile import/binding, Tailwind brand prefixes, rating, and licence.
- Drag-resizable panel — grab the in-page panel's left edge (320–640px); the width persists and wide layouts get two-column indexes.
- The Figma viewport-mismatch banner now measures the page's real viewport (it used to read the panel's own ~380px window and was permanently on).
Added
- ⌘K command palette (panel) — every mode and panel action, searchable, with keyboard navigation. The palette input sits inside the shared typing guard, so searching "grid" filters commands instead of toggling the grid.
- Trial countdown badge — the dock and panel now show
TRIAL · 5 while a Pro trial is running (amber for the last two days, TRIAL ENDED after), clickable straight through to upgrade. Deliberately styled lesser than the gradient PRO pill so buying visibly changes something and the badge changing on day 8 reads as the trial ending, not a bug. Paid and org-licensed users keep the gradient PRO.
0.7.5 — 2026-09-12
Added
- Page inventories (Page tab) — three new sections: Fonts (every family in use with size/weight variants), Layout (unique padding, border, and border-radius values with visual swatches and use counts), and Assets (images, inline SVGs, favicons, CSS backgrounds — with open, download, and multi-select download). Every row copies its CSS; Locate toggles a highlight on the page, moves it between rows, and steps through a row's matches on re-activation — the whole card is the click target (active row keeps a blue ring), with the copy and locate chips on top.
- Global refresh in the panel header — re-pulls page info and re-runs every scan that currently has results (Tailwind, DS components, inventories, Figma diff). Replaces the decorative pin button.
- Rate-us stars — an always-available row under the panel header; one click opens the Chrome Web Store review page.
- PRO badge — paid and org-licensed users get an animated iridescent PRO pill on the dock (rotates on vertical docks) and in place of the panel header's logo square. Display-only; the Pro boundary stays in the background handlers. Trial users don't get it — it marks a purchase. The panel's Pro feature labels (Accessibility, Lint audit, Dark-mode diff) wear a small version of the same pill.
- Colors inventory (Page tab, Colors view) — page-wide computed colors CSS Pully-style, one segment at a time like the Layout view: text colors (hex, text-bearing elements only), background colors, box shadows, gradients, and outlines, each as swatch cards with use counts, copy, and locate. The eyedropper palette + WCAG contrast checker moved to a "Picked" segment alongside.
Added (interface)
- Light mode — a sun/moon toggle in the panel header switches the whole panel and the on-page dock between dark (default) and light themes; the choice persists. Under the hood every panel surface now resolves through theme tokens instead of hardcoded greys.
- Dramatic hide/show — hiding the dock slides it off toward the screen edge (with a little anticipation dip) and leaves a glowing brand-gradient orb; clicking the orb slides the dock back in with an overshoot. Honors reduced-motion preferences.
Changed
- A minimal dock — seven buttons dropped from the full dock, nothing lost: select parent/child (
↑/↓), pause (Space), and shutdown (Q) are keyboard-only (listed in the ? popover); element screenshot and copy-CSS live in the panel's Element tab; Figma diff lives in the panel's Design tab. DS Components and DS Lint buttons now appear only when a design-system profile is bound to the page's origin. - The global open-panel command defaults to
Alt+Shift+P (was Alt+Shift+L), matching the in-page P shortcut. Chrome only applies suggested keys on fresh installs — existing installs keep whatever they have bound; check chrome://extensions/shortcuts to rebind. - Pricing: Loupe Pro is now a one-time $20 purchase (was $8/month / $59/year / $129 lifetime) — buy once, use forever; the 7-day free trial stays. Team org licences are self-serve at getloupe.org ($249/year); the store-issued licences are signed with a new key added to
LICENSE_PUBLIC_KEYS in this release.
Fixed
- Fonts inventory no longer selects the whole page — every element inherits a computed font-family, so "715 uses" counted containers and Locate's first match was often
<body>. Font groups now only count elements with direct text, and the view lists unique font styles (family + size · weight · style · line-height cards, CSS Pully-style) clustered by family, under a family chip row that filters on click — instead of expandable family rows. Locate buttons across the panel also switched to a proper target icon. - Anchor mode no longer disarms itself — after clicking "Anchor to element", the panel persisted a store snapshot carrying a stale
mode: 'idle', which synced back to the page and tore down the anchor inspector moments after it armed (timing-dependent; automation hit it every run, humans occasionally). The panel now mirrors the mode before writing. - Design tab shows the diff summary again — the panel's hydrate poll never applied
figmaDiff/figmaSummary from GET_STATE (every other heavy result was wired), so severity groups and repeat offenders never rendered after a compare. - Figma token errors are visible — a failed Save & Connect stored the error where only the connected view rendered it; the token form now shows the failure inline, names the scopes a scoped token needs (File content + Current user, read), and the scope-missing 403 gets a message saying how to fix it.
0.7.4 — 2026-09-12
Added
- Page Rulers crosshair — Rulers mode (
R) now tracks the cursor with a live crosshair and position tags on the ruler bars; hovering a real element snaps the crosshair to its edges and shows a floating X: Y: W: H: readout. Descends into same-origin iframes (common for embedded dashboards/tables) so it snaps to the real element inside rather than the iframe's own box. Shows nothing while hovering Loupe's own dock, instead of an unsnapped crosshair with nothing to measure. The ruler bars can be hidden from a popover behind the dock button, keeping just the crosshair; the choice persists across restarts.
Fixed
- Closing a mode's settings popover no longer exits the mode — the
X on the Grid and Rulers popovers used to call the same handler as turning the mode off entirely; now it only dismisses the popover, and it reopens the next time that mode is freshly activated.
0.7.3 — 2026-09-09
Added
? shows keyboard shortcuts — pressing ? now toggles the dock's shortcuts popover, same as clicking the help button.
Fixed
- Design tab Fetch always pulls a fresh tree — the explicit Fetch button now bypasses the 15-minute Figma cache, so the tweak-frame → refetch → recompare iteration loop never runs against stale data. The cache still serves batch compare and re-anchor paths.
- Figma diff labels transparent backgrounds honestly — a DOM element with no background compared against a filled Figma node now reads
background-color transparent → #… instead of inventing #000000 (alpha was dropped during parsing). Still flagged as drift — a missing fill is real — just no longer mislabeled. - Viewport-mismatch warning only fires for page-sized frames — comparing window width to a component-sized Figma frame (a card, a button) is meaningless since the diff anchors to one element; the Design tab now keeps the warning for desktop pages (≥ 500px wide) and mobile pages (≥ 320px wide and ≥ 600px tall) and stays quiet for component frames.
0.7.2 — 2026-08-16
Changed
- Component inventory sees nested components — a slotted container (
tabs, dialog, a page-level layout div) no longer swallows everything rendered inside it into one entry. Slot values following the <root>-<part> convention still count as parts of their root; any other nested slot (button, card, select-trigger) now gets its own inventory entry with its own variant histogram. Part names outside the convention can be declared via the new optional components.partSlots profile field. Lookalike detection now also runs inside component subtrees: an unslotted native control is flagged unless its direct parent is slotted (DS wrapper internals stay exempt). The scan now only records rendered elements, so panel counts, overlay badge numbers, and visible boxes always agree — hidden triggers and collapsed menus no longer produce phantom findings. - Org licences are sticky across profile auto-refresh — when the profile fetched from
updateUrl omits the license field, the refresh keeps the licence developers already imported. Teams can now host the profile publicly for token sync while distributing the licence privately once; a hosted profile that does include a licence still replaces the stored one (renewal rollout path). Documented in the authoring guide.
Internal
pnpm publish:store pre-flights versions before uploading: refuses when the zip's manifest version isn't greater than the store's published version (forgot the bump) or doesn't match package.json (stale zip — forgot pnpm package). --skip-version-check bypasses.- Custom domain getloupe.org: manifest
homepage_url, privacy-policy and store-listing URLs moved off contactashpat.github.io (old URLs redirect; onboarding page at https://getloupe.org/welcome).
Added
- Profile authoring guide published at https://getloupe.org/docs/profiles/ (the repo's
docs/profile-authoring.md, which is not publicly linkable); the DS tab's Import popover now links to it.
0.7.1 — 2026-07-28
Fixed
- Typing in panel inputs no longer triggers shortcuts — entering "px-lg" into the Tailwind brand-prefix field (or any panel input: Figma URL/token, DS import…) closed the panel the moment "p" was typed, because the panel's P check deliberately sat above the typing guard. Fixed structurally: both keyboard surfaces are now thin handler maps over a single
dispatchShortcut() that enforces the typing guard per shortcut from the keymap's own flags — only non-printable keys (Esc) may bypass it, an invariant enforced by unit test. The panel also gained the DS Components (O) and DS Lint (L) shortcuts it was missing.
Changed
- Component scan honours
ignoreSelectors — the profile's ignore list (previously lint-only) now also skips subtrees in the component inventory, so consciously-accepted exceptions (e.g. elements marked with a data-ds-exception attribute the profile ignores) stop reappearing in every audit. Documented as a team convention in the authoring guide.
0.7.0 — 2026-07-26
Added
- DS Profiles for Teams: offline org licences. Profile schema v2 adds
origins[] (auto-bound on import), updateUrl, reportWebhook, and an embedded signed license blob. Licences are ECDSA-P256-signed JSON verified fully offline against public keys shipped in the extension (key list supports rotation); a valid licence covering the tab's bound profile unlocks every Pro gate (audits, Figma compare, AI, batch emulation) for the whole team — no individual accounts. 14-day renewal grace after expiry with a panel warning; the DS tab shows "Licensed to <org> · expires <date>". Issued with scripts/keygen-license.mjs + scripts/sign-license.mjs; the private key lives outside the repo. v1 profiles remain fully supported. - Hosted-profile auto-refresh — profiles with an
updateUrl re-fetch daily and on browser start (new alarms permission); a fetched profile replaces the stored one only when it validates, keeps its id, and has a newer generatedAt — a broken deploy never bricks existing installs. Declared origins re-bind on refresh. - "Send to team" reporting — when the bound profile declares a
reportWebhook, lint and dark-diff results gain an explicit send button that POSTs the findings to the team's own endpoint (page URL + findings + profile id + extension version; never tokens/credentials; https only; never automatic). Privacy policy updated accordingly. - Team licensing surfaces — DS-tab "Get a team licence" link, README / authoring-guide / store-listing sections; commercial licensing is contact-based.
- "AI fix prompt" export — one click copies a self-contained markdown brief for a coding agent (Claude Code, Cursor, …) built from the audit findings: greppable class-string evidence, rendered-location selectors, per-rule fix guidance, replacement suggestions, and guard-rail constraints. Available on the component inventory (replace native controls with DS components), the lint audit, and the dark-mode diff.
- Numbered finding badges + annotated screenshot capture — component and lint overlay boxes now carry corner badges whose numbers match the prompt's
[n] markers (a documented contract between overlay and report), and a camera button beside the AI-prompt button downloads the annotated viewport as a PNG — paste the prompt, attach the shot, and a multimodal agent can cross-reference every finding visually. Visible viewport only. - Selector generator ignores framework-generated ids (
radix-_r_N_, React useId, Headless UI…) — they regenerate per render and never appear in source, so selectors built on them were useless as evidence; class selectors are used instead.
Internal
pnpm publish:store — zero-dependency Chrome Web Store API publisher (scripts/webstore-publish.mjs): --init one-time OAuth setup (loopback flow, credentials in gitignored .webstore-credentials.json, WEBSTORE_* env vars override for CI), default run uploads loupe-<version>.zip and submits for review, --upload-only / --status / --zip flags.
0.6.0 — 2026-07-26
Added
- Panel text zoom — ZoomOut/ZoomIn buttons in the panel header (70%–160%, click the percentage to reset). Uses CSS
zoom so every panel surface scales and reflows; persisted across browser restarts, applies to both the native side panel and the injected iframe panel.
Fixed
- "Log in" is now offered at every Pro gate (a11y audit, DS lint, dark-mode diff), not just the Design tab's UpgradeCard — users with a paid licence or dashboard-granted free access on another install had no way to link their email from the DS/Page tabs.
- DS Components shortcut hint disambiguated — "Press O (the letter O)"; the monospace kbd chip read as the digit zero.
- Modes no longer resurrect after being stopped (e.g. Tailwind Xray restarting seconds after pressing
S). The panel's 1-second state poll wrote its snapshot through persisting store actions, so a response fetched just before a mode exit re-broadcast the stale mode to the page via the storage sync. Hydrate now writes through the store's raw setState — display-only, never persisted. - Pro: dark-mode diff (DS tab) — snapshots every rendered element's colour channels, toggles the profile's
darkDiff theme axis on <html>, re-reads, and flags colours that are byte-identical across the toggle — hardcoded values the static lint can't see when consumer CSS indirects to them. Fully synchronous (snapshot → toggle → re-read → restore in one task) so page theme managers never observe an intermediate state; a no-transition style neutralises animated theme libraries; inherited channels report on the ancestor that set them, not every descendant; tokens whose light and dark values are identical by design are whitelisted. Severity: error when the static colour matches a primitive or nothing, warning otherwise; each issue suggests the nearest token. - Design-token-aware Figma compare — with a profile bound, colour diff hints resolve to named design-system tokens (
bg-surface) instead of raw var(--…) names, flowing through FixCard chips, grouped summaries, QA reports, and AI prompts unchanged. - DS-aware AI suggestions — the explain prompt now names the bound design system, instructs the model to prefer its semantic token utilities and avoid raw hex/deprecated aliases, and includes what the current DOM value already matches.
- QA report: dark-mode section — exported reports include the dark-diff table (with colour swatches) when a diff has been run; export uses the cached result only, so downloading a report never flashes the page theme.
0.5.0 — 2026-07-25
Added
- Pro: DS Lint audit — one-click page-wide lint against the bound design-system profile's rules: raw colour literals (classes + inline styles), primitive tokens without a dark-mode override, raw Tailwind spacing scale outside design-system components, the silently-dropped
[var(--density-…)] arbitrary form, hsl(var(--…)) wraps, deprecated aliases (suggestion names the replacement), and raw text sizes where the DS ships a type scale. Grouped results in the DS tab with click-to-locate; errors before warnings; 300-issue / 5,000-element caps. - Pro: DS Lint overlay — new mode on
L painting red (error) / amber (warning) boxes with per-issue tooltips. The overlay requests the scan through the background, so the keyboard shortcut cannot bypass the licence gate; unlicensed use shows a trial hint toast. - QA report: design-system section — when a profile is bound, exported reports gain a lint table (severity, issue, suggestion, evidence, selector) and the header names the profile and its error/warning counts.
- Profile authoring guide —
docs/profile-authoring.md: the released reference for design-system teams building their own profile JSON (schema, lint-rule semantics, generation, distribution, pre-release checklist).
Fixed
- DS tab no longer shows another tab's binding state. On tabs where Loupe wasn't started, the panel could display a different tab's profile meta and page origin (globally-synced store fields) while lint correctly failed with "no profile bound".
GET_STATE now always answers with the tab's own document URL and locally-derived profile meta, and the DS RPC handlers lazily load the origin binding on demand.
Internal
- Unit tests introduced (
pnpm test, Vitest 3 — v4 needs Vite 6): 49 tests covering profile schema validation, all seven lint rules, the token engine (reverse lookup, ranking, page-var fallback), and the Tailwind classifier. Standalone vitest.config.ts so the crx plugin stays out of the runner. Verification gate is now typecheck + test. - Shared panel style atoms extracted to
src/panel/styles.ts (ghost/kbd/ input/primary/secondary), replacing per-tab duplicates.
0.4.0 — 2026-07-25
Added
- Design System Profiles (free): import a JSON profile describing your design system — tokens (CSS vars + utility classes + light/dark values), component fingerprints (slot attribute + variant attributes), theme axes, and lint rule config — and bind it to a page origin. Import from a URL, pasted JSON, or a file; profiles persist in
chrome.storage.local and never ride the session store sync. No profiles are bundled — a design system's tokens and fingerprints are distributed by its owning team, not shipped to every Web Store user. scripts/build-profile.mjs — generic reference profile generator: merges a hand-authored base config (scripts/example-profile.base.json is the neutral starting point) with a token manifest; output lands in the gitignored profiles/ directory. Nothing design-system-specific is tracked in the repo.- Element panel Tokens view (free): the Code section's toggle is now Computed ⇄ Declared ⇄ Tokens. Per property: declared
var() usage (exact), design-system utility classes (exact, the only route for class-only legacy aliases), and computed-color reverse lookup (ranked candidates, never claimed as certain). Flags raw values, primitives, and deprecated aliases with their replacement. - DS Components mode (free): new mode on
O — inventories the page via the profile's slot attribute (component roots, part counts, variant histograms) and flags native button/input/select/textarea/[role=button] outside the design system as lookalikes. Teal boxes for components, red for lookalikes; lookalikes painted first under the 400-box overlay cap. - DS panel tab: profile management (import/bind/delete, detect banner) plus the component inventory with locate-cycling and rescan.
Internal
- The rAF box/tooltip overlay machinery is extracted from Tailwind Xray into a reusable
boxOverlay factory (offscreen boxes now skip painting); Tailwind Xray behaviour is unchanged. - New
readCssVarsDeep() walks @media/@layer/@supports and adoptedStyleSheets with theme-axis selector context (the Figma-compare var reader is untouched).
0.3.0 — 2026-07-25
Added
- Tailwind Xray (free): new mode on
S that highlights every element carrying raw Tailwind utility classes — category-colored overlay boxes, hover tooltip listing the matched classes, click-to-inspect. Detection is a heuristic classifier (variant/important/negative stripping, arbitrary values, curated utility families) with a configurable brand-prefix allowlist so design-system classes are never flagged. - Tailwind panel tab: per-utility counts with locate-on-page cycling, brand-prefix editor with live rescan.
Changed
- Select Target removed: the dock button and
S shortcut duplicated Inspect (I); the slot now triggers Tailwind Xray.
Fixed
- Select child (↓) was a silent no-op. Parent/child navigation now walks the live DOM: ↑ remembers the child it left so ↓ returns to it, falling back to the first element child — ↑/↓ are a reversible pair.
- Side panel is now strictly per-tab: it no longer stays visible when switching tabs, and a panel closed via any path (including Chrome's own ✕) no longer reappears when returning to its tab.
Internal
- Lockfile migrated to pnpm 11 (v9 lockfile),
packageManager pinned, esbuild/sharp install scripts approved via pnpm-workspace.yaml. - Privacy policy and store listing kit aligned with Web Store disclosures.
0.2.0 — 2026-07-19
Added
- Loupe Pro via ExtensionPay: subscriptions + lifetime plan, 7-day trial, background-enforced gating, QA report export (standalone HTML).
- Pro: accessibility audit — page scan for contrast, alt text, tap targets, form labels, control names, document language/title, heading order.
- Pro: breakpoint batch compare — re-runs the Figma diff across multiple emulated widths.
- Responsive mode:
chrome.debugger device emulation applied to the current tab in place (metrics, touch, UA + client hints), with an in-page toolbar; survives navigation while attached. - Color picker upgrades: live magnifier bubble with pixel sampling, clipboard copy, palette, CSS-variable matches, contrast checker.
- Element screenshot and copy-as-CSS dock buttons.
- Dock UX: drag + snap to any screen edge, compact state, startup hint, shortcuts help.
Fixed
- Find-element text search.
- Service-worker registration killed by ExtPay validation (payment-page content script now runs at
document_start).
0.1.0 — 2026-07-12
Initial release: element inspector, xray outlines, layout grid, rulers,
element-to-element distance measuring, color picker, find element, side
panel / in-page panel surfaces, Figma design-vs-DOM comparison with optional
AI explanations.