Overview
AnchorKit is a WordPress plugin I designed, built, and shipped end-to-end — a polished, accessibility-first table of contents plugin with a WYSIWYG settings experience.
It's self-initiated work. There was no client brief, no scope document, no deadline. Just a category I'd noticed was being underserved on the design front, and a hypothesis about what a more thoughtful product could look like. The plugin is live on the WordPress.org plugin directory and passed the wp.org review process.
It's also the case study where I learned the most not from what worked, but from what didn't.
The Gap
A handful of plugins dominate the WordPress table of contents category, with hundreds of thousands of active installs between them. By every business measure, they're successful. Spend an afternoon inside their settings panels, though, and the product gap becomes obvious.
Dated Default Output
The TOCs that ship out of are very poorly designed. Heavy borders, default link styling, no consideration for the surrounding content. Customizing them is possible, but the defaults set the tone.
Dense, Confusing Settings
Most settings interfaces are unstyled WordPress defaults — long forms, terse labels, no grouping logic. They were designed to expose options, not to help users make decisions about them.
No Live Preview
Every change requires the same loop: save the setting, reload the front-end in another tab, check the result, return to the settings, repeat. The category had collectively decided this was acceptable.
Existing settings UX in the category
It's a familiar pattern. Plugins ship early, capture distribution, and never reinvest in the experience — while user expectations for settings interfaces have moved on. Modern app settings show you what you're changing in real time. WordPress plugins, mostly, do not.
I thought I could do better.
The Hypothesis
Users would prefer a table of contents plugin where every setting — colors, layout, animation, behavior — reflects instantly in a live preview that mirrors the actual front-end. No save buttons. No reloads. No guessing.
If I designed something visibly more polished than the incumbents, with better options and a settings experience that felt like a modern app rather than a WordPress admin form, it would find its way to users frustrated with the existing options.
It's a clean hypothesis. It also turned out to be the wrong starting point — but I'll come back to that.
What I Designed
Live Preview Without Compromise
The core design decision was simple: every setting should reflect instantly in a preview that mirrors what the user will actually see on their site. No save buttons, no reloads, no "did that work?" guessing.
Behind the scenes, this was the most technically demanding part of the build. The preview pane had to render TOC fragments through the exact same code path as the live front-end — anything else risked a preview that didn't match production.
To pull that off without flooding the database with intermediate states, I used a debounced AJAX layer that writes settings normally, then renders the preview using temporary option overrides that intercept reads without polluting the cache.
The settings page and the public front-end share zero JavaScript. But the preview is production-truth.
Settings panel with live preview
Depth Without Density
The plugin exposes more than fifty persisted options — full color palettes for light and dark modes, typography controls, layout, animation, scroll behavior, anchor ID format, post-type targeting, mobile breakpoints. The surface area would be overwhelming if it were exposed as one long form.
Instead, the interface is tabbed and grouped. Related controls sit together. Defaults are sensible and visible.
Every option is also overridable per-instance via shortcode attributes or Gutenberg block controls — so a single page can run multiple TOCs with different behaviors without fighting global settings.
Tabbed settings — depth without density
Per-Section Reading Time
A small but useful detail: each TOC entry can show the estimated reading time for that section, not just the full post. It surfaces the question readers actually have — how much am I committing to if I jump here? — and answers it inline, where the decision is being made.
Accessibility as Default
The TOC ships as a <nav> element with proper ARIA labelling. Toggles are keyboard-accessible buttons with aria-expanded and aria-controls. Focus states are visible. Theme switching (light, dark, system) is handled through CSS custom properties, so swapping modes is instant and avoids any flash of unstyled content.
For this plugin, accessibility wasn't a feature added at the end. It shaped the markup decisions from the start.
Key Design Decisions
Production-Truth Preview Over Approximation
Most "live preview" features in WordPress plugins use a separate code path — a simplified rendering that approximates what the front-end will look like. AnchorKit uses the real one. Every preview frame is the same HTML that production would output. The technical cost was higher; the trust the user places in the preview is also higher.
Anchor IDs That Match Gutenberg's Behavior
WordPress core (via Gutenberg) generates anchor IDs for heading blocks using a specific slugification logic. Most TOC plugins use their own — which means a link from a TOC to a heading block can silently break. AnchorKit deliberately matches core's behavior, including the underscore-stripping quirk, so links work on hybrid pages where some headings are plugin-generated and some are native.
No Custom Database Tables
All data lives in the standard WordPress options table with a consistent prefix. Uninstalling the plugin cleanly removes every trace, including across multisite networks. Plugins that create custom tables are common; plugins that clean up after themselves correctly are rarer. The decision was about respect for the user's database.
How It Got Built
I designed the architecture, the UX, the settings model, the visual language, and the microcopy. I used Claude Code and Cursor to write most of the implementation, with my judgment driving every meaningful design and architectural decision — how the live preview avoids cache pollution, how anchor IDs match core behavior, how multisite uninstalls iterate every site, what to gate behind a Pro tier, where to draw the line on customization depth.
The plugin passed the WordPress.org plugin review on first submission — strict prefixing, escape-on-output, nonce verification on every privileged operation, GPLv2 licensing, transparent telemetry messaging, no obfuscation, no eval, no external script loading at install — and went live in the directory.
For a designer, the relevant detail isn't the code. It's that the design intent survived all the way through to a shipped, audited product, with no compromises forced by handoff to someone who didn't share the vision.
AI tooling makes that level of end-to-end ownership newly possible for designers with strong product judgment. AnchorKit was, in part, a deliberate exercise in finding the limits of that.
Front-end output — clean, accessible, and on-brand by default
What I Learned
A clean UX hypothesis is not a validated market opportunity. The design gap was real — but I never asked whether the people using the incumbent plugins were actually frustrated by it.
The honest answer, which I figured out after shipping: most users install a TOC plugin once, click save, never open the settings again, and never think about it. The category isn't underserved by design quality. It's underserved by anyone marketing design quality as a reason to switch. Those are very different problems, and I had only solved one of them.
The lesson isn't that the design was wrong. It's that shipping a polished product is only half the work. The other half — talking to users, validating the pain, finding the channel, learning the positioning — I'd quietly treated as someone else's job. It isn't. It's the work that decides whether anything I build gets used.
This is the kind of mistake easy to make as a designer with execution capability. The temptation to build is strong. Building feels productive. Validating feels slow, and harder to measure, and uncomfortable in a way that staring at a Figma file is not. But execution without validation is how good products end up unused — and the experience taught me that distinction in a way no amount of reading would have.
If I started AnchorKit over today: a landing page first. Posts in WordPress communities. Conversations with people about their TOC pain — close attention to what they actually said versus what I assumed. A smaller version shipped sooner. Real usage telling me what to invest in. Marketing as a first-class concern, not an afterthought.
Instead, I built the full thing — and then learned the lesson. That's a worse order. But the lesson stuck.
Outcome
Live and Audited on WordPress.org
Passed the wp.org review process — security, escaping, prefixing, accessibility, licensing, and telemetry transparency all met the directory's standards.
A Working Reference for Plugin UX
A self-contained example of what a design-led WordPress plugin can look like — production-truth live preview, accessibility as default, clean settings architecture, real respect for the user's environment.
A Validation Discipline I Now Apply
Every product hypothesis since has gone through a validation step before any meaningful build work — landing page, conversations, smallest possible version. Build is no longer the first move.
Proof of End-to-End Ownership
A 0-to-1 product designed, architected, built, audited, and shipped by one person — the kind of range that's increasingly possible for designers with strong product judgment and modern tooling.
Reflection
AnchorKit is the project that taught me the difference between being able to build something and building something that should exist. They sound like the same thing. They aren't.
The most useful skill I learned wasn't technical. It was the discipline to sit with a hypothesis longer before acting on it — to resist the pull of execution when execution is the most familiar move.