跳到正文
DEV Community· SURAJ NANDAN·· 3 小時前AI 評分54

我為何打造 Whiteboard.ai,作為系統設計練習白板

Why I built a whiteboard for practising system design

AI 導讀

作者打造 Whiteboard.ai,作為可即時協作的系統設計白板,讓 AI 審閲架構圖。畫布會轉成帶類型的圖,由瀏覽器執行九項確定性規則,再交由 Claude 按五個維度撰寫結構化評審;更新寫入 Postgres 後才顯示「Saved」。AI 評測已設計 15 個測試白板、植入 16 個缺陷,通過門檻為 12/15,但尚未以真實 API key 執行,提示詞的檢出率亦未測量;工具尚未部署。

正文

System-design interviews ask you to draw boxes and defend them. Most of us practise on tools that were never built for that, and feedback depends on finding a human who'll read your diagram closely.

So I built Whiteboard.ai: a real-time collaborative system-design whiteboard where an AI reviews your architecture diagram like a senior engineer. This post covers what's in it and, more usefully, the decisions underneath. I'll also be upfront about its limits, which are real.

The problem

A generic whiteboard has no idea that a box labelled "Postgres" is a single point of failure. And interviewers running a live round juggle a canvas, a timer, a question and private notes in four different places.

Building it properly turns out to be mostly not about the canvas. It's about:

  • real-time sync that survives a crashed server,
  • permissions that hold on the WebSocket as well as the REST API,
  • an AI reviewer whose bill and prompt-injection exposure are bounded,
  • and a private mode where the server genuinely can't read the board.

How a board works

Each board is a Yjs document. Shapes (rectangles, ellipses, text, stickies, freehand, arrows that bind to shapes, plus twelve typed system-design components) live in a shared map, and every read and write is validated with zod.

For sync, I wrote my own server rather than using a hosted service: Fastify and ws on one port. I chose that because rooms, backpressure, persistence and revocation are the product. If those are someone else's black box, I can't make promises about them.

"Saved" is a promise

This is the decision I'm proudest of. Live updates broadcast immediately, so collaboration feels instant. But the "Saved" indicator only appears after the update is committed to Postgres, and it carries the exact state that's now durable.

client edit → server room → broadcast to others immediately
                         → write-ahead log in Postgres (within ~50 ms)
                         → only now: tell the client "Saved"

The consequence: an edit that shows Saved survives a hard kill -9 of the server. An edit that doesn't show Saved is still in the browser and re-sends when the connection returns. The label means what it says.

The review pipeline: rules first, AI second

The AI never looks at a picture. The canvas is converted into a typed graph, and then:

  1. Nine deterministic rules run in the browser, in about 17 ms for a 2,000-shape board. They catch things like a database as a single point of failure, a client talking straight to a database, synchronous cycles, and a queue without a dead-letter queue.
  2. Only then does Claude write a structured review: scores on five dimensions, with findings pinned to specific shape IDs.
  3. The response is validated and repaired server-side. If the model invents a reference to a shape that doesn't exist, it's dropped.

Why this order? Cheap, deterministic checks catch the obvious problems reliably, so the model can spend its effort on the judgement calls. And because the model sees data with no tools to call, there's nothing for a malicious board label to hijack.

Private data and permissions

A few details that taught me how much "permissions" hides:

  • Interview notes and hidden hints are never in the shared document. The candidate is an editor and could rewrite anything inside it. Secrets live only behind role-checked REST routes, and a test records every frame a candidate's socket receives and asserts that no secret appears.
  • Private rooms are end-to-end encrypted. A 256-bit AES-GCM key is generated in the browser and kept in the URL fragment; the server stores and relays ciphertext only.
  • Spend is bounded in code. Quota is checked and reserved in one transaction under a per-user advisory lock, so two parallel requests at quota minus one produce one success and one rejection.

Bugs that taught me things

Real ones from the project's log:

  • Viewers sat on "Saving…" forever. The store stamped a schema version into the document on creation, an update the server rightly rejects from viewers. Fix: stamp it at the first local edit.
  • A removed member could still open the board offline from IndexedDB. Fix: revocation now wipes the local copy, not just the live socket.
  • Analytics would have leaked an encryption key. Page-analytics recorded full URLs including the fragment, which is where a private board's key lives. Fix: a hook strips fragments from every event, with a test.
  • A candidate who joined via share link saw nothing. Found by a browser test, since candidates normally join by link.

Honest limits

I'll repeat what the case study says, because it matters:

  • It is not deployed. It runs locally against a dev Supabase project, so there's no live demo. Load numbers come from one Mac and haven't been re-measured on a staging host.
  • The AI review eval has never been run against a real API key. It's written (15 fixture boards, 16 planted flaws, a 12/15 pass bar), but the prompt's catch rate is unmeasured.
  • Payments are tested with a scripted provider, not yet in real test mode.
  • Private boards can't rotate keys. A removed member stops syncing but may keep the key and old content.
  • The design check only understands palette shapes. Boards drawn with plain rectangles get few findings.

What I'd tell someone building something similar

  1. Decide what you'll promise, then write a test that tries to break each promise.
  2. Put cheap deterministic checks in front of expensive AI ones.
  3. Treat the AI as an untrusted component with a budget.
  4. Write down the limits while you still remember them.

Twelve questions to ask of any system-design diagram

Use these on your own diagrams, or on a friend's. They're the sort of thing the deterministic rules in Whiteboard.ai check automatically, and every one can also be asked by a person.

  1. Where's the single point of failure? What happens if each box goes down?
  2. Where does data live, and who owns it? One writer, or many?
  3. What's synchronous and what's asynchronous? Are there synchronous call cycles?
  4. What happens at 10x the load? Which box saturates first?
  5. What happens when a downstream service is slow, not down? (Slow is often worse than down.)
  6. Is a client talking directly to a database? If so, where are the access rules enforced?
  7. Do queues have a dead-letter path for messages that keep failing?
  8. Where are the retries, and are they idempotent? What happens if a message is delivered twice?
  9. How do you know it's healthy? What metrics and alerts exist?
  10. What's cached, and how does stale data get invalidated?
  11. How does it deploy and roll back?
  12. What's the data model's biggest assumption that might not hold?

Print this list. Asking them out loud, even to yourself, is most of the skill.

How to practise with a partner

A simple 45-minute format:

Minutes Activity
0–5 Partner reads the prompt ("design a URL shortener"). You ask clarifying questions.
5–10 State requirements and rough numbers (users, reads vs writes).
10–25 Draw the design. Narrate every box.
25–40 Partner pokes at failure modes using the twelve questions.
40–45 Both note what to study.

Swap roles next time. Being the interviewer teaches as much as being the candidate.

A worked example

Prompt: a URL shortener.

  • Core: a write path (create short code) and a read path (redirect).
  • Data: a table mapping code → URL.
  • Scale thought: reads vastly outnumber writes, so cache hot codes.
  • Failure thought: if the cache is down, reads fall back to the database. Can the database cope? If not, add a rate limit.
  • A question to ask yourself: how do you generate codes without collisions? (Counter-based, random with retry, or pre-generated pool, each with trade-offs.)

Even this tiny walkthrough uses five of the twelve questions.

Why drawing failure arrows matters

Diagrams of the happy path are easy and nearly useless. The valuable part is what happens when something breaks. A good habit: use a second colour (red) for failure paths, and don't consider the diagram finished until every important box has a red arrow out of it.

What an AI reviewer can and can't do

A tool can reliably catch pattern problems: a database with no replica, a queue with no dead-letter path. It can't know your product's real requirements, your team's skills or your budget. Treat automated feedback as a second pair of eyes that needs your judgement, not as a verdict.

Key takeaways from day 12

What's your go-to first question when you start a system design? And if you've built real-time sync before, what did you wish you'd known?

來源:DEV Community · dev.to