ASCII Diagrams: Drawing Boxes and Arrows With Nothing but Text
You can draw a diagram in plain text with three characters: + for corners, - for horizontal edges and | for vertical edges. Put it in a fenced code block, keep it in a monospace font, and it works in a README, a code comment or a commit message with no renderer at all.
Quick answer
A box is a rectangle of +, - and |. An arrow is a line of - or | that ends in >, <, v or ^. If you control the font, Unicode box-drawing characters such as ┌, ─ and │ look cleaner. ASCII diagrams stay readable in terminals, diff cleanly in version control and need no external tools, which is why they keep turning up in design docs and RFCs.
Step-by-step
1. Draw a box
Write the top edge, the label row and the bottom edge. Every line must have the same number of characters.
+----------+
| Server |
+----------+For a softer look, swap the corners for . and ':
.----------.
| Server |
'----------'2. Add arrows and connectors
Horizontal links use -, vertical links use |, and the arrowhead goes on the end that receives the data. A two-way link puts a head on both ends, like <------->.
+--------+ +--------+
| Client |--------->| Server |
+--------+ +--------+
|
v
+--------+
| DB |
+--------+Notice that the | under "Server" sits in the same column as the - of its box. Aligning columns is the whole craft, and it's easy to get wrong.
3. Label boxes and connections
Keep labels to one to three words per box, name each component the same way everywhere, and label the connections with the protocol or data type, such as HTTP or events. If a box needs a paragraph, move that text under the diagram.
4. Nest boxes for layers
An outer box is a layer, and the boxes inside it are components. The same guide suggests = for the horizontal edges of outer boxes, so containers read differently from components.
+=====================+
| Application |
| +------+ +------+ |
| | API | | Jobs | |
| +------+ +------+ |
+=====================+Every line here is exactly 23 characters wide. Run that check on any nested diagram: the right edge of each line has to end in the same column.
5. Switch to Unicode box-drawing characters
The Box Drawing block runs from U+2500 to U+257F, 128 code points, and it exists for compatibility with legacy graphics standards. The families include light lines, heavy lines, double lines, rounded corners and dashed lines:
- Light:
─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ - Heavy:
━ ┃ ┏ ┓ ┗ ┛ - Double:
═ ║ ╔ ╗ ╚ ╝ ╠ ╣ ╦ ╩ ╬ - Rounded corners:
╭ ╮ ╯ ╰
The same box and arrow, redrawn:
┌────────┐ ┌────────┐
│ Client │─────────>│ Server │
└────────┘ └────────┘Strictly speaking, this isn't ASCII anymore, since these characters sit outside the 7-bit set. The file is still plain text, though, and any Unicode-aware editor will show it.
6. Draw trees and branches
Two more shapes are worth knowing. A directory tree uses ├──, └── and │, and the tree command prints exactly that shape for any folder, so you rarely need to type one by hand:
some-directory/
├── Dir_A
│ └── File_C
├── File_A
└── File_BFor a git-style branch diagram, rounded corners `╭ ╮ ╯ ╰` curve a branch away from the main line, and commit markers such as `●` or `o` sit on the lines. Letters like A, B and C work just as well when you need to refer to a commit in the text.
A habit that saves time: build the diagram in a plain-text editor, one row at a time, and check the columns before you paste it into the document. Fixing a misaligned row there is a one-line edit. Fixing it inside a rendered page means hunting for the cause first.
Common problems and fixes
Columns drift out of alignment
Box-drawing characters are meant to join their neighbors, so they typically only work well in a monospace font. In a proportional font, a | is narrower than a letter and every row ends in a different place. Use a code block, or a monospace font in your editor, and count characters when a row looks off.
Glyph widths and fallback fonts
Width can vary by context. U+2500 may be displayed wide or narrow in East Asian text. A blog post that tested these glyphs also found that heavy `━` and dashed `┉` can be wider than a space on some systems, and that a missing glyph makes the system substitute a fallback font with different widths. Its practical advice: lean on ─, ━ and │ for the most predictable alignment, and test in the place readers will actually see the diagram.
Mixed line characters
Pick one vertical character and stay with it. Mixing | and │ in the same box looks uneven, because the two glyphs differ in weight and sometimes in width.
The diagram collapses outside a code block
Markdown reflows ordinary paragraphs and strips repeated spaces. Wrap the diagram in a fenced code block, with three backticks above and below, so the spacing survives. The CommonMark spec defines how those fences behave.
When to skip ASCII
ASCII fits best when the diagram must live in version-controlled plain text and is simple enough for characters to carry the structure. For many node types, styling or frequent edits, a text-based tool is easier to maintain. We cover Mermaid diagrams in Markdown files and other diagram-as-code tools separately, and they need a renderer, which a README viewed in a terminal does not have.
Doing this with Carets
A hand-aligned diagram is all column positions, which makes it plain text work. Carets is a native notes and code editor for iPhone, iPad and Mac that keeps Markdown, plain text and code in one place, so a diagram sits in the same file as the notes or README it explains. Because your files stay plain text, the diagram stays portable: it opens in any other editor and diffs cleanly in Git. You can organize the files into projects and tags, and keep a scratch file for sketching a layout before it goes into a README.
Download Carets on the App Store for iPhone, iPad and Mac.
Frequently Asked Questions
Which characters do I need for a basic ASCII box?
Plus signs for corners, hyphens for horizontal edges and pipes for vertical edges. Add >, <, v and ^ for arrowheads.
Why does my diagram break in some places?
Usually the font. Proportional fonts, wider glyphs and fallback fonts all shift columns. Use a monospace font, put the diagram in a code block and check that each row has the same number of characters.
Should I use ASCII or Unicode box-drawing characters?
Plain ASCII is the safest because every font has those characters. Unicode box-drawing characters look cleaner, but they depend on the font and the viewer handling their widths correctly.
When should I use Mermaid instead?
When the diagram has many node types, needs styling, or will change often. Mermaid is still text, but it needs a renderer to turn into a picture.