Contents
The Process.
Seven chapters, from one conversation at Config to a plugin anyone can install. Read it the way it happened, or jump straight to a part.
- 01
Spark
- 02
Problem
- 03
System
- 04
Design
- 05
Brand
- 06
Ship
- 07
Reflection
Spark
Figma brought Config to India for the first time. I went to listen, found a gang of six, and left with a promise to keep.
Spark · Config India 2026
Figma's first Config in India, and a gang of six.
It was an invite-only room. I went as a design-first builder, mostly to listen. I walked in alone, and within the first hour I had found a group. Six of us stayed together the whole day.
We talked design all day
- 01Where AI fits in a designer's week
- 02Whether craft still matters
- 03What good means now
I learnt more from those conversations than I expected.
The announcements
- Code layers
- Specstood out
- A whole set of betas
The promise
Twelve hours later it worked
Later that day, Riya mentioned she uses Obsidian. So do I. I told her I'd try to build a Figma plugin for it. Twelve hours after the event, I had a first version working.
Why it stuck
I'd moved from Evernote to Obsidian a few months back, and I probably talk about it too much.
My whole working memory lives in a vault: product specs, research, design decisions. My designs live in Figma. Spec was the first announcement that made those two feel like they belonged on the same canvas.
- First commitPlugin, local vault bridge and a preview harness
- Site liveMarketing page, README shots, MIT licence, Pages deploy
- v1.0Specs export and the status chip on the frame
Spark · What Spec changed
Specs speak markdown, and so does Obsidian.
A Figma Spec is markdown. Drop any .md file on the canvas and Figma turns it into a native Spec. Every note in an Obsidian vault is already a plain .md file. The bridge was sitting right there.
---
tags: [spec, checkout, payments]
status: draft
---# Payment MethodsOrder of methods on the payment step,
decided by device and locale.## Rules- Apple Pay first on iOS/Safari, Google Pay
first on Android/Chrome
- Cards always available; PayPal only in
US/UK/DE
- Remember last used method per account
(see [[Checkout Redesign]])## Copy- Title: "How would you like to pay?"
- Helper: "You won't be charged until you
confirm."
#spec#checkout#paymentsdraft
Payment Methods
Order of methods on the payment step, decided by device and locale.
Rules
- Apple Pay first on iOS/Safari, Google Pay first on Android/Chrome
- Cards always available; PayPal only in US/UK/DE
- Remember last used method per account (see Checkout Redesign)
Copy
- Title: "How would you like to pay?"
- Helper: "You won't be charged until you confirm."
The catch: Figma ships no Plugin API for Specs. A plugin can't create one. So Obspec had to meet Specs halfway, and that became the first of four walls.
Problem
The decisions live in Obsidian. The designs live in Figma. The space between them is where specs go stale.
Problem · The gap
Decisions in one app, designs in another.
The why behind a button, the rules for a payment step, the copy everyone agreed on: it all gets written down in notes. The frames that carry it out live in Figma. Paste a note into a frame and it starts going stale the moment either side changes.
The problem space
Specs get copy-pasted between two apps that never talk to each other, so nobody knows which side is right.
The solution
Obspec puts the vault one search away from the canvas, and keeps every note linked to the frames it describes, both ways.
- Monday
The spec is pasted into a frame. Both sides agree.
- Wednesday
The note changes: PayPal is now US only. The frame never hears about it.
- Friday
The build follows the frame. Nobody knows which side was right.
A familiar week, and the reason a link has to know when either side moves.
Problem · Constraints
Four walls Figma puts around a plugin.
Two were known on day one. The other two showed up the first time the plugin met real Figma. None of them could be argued with, only designed around.
- 01
A plugin can't read your disk
sandbox + iframe · no file systemSo a tiny bridge runs on your own machine, indexes the vault and answers the plugin over localhost.
- 02
Figma rejects IP addresses
allowedDomains: "http://127.0.0.1" ✕So the manifest allows exactly http://localhost:27123, and the bridge listens on both 127.0.0.1 and ::1.
- 03
Specs have no Plugin API
Plugin API · no Specs endpointSo Obspec exports Spec-ready .md and writes only the blocks Specs understand: headings, lists, quotes, code. No tables.
- 04
FigJam has no frames
editorType: ["figma"]So the first release is Figma only. Spec cards are auto-layout frames, and FigJam can't hold one yet.
Problem · Scope
Two ideas, and nothing else.
The brief I held myself to, on the plugin and on the site: two ideas only, no info dump. Every feature had to serve one of them, or it didn't ship.
Search the vault inside Figma
Every note, by title, path, tag or body, in milliseconds.Two-way sync with Figma Specs
Link a layer to a note. Pull changes in, send design back.- Kept out on purpose
- ✕Accounts
- ✕A cloud
- ✕Analytics in the plugin
- ✕A feature grid
- ✓Plain .md stays the source of truth
System
A plugin that can't touch your disk, a vault that can't talk to Figma, and a tiny bridge on localhost in between.
System · Architecture
Three hops, all on your machine.
The plugin's UI runs in an iframe and its logic in Figma's sandbox. Neither can see your disk, so a zero-dependency Node bridge does: it indexes the vault, watches it, and answers on localhost. Edit a note in Obsidian and the bridge pushes an event before you've switched windows.
Figma
Obspec Bridge
Obsidian vault
- Product/Specs/Payment Methods.md
- Product/Specs/Checkout Redesign.md
- Design/System/Button.md
- Research/Checkout Interviews Oct.md
- + every other .md file
bridge · replaying the demo flow
- GET/health
- GET/vaults
- POST/vault
- POST/vault/pick
- DELETE/vault
- GET/hashes
- GET/search
- GET/note
- GET/notes
- PUT/note
- PATCH/note
- SSE/events
It binds to 127.0.0.1 and ::1 only, allows just the plugin's origin, figma.com and localhost, and writes to the vault only when you press Send to Obsidian.
System · Two-way sync
Every link knows who moved.
A link lives on the Figma layer itself, as plugin data: the note's hash and the layer's design fingerprint at the last sync. Compare them with what's there now and you know which side changed. No database, no account, no server keeping score. Try it.
obspec:link plugin data on the frame
- path
- Product/Specs/Payment Methods.md
- kind
- linked
- noteHash
now- designHash
now
computeSyncState() → in-sync
How would you like to pay?
Apple PayCard number Continue to paymentThe same FNV-1a hash and the same computeSyncState() the plugin ships, running on this page. Edit both sides to see Both changed.
System · Performance
From 26.5 seconds to 45 milliseconds.
The demo vault has eleven notes. Mine has over six thousand. The first build worked out backlinks by scanning the whole vault every time you opened a note. A basename index and an inbound-link index turned that into a lookup.
Opening one note · 6,000-note vault
589× faster, on the same 6,000-note vault
Design
A 500 × 780 window with three tabs. Everything a designer needs from their notes, and nothing they'd have to learn.
Design · First run
Two steps, then it gets out of the way.
A plugin that needs a helper on your machine lives or dies on its first minute. The first run waits for the bridge and moves on by itself when it comes up, then lists the vaults Obsidian already knows about. Click one, and you're searching.
- 0accounts or sign-ins
- 1command, once
- 2screens to your first search
Design · Search
The whole vault, one search away.
Grep-style search over title, path, tags and body, with filters that feel like a code editor's. This is the real demo vault, all eleven notes, searched in your browser the same way: highlights, line numbers, which fields matched. Type anything.
Results11 notes
Drag any result onto the canvas to drop it there as a spec card.
Try one
On a 6,000-note vault the bridge answers in about 30 ms. Here it's eleven notes and your browser, so expect well under one.
Design · The spec card
A note, rebuilt as a real Figma frame.
Press Insert, or drag a result onto the canvas, and the note becomes an auto-layout frame: headings, lists, quotes, code and images become real layers. Drop it inside a frame or section and it lands right there. The status chip sits on the frame itself.
- Source lineVault folder, always visible
- TitleThe note's H1
- TagsFrom frontmatter and #hashtags
- BodyHeadings, lists, quotes, code
- FooterOpen in Obsidian, path, word count
- Live statusIn sync, Note changed, Design changed
- Real layersText, not a picture of text
- WikilinksBecome plain text, nothing dangles
- Auto layoutGrows with the note on every Pull
Design · Flows
Five things, end to end.
Everything Obspec does fits in five flows, and every one of them runs in the preview harness with the real plugin UI and the real bridge. These stills are from it.
Design · Views & themes
Three layouts, two themes, one window you can stretch.
The default window is 500 × 780, with a grip to resize it and the size remembered. Results come as Cards, a List or Compact rows, and the theme follows Figma's or overrides it.
Brand
Figma's mark, carved from violet obsidian, and a landing page that went through ten rounds of feedback in one day.
Brand · The mark
Figma's mark, carved from violet obsidian.
Obsidian is volcanic glass, and Figma is the canvas. So the logo is Figma's own five-piece mark, cut from banded violet obsidian. It renders live in three.js on the site, from the 50px header gem to the big one on its plinth. These stills come from the same code.
- GeometryExtrudeGeometry · depth 7.5 · bevel 2.4 · 2 bevel segments · 7 curve segments
- TextureCanvas-drawn violet bands at −0.62 rad, 220 pale flecks
- MaterialMeshPhysical · roughness .14 · clearcoat 1 · flat shading
- LightBacklight #ffc98a · fill #8f6bff · violet point light behind
- v5An obsidian stone with the Figma mark on it
- v6Stone in 3D, the mark kept flat
- v7Black glass. No glitter, no halo, no wireframe
- v10The logo is the gem
- v11A polished plinth, after the jagged rock
Brand · The site
Ten rounds of feedback, one landing page.
I was my own toughest client. The site went from v3 to v12 in a single day, each round a short brief, some of them a single line (quoted). Only two ideas were ever allowed on it. Everything else got cut.
- v3
Cheap, garish and generic
3D notebooks on a rail. Thrown out entirely.
Rejected - v4Two screens, scrubbed by scroll
OffBit display type, Apple's system font, Obsidian and Figma side by side, scrubbed by scroll.
Rebuilt - v5
Doesn't fit
Cobalt and orange out. Obsidian glass in: near-black, paper and one Obsidian purple.
Recoloured - v6
Stone 3D, mark flat
One fixed stage, no footer. Six states and an outro where the window lifts away.
Restaged - v7Seven fixes in one brief
A scroll button that names the next step, black glass, and teammates' cursors on the canvas.
Seven fixes - v8
Wasn't catchy
The purple banner became paper white. A laurel badge and a mock frame that draws itself.
Rewritten - v9Open source again
A glass medallion, a banner that folds itself after 15 seconds, and a Contribute button.
Opened up - v10The logo becomes the gem
Figma's five pieces carved from obsidian, in the header and in the outro.
Kept - v11
It's Obsidian X Figma Spec, not the other way
Repo and Pages live, the lockup reordered, a polished plinth.
Shipped - v12
Breathing space
Wider gutters, a capped window, and the award reduced to grey line-work.
Live
Brand · The scroll
Six states, one scroll.
The whole site is one fixed stage. Scroll scrubs six states, both ways, because everything derives from a single progress value: search, results, a note flying through the seam, the link, a Pull and a Send. Drag the scrubber to play it.
Shot from the live site's code at 2×, with the announcement banner folded away.
Ship
28 commits in 60 hours, tested without opening Figma, through Figma's review, and down to one line in a terminal.
Ship · The build log
Every commit, from first line to Community.
This is the step-by-step build: all 28 commits, on a real clock. The first one lands on Thursday night. The site ships Friday morning. Saturday afternoon is the first run in real Figma, and the listing goes live that evening. Press replay.
From the repo's git log. Every commit was co-written with Claude Code.
Ship · Testing
Tested without ever opening Figma.
Testing a plugin by hand is slow. The preview harness runs the real plugin UI and the real bridge against a mock Figma document, with one-click emulations of every flow, and the same scenarios run headless in Chrome before anything ships.
$ npm test # tests 36 # pass 36 # fail 0 # duration_ms 276.4
- 36bridge, search, markdown and note tests, all green
- 7end-to-end scenarios in headless Chrome
- 27124the preview's own port, so a live plugin on 27123 is never touched
Ship · Figma review
Passing Figma's review, honestly.
Figma's review reads the manifest and the data-security answers. Obspec's are short because there is almost nothing to declare: one localhost address, no account, no analytics, no AI.
{
"name": "Obspec",
"editorType": ["figma"],
"documentAccess": "dynamic-page",
"networkAccess": {
"allowedDomains": ["http://localhost:27123"],
"reasoning": "Obspec talks only to the Obspec
Bridge running on your own machine
(localhost:27123), which indexes your
Obsidian vault. No data leaves your
computer."
}
}
- Does the plugin collect, store or transmit user data?
- No. Notes are read over localhost from a folder on your own computer. No server, no sign-in, no trackers.
- Does it write to your files?
- Only on Send to Obsidian. Searching, previewing, inserting and linking are read-only.
- Third-party services or AI?
- None.
First contact with real Figma · Sat 15:19 – 15:46
- Use the Figma-assigned plugin id
- A dev shim at the path Figma had registered
- Localhost-only network access, both loopbacks
- No symlinks, and listen for changes after pages load
- Spec card polish from the first real run
Five fixes in 27 minutes, and the plugin ran in Figma for the first time.
Ship · Install
One line in a terminal, once.
The first version asked you to start the bridge every time you opened Figma. My brief was blunt: “It's one time setup, not run the bridge every time.” Now one command installs it as a login service, and you never think about it again.
$ npx github:Kamal007OLica/obspec Obspec Bridge v1.1.0 — one-time setup ✓ Installed to ~/.obspec/bridge/obspec-bridge.mjs ✓ Registered with launchd (starts when you log in) ✓ Running at http://localhost:27123 · no vault yet (pick one in Figma) Done. You can close this window — the bridge keeps running in the background and comes back on its own after a restart. Go back to Figma and pick your vault.
- macOSa launchd agent in ~/Library/LaunchAgents
- Linuxa systemd --user unit
- Windowsa script in the Startup folder
- Laterstatus · uninstall · run in the foreground
Reflection
One conversation, one weekend, one plugin people can actually install.
Reflection · Results
Live on Figma Community
From one conversation at Config to a plugin anyone can install.
Reflection · Lessons
What I'd tell the next person building one.
Most of what made Obspec good was decided by things I couldn't change. The rest came from being a stubborn client to myself.
- 01
Design around the walls
No disk access, no IPs, no Specs API, no FigJam frames. Each wall became a decision: a local bridge, plain markdown, one localhost address.
- 02
Let the site make promises
The landing page said “insert them as Specs” and “status sits right on the frame” before the plugin did. Then a commit made both true.
- 03
Test where Figma isn't
The real UI and the real bridge against a mock document meant every flow could be checked in seconds, headless, before Figma ever saw it.
- 04
Big vaults tell the truth
Eleven demo notes hid a 26.5-second bug. Six thousand real ones found it. Always test with your own messy data.
- 05
Setup is part of the product
“Run the bridge every time” was a bug, not a step. One command, a login service, and the helper simply stays there.
Reflection · What's next
Where it goes from here.
Straight from the README's own list of limits. Nothing here is promised by a date.
- FigJamSpec cards need frames, and FigJam can't hold them yet. The first release is Figma only.
- Native SpecsToday Obspec hands you a Spec-ready .md. The day Figma opens a Plugin API for Specs, it can make them directly.
- Windows & LinuxThe bridge supports both, paths and folder dialogs included, but so far it's only been exercised on macOS.
Reflection
Final thoughts before we leave.
Leaving the gang at the end was the hard part.
One day with six people, and it already felt like home. Obspec is what I brought back from it: a small, local tool for the way I actually work, built because Riya mentioned Obsidian and I said I'd try.
Thank you, Figma, for coming to India. Thank you to the Figma community and every designer in that room.






















