Jan 9, 2026
Tech is enamoured with natural language these days, but not in a way that sparks my imagination and excitement. I don’t want to look into the cold, blinking mouth of a chatbot and try to exercise my artistic creativity through a simulated conversation.
Instead, I’ve always been interested in using code to celebrate what’s already rich and beautiful to me about language — the structures inherent in the technology, the miracle of understanding each other’s complicated sentences and fragments, how full of meaning and ritual the whole dance can be.
This pattern language interprets a limited set of natural language instructions to paint a graphical picture. Write the word “triangle” and out pops a triangle on the screen. Call it a “red triangle” and the picture adjusts accordingly.
In contrast to a typical graphics programming library, the tool is heavy on constraints. You can only use six colors and a handful of shapes. But when we’ve stripped language down to this set of parameters and we start to play with them, interesting questions start to puddle out, like: what do color words mean?
Colors
In the first iteration, any of the approximately 150 CSS named colors were recognised, so you could have a “rebeccapurple square” or a “palegoldenrod triangle". Colors written in the text box were plugged straight into ctx.fillStyle.
I tend to have a soft spot for playing with the raw materials of the web, so I was happy playing with this for a while. But with some feedback from my coworkers, I decided to try limiting the color palette and was really delighted by the results.
The current version only allows for six named colors: red, orange, yellow, green, blue, and purple — the primary and secondary colors on the color wheel. This gave me an opportunity to decide what exactly “red” or “blue” should mean.
Instead of using hard and raw values like #ff0000 for “red”, maybe “red” could be a variable that had a handful of possible values. It could mean #ea3546 or #e58383 or #c44536, which are the values of “red” from the palettes currently in the tool.
Viewing the same shapes and colors through different palettes suddenly casts a completely different mood and feel over the picture.
Layout
The layout engine is currently very straightforward. It lays every shape or group of shapes in a vertical line from top to bottom, reflecting the order of the text. (A fun side effect of this is that while the text primarily serves as the code or instruction for the graphic, it also happens to function as the corresponding alt text!)
Adding a count will generate copies of the shape and arrange them in a circle, applying rotation.
Specifying “along edge” will create a border with that color and shape.
More recently, I began loosening the reins to play with a tiny bit of randomness: use the keyword “anywhere” to take a shape out of the vertical layout and place it randomly on the canvas. It's still so simple, but the effect kind of thrilled me. Having stared at the strict vertical arrangement of one to three shape patterns for so long, just this tiny bit of randomness and juxtaposition felt like a reward.
This layout system would be pretty adaptable to a landscape orientation — just lay the shapes out in a horizontal line instead of a vertical one.
I think the next challenge here would be to figure out if there’s a systematic way to allow for more flexibility in composition. I have plans for a little bit of variation in size (“small” and “big” keywords), but how could you get different layouts and combinations of layouts? Could you arrange shapes diagonally, in a repeating pattern background, overlay patterns on top of each other, assemble complex column and row layouts?
The hard part is always pulling back from seeing the possibilities and deciding what the useful boundaries of the system should be.
Speaking of the system…
How does it work?
In my first iteration, I used some pretty rough code to “parse” the text, line by line, identifying recognisable words and using those to build the shapes on the canvas.
After I hit a wall with that, I went back to write a proper parser, using what I had learned when writing Coem but trying to follow a different tutorial this time. This isn’t a traditional programming language, but materials like these, combined with some rusty knowledge from syntactic linguistics classes, help me understand how programming languages work and how I can use that to build something useful for my purposes.
The parser first runs through the text to build a stream of tokens. Then, it creates meaningful groups out of those tokens, building an object for each pattern, modelled after noun phrases in language.
The text “a slowly rotating red square” becomes:
[
{
"type": "det",
"value": "a"
},
{
"type": "vp",
"vp": {
"adv": "slowly",
"verb": "rotating"
}
},
{
"type": "adj",
"value": "red"
},
{
"type": "noun",
"value": "square"
}
]
That’s the system for now! There’s so much that I feel like I could play with, but I’m excited to put it down and share what I have.
A list of possible things I have written down to think about:
-
Multiple palette options- Maybe option to add your own palette?
“anywhere” keyword for random placement and rotation — introducing a tiny bit of randomness-
“small”/“big” keywords for a little bit of control over size
- with slider for control over what that means!
- Experimenting with other movement/animation verbs
- Experimenting with a wider variety of layouts and more flexibility in composition
- Debug mode, or a way to see the parse tree
- Export image with text overlaid/at the side
- Option for landscape orientation instead of portrait orientation
- Export SVG