Thesis

Prototyping got cheap. A working artifact used to take a week and a designer; now it takes a prompt. The cost collapsed everywhere except one place: the feedback layer, which is still a screenshot pasted into Slack with an arrow drawn on it.

Sidenote is built for the world the prototype tools just made. Design feedback is mostly grammar problems: reviewers can't agree on what they're looking at, what they're objecting to, or what would resolve the comment. Sidenote treats review as a structured language. Every note is anchored to a real element, tagged with severity and intent, and routed as a ticket the moment it's filed.

The result isn't more feedback. It's feedback that keeps up.

Severity × intent

Most comment tools collapse two questions into one box: "what's wrong" and "what do you want me to do about it." A reviewer typing "this looks off" is doing both: voicing a reaction and implying a request, and the receiver has to guess which.

Severity ↓ / Intent →
Fix
Change
Question
Approve
Blocking
Modal traps focus
Use H1, not div
Important
Tighten this copy
Why this color?
Suggestion
Inline label?
Ships.
Three severities × four intents = twelve cells. Every comment carries this triplet downstream: what element, how serious, what action.

Sidenote splits the question. Severity describes the gravity of the observation: blocking, important, suggestion. Intent describes what the reviewer wants to happen next: fix, change, question, approve. The default is small on purpose. Every additional cell re-introduces the ambiguity the system was meant to remove. That's the grammar.

Defaults, not constraints

Three by four is the default, not the rule. Teams can edit either axis to fit their vocabulary: collapse "fix" and "change" into one, trade "blocking" for "critical", add a "polish" intent, drop a severity that doesn't show up in design review. What doesn't bend is the structure. Every comment still carries one severity and one intent. That's the grammar; the vocabulary belongs to the team.

Why an extension, not a Figma plugin

For the grammar to do its job, it has to live where work lives. The reflexive answer was Figma plugin: design lives there, the comment thread lives there, ship it. The problem: most consequential feedback happens after the design has left Figma. It surfaces when a PM is poking at a staging build, when an engineer notices a spacing drift in a PR preview, when a stakeholder reviews the live URL.

Figma

Storybook

PR Preview

Production

The same anchor, four surfaces. The comment doesn't translate. It travels.

An extension follows the work wherever it actually lives. Anchoring a comment to a DOM node, not a frame, means the comment survives translation: from Figma → Storybook → PR preview → production. The taxonomy travels with it. The ticket travels with it.

It's also keyboard-first. Anchor a comment, tag severity, tag intent, ship. All of it happens without leaving the keyboard. Reviewers who are designers are reviewers who live there.

What we killed

Severity scale

criticalblockingimportantsuggestionnit

Easing curves

entrance easeeaseOutQuint (signature)exit ease

An earlier default severity scale had five values. Two of them (critical and nit) never disagreed with their neighbors in user testing. Reviewers used "critical" and "blocking" interchangeably and treated "nit" and "suggestion" as the same act with different apologies. We cut both. Three values forces a decision; five let people hide behind the middle.

Same edit on the motion side. An earlier prototype used three different easing curves: one for entrances, one for exits, one for state changes. It read as fussy. Consolidating to one signature ease and one spring made the product feel more deliberate, not less.

Motion as part of the product

Sidenote lives over someone else's UI. Motion is how it earns the right to be there. Every animation has to feel native to the host page, not like a foreign overlay. The product ships with two primitives, named the same way they're named in the codebase.

The ease

cubic-bezier(0.23, 1, 0.32, 1)

easeOutQuint, the signature curve. Comment composers open with it, surfaces settle into place with it.

The spring

stiffness 340 · damping 14 · mass 0.6

A hand-tuned spring with a small overshoot. Markers drop onto DOM elements with it. The italic ‘feel’ in the H1 above rides this same spring.

Two primitives, looping above. Everything in the product is one of these two curves applied to a different surface.

Everything else (anchoring, severity selection, resolution into focus) is one of these two curves applied to a different surface. Restraint in motion the same way the taxonomy is restraint in language. Three severities, one ease, one spring.

Closing

When motion is part of the grammar, the language of feedback stops being something reviewers have to translate. A comment is anchored, classified, and ticketed, and it gets there in curves the rest of the product already speaks.

A grammar isn't rules. It's the shape of how things hold together.

Theme as a layer of the page. Directional clip-path reveal via the View Transitions API. Light sweeps down, dark sweeps up. Sidenote rides the host page's transition, not its own. The theme switch you just used on this portfolio is the same primitive.