VOOZH about

URL: https://dev.to/qonspekt/i-built-a-byok-browser-tool-that-turns-any-article-into-atomic-obsidian-notes-5c6d

⇱ I built a BYOK browser tool that turns any article into atomic Obsidian notes - DEV Community


I kept procrastinating on taking notes from articles I read. The cycle was always the same: read something interesting, tell myself I'll write proper notes later, never do it. So I built a tool to do it automatically.

What Qonspekt does

Paste any article → Claude AI extracts the key concepts → you get 3–7 atomic Markdown notes, ready to drag into Obsidian.

Try it: https://dertill123.github.io/qonspekt/

Each note gets:

  • YAML frontmatter (title, tags, aliases)
  • [[wikilinks]] connecting related concepts from the same article
  • ## Sources section with the original URL
  • Proper filename (concept-slug.md)

The technical approach: single HTML file, no backend

The whole thing is one HTML file. No framework, no build step, no server.

const response = await fetch('https://api.anthropic.com/v1/messages', {
 method: 'POST',
 headers: {
 'Content-Type': 'application/json',
 'x-api-key': userApiKey,
 'anthropic-version': '2023-06-01',
 'anthropic-dangerous-direct-browser-access': 'true', // official BYOK header
 },
 body: JSON.stringify({ model, max_tokens: 4096, system, messages })
});

The anthropic-dangerous-direct-browser-access: true header is Anthropic's official way to support BYOK browser tools. Your key goes from your browser directly to Anthropic — I have no server to log anything.

Getting consistent JSON from Claude

The trickiest part: Claude sometimes wraps output in markdown code fences even when told not to.

const raw = data.content?.[0]?.text || '';
const match = raw.match(/\[[\s\S]*\]/); // extract JSON array regardless of wrapping
if (!match) throw new Error('Could not parse response');
const notes = JSON.parse(match[0]);

This regex approach handles both clean JSON and fenced output reliably.

Serverless sharing

After generating, there's a "Share" button that base64-encodes all notes into the URL hash:

const enc = btoa(unescape(encodeURIComponent(JSON.stringify(notes))));
const url = location.origin + location.pathname + '#shared=' + enc;
navigator.clipboard.writeText(url);

On load, if the hash starts with #shared=, it decodes and renders the notes in read-only mode. No server, no database, no account needed for the recipient.

The system prompt

Getting the right structure took iteration. Key constraints that worked:

- Extract 3-7 key concepts, write one atomic note per concept
- Each note is self-contained but uses [[wikilinks]] to reference 
 related concepts from the same batch
- 150-280 words per note body
- Tags: 2-4, lowercase, hyphens for spaces
- Return ONLY a valid JSON array, no markdown fences

The "same batch" constraint for wikilinks is important — it makes the notes interconnected without hallucinating links to notes that don't exist.

Cost

~$0.003 per article with Claude Haiku 4.5. New Anthropic accounts get free credits.

Source

MIT licensed: https://github.com/Qonspekt/qonspekt

Would love feedback on the note structure or the prompt. What frontmatter fields do you typically use in your vault?