Markdown Needs a Comment Button

How a recurring annoyance at work — nobody outside engineering can read or comment on a .md file — turned into md.jholec.com, a hosted markdown reviewer I built with a team of 13 AI agents in five days.

AI Disclosure

Some parts of these notes were clarified and refined using AI tools such as ChatGPT, Gemini, and Claude to enhance clarity and readability. All ideas are my own, and I reviewed and edited all texts myself.

Date

/

Category

🎓 MUNI: Budoucnost práce

🎓 MUNI: Budoucnost práce

I work in markdown all day — specs, notes, decision docs, the raw output of every AI tool I touch. Sharing it with people who don't live in a terminal was quietly broken, so over five days I turned that annoyance into a product: md.jholec.com. And I didn't write most of it — I orchestrated a team of thirteen AI agents.

The pain point

Markdown is the native language of the AI era. Every Claude or ChatGPT output worth keeping ends up as a .md file. Specs, READMEs, decision docs, process notes — it's all markdown now, because it's the format the models write best and the format git tools handle natively.

That's great if everyone you work with lives in a terminal. It falls apart the moment you don't.

For technical colleagues, sharing a .md file is a solved problem: push it, open a PR, leave inline comments, done. For everyone else — designers, PMs, stakeholders, my own non-technical coworkers — a .md file is just a wall of asterisks and pound signs. So it gets converted. Into a Word doc, a PDF, a Google Doc. The moment that happens, you've lost the canonical source. Now there are two versions of the truth, feedback lands scattered across email threads and Slack messages instead of anchored to the text it's about, and someone has to manually reconcile all of it back into the original file — if anyone remembers to.

I hit this often enough that it qualified as a proper pain point: a document I actually cared about, feedback I actually needed, and no clean path between the two.

What I built

md.jholec.com is a hosted markdown review tool. The workflow is deliberately narrow:

  1. You upload a .md file. No account required.

  2. You get two links: a reviewer link to send around, and an owner link for yourself.

  3. Reviewers open the reviewer link and see a clean, rendered preview — proper typography, light or dark mode, works fine on a phone. No markdown knowledge required.

  4. They select any piece of text and leave a comment on it, the way you'd comment on a Figma frame or a Google Doc paragraph. Comments can carry emoji reactions and turn into reply threads. Everyone watching the document sees new comments appear live, no refresh.

  5. As the owner, you download the file whenever you want — and it comes back with every comment still attached, embedded invisibly so the file you get is still a clean, valid .md. Round-trip complete.

The one rule the whole design hangs off: reviewers annotate, they never edit. There's no shared editing surface to conflict over, no risk of someone "fixing" your doc mid-review. The source of truth stays exactly where it started, and feedback is just structured metadata anchored to specific words in it — anchored well enough that comments survive even if you edit the surrounding text later.

There's also a read-only link built specifically for AI agents: drop it into ChatGPT or Claude and the agent can read the document and every comment on it, which is a small thing but has already become the way I actually use my own tool day to day.

How it was built

This is the part that's actually about the course topic. The product went from a brainstorm to a live URL in under 48 hours, and to a complete v1 in five days (June 13–17), and I didn't write most of it — I orchestrated a team of thirteen specialized AI agents — among them a product owner, separate UX, frontend, backend and QA leads, frontend/backend/QA specialists, a UI-motion manager, a micro-tasker, an accessibility/HIG specialist, and a reviewer role — working through a spec → plan → execute pipeline with a QA gate at the end of every phase (typecheck, lint, unit tests, Playwright end-to-end on desktop and mobile, accessibility checks, a security pass).

The QA gate wasn't ceremony — it caught real bugs that a lone implementer, human or AI, would likely have shipped: an async syntax highlighter that crashed because the markdown renderer runs synchronously, a secure: true cookie flag that silently killed sessions on localhost, a button with 2.99:1 text contrast against a WCAG AA requirement. None of these show up in a build log. They show up when something is specifically told to go look for them.

The security side told a similarly honest story. Building my own auth model (capability tokens and per-document passwords, no Supabase Auth) meant a dedicated audit was worth running, and it found real issues before launch — including an unauthenticated token-minting endpoint that would issue tokens with arbitrary scopes, and personal access tokens that could authenticate against any document instead of the one they were issued for. Both got fixed before anything shipped publicly.

There's a less flattering version of the same lesson, too. At one point an agent committed an environment key straight into a file in the repo — the kind of slip that means rewriting git history to purge it, not just deleting a line. The takeaway stuck: agent output has to be treated as untrusted, secrets included, and that discipline is exactly what made the codebase safe to open-source later.

And none of it was free. Five days of orchestration at this depth burned through a genuinely absurd amount of model usage — the speed is real, but so is the bill, and it's worth being honest about where the leverage actually comes from.

Try it / self-host it

The live version is at md.jholec.com, and it's genuinely how I now share markdown with non-technical people at work.

On July 2nd I open-sourced it under AGPL-3.0: github.com/holecjakub/md.jholec.com-public. It's a mirror, generated automatically from the private repo — a script exports only the tracked files on every push to main, strips internal AI-team process docs and ops scripts, and a GitHub Action runs a secret-leak scan before anything reaches the public repo. So what you get is the working app, not the internal scaffolding I used to build it.

To self-host it:

  1. Fork or clone the public repo.

  2. Create a Supabase project and apply the included migrations (Postgres + Realtime, no Supabase Auth).

  3. Set three environment variables: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY.

  4. Deploy to Vercel (or any Node-compatible host) with the Root Directory set to apps/web.

The public README walks through the full setup end to end.

What I learned

Orchestrating an agent team is closer to managing a small engineering team than to prompting a chatbot. The plan → execute → QA-gate structure wasn't optional overhead, it was the thing that made thirteen agents produce something coherent instead of thirteen slightly different opinions about the same product.

AI doesn't remove the boring, load-bearing engineering decisions — it just makes it cheaper to actually do them properly. Deny-by-default row-level security, a hand-rolled realtime broadcast channel instead of the obvious Supabase default, capability tokens instead of a password in a URL fragment — none of that was automatic. Each one was a deliberate call, made because the tooling made it fast enough to actually implement the careful option instead of the quick one.

The pain point itself is a symptom of the same shift. Markdown became the lingua franca because it's what language models produce best. That means every team now has a growing pile of .md files and an uneven mix of people who can and can't engage with them natively. Building a bridge for that isn't a side project anymore — it's infrastructure for how AI-assisted teams are already working, whether they've noticed it yet or not.