A grid of modules is easier to trust when you can see it. Today you render the symbol as text - dark and light blocks with a light quiet-zone border - so the whole chapter's work becomes visible.
Render the grid as text with a quiet zone around it.
Every chapter ends on something you can look at, and a QR grid is the most literal case. Rendering is a straightforward double loop: dark modules print as a filled block (two characters wide reads squarer in a terminal), light modules as blanks. The one thing you must add is the quiet zone - a border of light modules, at least four wide, around the whole symbol. A scanner needs that margin to separate the code from whatever surrounds it; without it, even a perfect grid may not scan.
With a 4-module quiet zone, the 21-module Version 1 symbol renders as a 29x29 field, and the three finder patterns jump out as the familiar nested squares. What you are looking at right now is the unmasked symbol - correct in structure but not yet optimized for scanning, and still missing its format bits. The last chapter applies masking to even out the data pattern, chooses the best mask by scoring, writes the format information, and finally produces a symbol a real scanner reads.
// Two chars per module reads squarer in a terminal. Wrap with// `quiet` light modules on every side.for r := -quiet; r < size+quiet; r++ {for c := -quiet; c < size+quiet; c++ {if g.dark(r, c) { print("##") } else { print(" ") }}println()}