A text to schematic diagram starts as a few sentences about which boxes share a row, and only then becomes a block-beta grid. You are encoding a layout you already described, not asking a flowchart to invent one.
I keep this separate from the “how do I click a schematic together” chore. The creator page can walk the buttons. Here the work is the translation: a paragraph a teammate would say out loud, then the rows that paragraph demanded. If the paragraph doesn’t mention rows, you don’t have a schematic yet. You have a wish.
Sentences first, or the grid is fan fiction
I make people write three to six sentences before they touch syntax. Each sentence should be boring enough to argue with. “The browser is alone on the top row.” “The web app, the API, and the worker share the middle row.” “The database is alone on the bottom row, and the worker reaches it.” If a sentence uses “somehow” or “and other stuff,” I send it back. Somehow is how a cache appears in the picture and then in a design doc as if we’d agreed.
The sentences are the spec. The diagram is a rendering of the spec. That order matters because block diagrams look official. A box on a grid feels like an architecture decision even when you typed it in four minutes. I have had a sentence like “we might put Redis next to Postgres” survive into a quarter’s plan because the box was already in the figure. The sentence had “might.” The figure didn’t. Kill the box or delete the “might.” Don’t let the grid promote a guess.
This is also why I don’t start in the generator. A model will give you a grid that looks like the sentences you didn’t write. You’ll nod, because the boxes say Web and API and Database, which are words you use. Then you’ll discover the worker is on the wrong row and the arrow skips a tier you actually have. Write the sentences on purpose. Generate later, if at all, from those sentences, not from the product name.
The paragraph, then the rows it became
Here’s a paragraph I want turned into a schematic, written the way a teammate talks.
“The browser sits on a row by itself, full width. Under it, one row holds the web app, the public API, and a worker. The database sits alone on the last row, full width. The browser talks only to the API. The web app talks to the API. Both the API and the worker talk to the database. The worker does not talk to the browser.”
Count the claims. Three rows. The middle row has three boxes. Two boxes span the full width. Four arrows, and one explicit non-arrow. The non-arrow is the one people drop, and then a later edit adds browser --> worker because the layout engine in their head likes diagonals. There is no layout engine in this diagram that will save you. You place the cells. If the arrow isn’t in the paragraph, it isn’t in the file.
The grid that matches that paragraph:
block-beta
columns 3
browser["Browser"]:3
web["Web"] api["API"] worker["Worker"]
db["Database"]:3
browser --> api
web --> api
api --> db
worker --> dbcolumns 3 is the middle row’s width, not a suggestion. The browser spans 3, so it occupies the whole first row. Web, API, and worker are one cell each, so they fill row two and nothing wraps. The database spans 3 and takes row three. If you forget :3 on the browser, it becomes one cell of three and the web app jumps up beside it. The paragraph said the browser is alone. The file lied. I check spans by adding them. Row one is 3. Row two is 1+1+1. Row three is 3. Anything else is a wrap wearing a confident label.
The arrows repeat claims the stack already hints at, and I still want them, because “above talks to below” is too vague when the middle row has three neighbors. Browser to API, not browser to web. That’s the claim that stops a teammate from wiring the page straight at the database “just for this one query.” The missing arrow is the feature. I don’t draw browser to worker. I don’t draw web to database. Absence is the schematic doing its job.
The block diagram reference documents columns, spans, and space when you need a hole in a row. I’m using the smallest slice of that here. If your row needs a gap, space is a cell you can count. A missing cell is not a gap. It’s a wrap, and the database will sit next to the worker while you swear you indented it.
A second paragraph, because one picture becomes a template too fast
People copy the three-tier stack onto every system. Nightly billing is not that stack. Here’s the paragraph.
“Four rows, one box each. Scheduler on top. Worker under it. Ledger under the worker. Warehouse on the bottom. The scheduler only starts the worker. The worker writes the ledger and also writes the warehouse. The ledger does not talk to the warehouse. Nothing in this picture is a browser.”
No middle row of peers. No span. A single column, because the paragraph is a stack of starters and writers, and a horizontal arrangement would imply the ledger and the warehouse are the same tier. They aren’t. The worker talks to both, which is an arrow claim, not a reason to put ledger and warehouse side by side. Side by side would say “these are neighbors in a tier.” The sentences say the worker has two downstreams and they don’t talk. A column plus two arrows says that. A row of two boxes would say something else, and I’d have to fight the picture in review.
block-beta
columns 1
sched["Scheduler"]
worker["Worker"]
ledger["Ledger"]
warehouse["Warehouse"]
sched --> worker
worker --> ledger
worker --> warehouseOne column means I cannot accidentally place the warehouse beside the scheduler. Position is list position. If someone inserts a cache, they insert a line, and they have to decide whether it sits above the ledger or below it. That decision is the design. A flowchart would have parked the cache wherever the layout felt room, and we would have nodded. I don’t want that nod.
Look at what I refused to draw. No arrow from ledger to warehouse. The paragraph forbade it. If finance later says the warehouse is fed by the ledger, not by the worker, the paragraph changes and then the arrows change. I don’t “add the arrow so the picture looks connected.” Connected is how you specify a pipeline you don’t have. Our bug last spring was a job that wrote the warehouse from the worker and also, sometimes, from a backfill that read the ledger. Two writers. The schematic with one arrow from worker to warehouse made the backfill visible by its absence, once we compared the picture to the cron list. The picture was useful because it was incomplete on purpose.
Encoding rules I don’t want to rediscover
The id and the label are different. api["API"] keeps the id api when the label becomes “Public API.” Arrows point at ids. If you rename the id and not the arrow, the diagram breaks, and the break is the good kind. It tells you the sentence and the file drifted. A label-only rename should not move the box. With columns 1, the box moves when you move the line. With a multi-column row, the box moves when you change its place in the row or its span. I move lines. I don’t drag.
Labels stay short. “Worker that settles last night’s invoices except refunds” is a paragraph you owed the doc, not a cell. The cell says Worker. The paragraph under the figure keeps the exception. I put the exception in the figure once, the cell grew, the row wrapped, and the database sat in the wrong tier. The preview didn’t error. The architecture did.
Quote a label that has parentheses. web["Web (edge)"] is legal. web[Web (edge)] is how the preview goes blank and someone decides block diagrams are broken. They aren’t. The parentheses closed the shape early. Same rule as flowcharts, easier to forget because the grid looks so plain.
Don’t use end as a block id. That word closes a nested block. If a tier is called End user, the id can be client and the label can say whatever you need. I learned this by naming a block end and watching the rest of the file disappear. The error feels like a layout bug. It is a keyword bug.
Spans plus spaces equal columns on every row. I add them with a finger on the screen. If they don’t add up, I don’t look at arrows yet. Arrows on a wrapped grid point at the right ids and still depict the wrong building. Fix the arithmetic. The system layers template is a wider grid if one column is too plain for the overview you’re actually trying to match. Start from it when your sentences already talk about layers. Don’t start from it when your sentences talk about a nightly job. You’ll spend the hour deleting a tier you never had.
When the sentences are still mush
Some paragraphs aren’t ready, and the diagram will not discipline them. “We have a platform.” No rows. “It’s microservices.” No cast. “Kind of like the last system but the queue is different.” That’s a diff against a picture you haven’t opened. I send those back for nouns.
A workable rewrite is forced and a bit childish. Name the top row in one sentence. Name who shares the next row. Name who is not allowed to call whom. If you can’t say the forbidden call, you don’t know the schematic, you know the org chart. Org charts are allowed. They aren’t this picture. Put teams in a different figure, or you’ll draw a box called Platform Team and an arrow to Production, and an executive will ask what the arrow deploys. You will not have an answer. I didn’t, in 2019, and I still remember the silence.
The architecture guide is the wider map of which Mermaid type belongs to which architecture question. A C4-style picture and a block grid are not interchangeable. I use the block grid when the row is the meaning. I use something else when the meaning is “this system is outside our boundary.” If you need cloud icons and a vendor’s product names, the AWS-shaped diagrams discussion is the honest version of what Mermaid will and won’t imitate. I won’t pretend a block labeled S3 is a Visio stencil with the official logo. It’s a box with letters. If the letters are enough, good. If the logo is the point, you’re in a different tool.
Generating from the sentences, and not from the vibe
The block generator is useful after the paragraph exists. Paste the sentences. Tell it block-beta, the column count, which ids span, and which arrows are forbidden. “Use columns 3. Row one is browser spanning 3. Row two is web, api, worker. Row three is db spanning 3. Arrows only from browser to api, web to api, api to db, worker to db. Do not add a cache.” That prompt is the paragraph plus the arithmetic. A prompt that says “schematic of our platform” will add the cache, a queue, and a box called Users. You’ll spend the next use deleting them, if you have a use left.
Free AI is five uses total, not five per schematic. A one-column stack often lands on the first try. A spanned row often needs a second try because the first draft forgets :3 and wraps. Spend the second use on the spans. Change a label with your hands. Hand edits don’t spend a use, and block source is short enough that a label change is one quoted string.
If the draft comes back as a flowchart, it ignored you. Don’t accept a flowchart and call it a schematic because the boxes are in a vertical line today. Tomorrow’s edit will reflow them. Send it back with the keyword block-beta and the column count, or delete it and type the ten lines yourself. Ten lines is faster than a third prompt that says “no, a real schematic.” I have paid that third prompt. I was annoyed at myself, not at the model. The model did what vague requests do.
The block examples are worth skimming when you want to see spans and spaces in more than one layout. They’re examples, not your rows. Copy the arithmetic, replace the nouns. The schematic creator and the block generator writeup cover the tool path. Use them when the sentences are done and you’re fighting the editor. Use this page when you’re still trying to make the paragraph say a row out loud.
What I check before I paste the figure into a doc
I read the sentences with the figure covered. Then I uncover it and see if every sentence has a cell or an arrow, and if every arrow has a sentence. Extra arrows are defects. Missing rows are defects. A box that only exists because the template had one is a defect even when the template is ours.
I also check the forbidden call. In the first figure, browser does not reach the database. In the second, ledger does not reach the warehouse. If I can’t find the absence, the figure is decoration. Decoration gets screenshotted into a slide and then argued as if it were a constraint. I’d rather have a slightly ugly grid that makes one forbidden arrow obvious.
Then I leave the sentences under the figure. The diagram without the paragraph is how “might” returns. A reader should be able to disagree with a sentence without redrawing. “The worker should not write the warehouse” is a review comment. “Move this box” is a layout comment. I want the first kind.
If your sentences are ready and you want the grid in front of you, open the editor and type block-beta before you type a single box. Put the column count on the next line. Then make the rows add up. The schematic is the arithmetic. The labels are just how you remember which sentence each cell came from.
Related posts
Frequently asked questions
How is this different from the schematic creator post?
That post is how to choose rows. This one starts from prose you already wrote and turns the sentences into blocks.
Can AI do the encoding?
Yes, if your prompt says block-beta, gives the column count, and lists the labels. A prompt that says 'architecture' often comes back as a flowchart.
What if the host cannot render block-beta?
Export a picture from a current editor, or redraw the stack as a top-down flowchart. The sentences are still the spec.