Birthday crosswords made of private jokes
Five arrow-word grids for Lo's birthday, built from 157 words only his friends would get. Notes from writing my own generator, and why every grid still had to be rewritten by hand.
- grids
- 5
- own words
- 157
- filler words
- ~62,000
- grid shapes
- 7,358
- code
- ~13.6k lines
- A5 booklet

It was Lo’s birthday, and he loves solving puzzles. So I thought: why not make him a crossword of his own, full of private jokes and the names of people we know?
I assumed it would be easy. I remembered seeing plenty of crossword generators online, the kind where you type a few words and get a grid back. Little did I know. What I wanted was not a crossword, not everything about it can be automated, and the part that can’t turned out to be the fun part.
Arrow words are not crosswords
The puzzle Lo solves is the mots fléchés, the arrow-word grid. There is no numbered list of clues beside it. Each clue is written inside a cell of the grid itself, with a small arrow pointing to where the answer goes. It is the common format in French-speaking countries, much less so in the United States, and that is why I found so little written about how to generate one.
Why the grid itself is the hard part
I thought the difficulty would be finding words that cross. It is, but there is a problem before that one. In a crossword, the clues sit in a list beside the grid, so the grid only has to hold letters. In an arrow word, every clue takes up a cell, and that cell has to touch the first letter of its word.
That one rule decides most of the shape. Try it:
This sheet can be filled.
Long words have to be broken, and the only tool is another clue cell. Each one costs a letter, has to point at a word, and must not strand the letters around it. 5 more cells, and this sheet can be filled. Now press any cell and watch how fast it stops working.
- Words without a clue cell
- 0
- Words over 6 letters
- 0
- Clue cells pointing at nothing
- 0
- Letters left in no word
- 0
A crossword would spend no cells on clues. This sheet spends 11 of 48.
Press a cell to switch it between letter and clue. Arrow keys move around the sheet.
Three things follow, and each of them cost me an evening to understand.
The margin is not yours. A word that starts against the top or left edge has nowhere to put its clue. So the first row and the first column alternate: clue, letter, clue, letter. Every clue cell there carries two clues and points two ways, often around a corner.
Every clue cell has to earn its place. It costs a letter, it holds two clues at most, and if it points at nothing it is a hole in the page. Placing one to fix a word usually breaks the word next to it.
So you cannot draw a shape and hope. A shape that obeys all of this can still be impossible to fill, because its words are too long or cross too tightly. That is why I stopped inventing shapes and started collecting them from grids that people had already solved.
I did learn a few things along the way. The people who make these grids are called verbicrucistes. The people who solve them are cruciverbistes, which is the word I had been using for both. There are companies whose whole business is producing grids, including a French one that supplies most of the websites offering free puzzles [name it?]. And the really hard grids, the ones with a reputation, are still made by hand.
The format is also having a moment. What gave me the idea in the first place was an Instagram ad for Grillé, a brand started by two women, Louise and Dior, who decided to publish their own booklets. Their clues mix pop references, humour and traps, a long way from the definitions I remembered from my grandparents’ magazines. Their site says they have sold more than 50,000 booklets. One magazine filed them under holiday pastimes.

So the plan became: the same thing, for an audience of one.
Thirty words is not enough
I started with the dictionary. I built a small tool where I could type a word and a simple definition: a private joke, a nickname, a place, the name of someone we both know.
I ran out at around thirty. That is the first thing nobody tells you. Thirty words feels like a lot when you are writing them down, and it is nowhere near enough. A grid has dozens of slots of very specific lengths, and the words have to cross each other. You need at least a hundred before the grids start to make sense and still feel personal.
Two things got me there.
Asking for more ideas. I fed my list to Claude, ChatGPT and Gemini and asked what else could belong on it. They don’t know Lo, but they are good at noticing what a list implies: if these three words are here, what about the fourth?
Playing other people’s grids. Solving arrow words on puzzle sites gave me shapes, and it gave me material. You can take an existing word with its definition and bend it to your own story. The word stays. The clue becomes about him.
I ended up with 157 words.
Length turned out to matter as much as number. A grid is built mostly from short words, and the things I wanted to say about Lo were rarely two letters long.
- Slots in the five finished grids (228)
- My own words (157)
Letters in the word
Show the numbers
| Letters | Slots in the grids | My own words |
|---|---|---|
| 2 | 45 | 15 |
| 3 | 64 | 37 |
| 4 | 54 | 44 |
| 5 | 25 | 27 |
| 6 | 16 | 19 |
| 7 | 13 | 9 |
| 8 | 10 | 4 |
| 9 | 1 | 1 |
| 10 | 0 | 1 |
Almost half the slots in my finished grids hold a word of two or three letters. Only a third of my own words were that short. So part of the list had to be written for the grid, not for the joke: initials, nicknames, the two letters of a name.
I won’t give the answers here, because they are his. But the clues give the flavour. Dort en soirée: falls asleep at parties. Pour taguer un pote: for tagging a friend. Tournée au pub: a round at the pub. OMG à Liège: what you say instead, in Liège. Each of those is one person, or one evening, that everyone around the table would recognise.
[Add one or two with their answer and the story behind them, if you are happy to share.]
The words that fill the gaps
A grid made only of private jokes is a list, not a puzzle. Most of the words in a real grid are ordinary ones, and they need ordinary clues.
So I loaded existing dictionaries to act as fillers: about 35,000 words that already came with crossword-style definitions, and about 27,000 more from Lexique, a database of French words. My own 157 sit in a separate dictionary that the solver treats differently.
I also needed shapes. Where the clue cells go decides whether a grid can be filled at all, and published grids are designed by people who know that. I collected 7,358 distinct shapes from real grids and kept only the pattern of each one: this cell is a clue, that cell is a letter.
A solver, in one Saturday
Most of the code was written in a single day. I started on a Saturday afternoon and stopped around midnight.
I built it with Claude. I also kept Gemini and ChatGPT open the whole time, not to write code but to challenge the plans I was making. Before each big step I would hand them the plan and ask what was wrong with it. They disagreed with each other often enough to be useful.
The order of operations is simple to describe:
- Pick a shape whose slot lengths suit my words.
- Place as many of my words as possible.
- Fill everything else from the big dictionaries.
- Do it again with another shape and another random seed, and keep the best attempt.
The first solver was greedy. It always filled the most constrained slot next, chose the word that left the most options for the slots crossing it, and refused any word that would leave a crossing with nothing to put in it. It never went back on a decision. When it got stuck, it started over.
That got further than I expected, and then it stopped improving. The next few hours were a sequence of small discoveries.
Short attempts beat one long one. Cutting the time budget into two-second attempts and keeping the fullest grid filled 22 slots out of 31, against 18 for a single long run.
Local search does not work here. I tried a finisher that repairs conflicts one at a time. It plateaued at around fifteen broken slots and never converged, however long it ran. I removed it.
My shape scoring was backwards. The score I used to pick a shape turned out to be negatively correlated with how well that shape actually filled. I had been choosing the worst candidates with confidence. After recalibrating it, the generator lands on shapes that fill at 72 to 81 percent.
A real constraint solver changes the result. Late in the evening I tried OR-Tools, Google’s constraint solver, behind a switch. It beat the greedy solver on five shapes out of six. On a real run with my own dictionary it placed 16 of my words where the greedy one had placed 7.
Sixteen private jokes in one grid, instead of seven. That was the number I had been chasing all day.
I ran both solvers again for this article, with the dictionary as it is today. The gap is smaller now that the word list has grown, and it is still there.
- My words
- Filler words
- Clue cells
- Left empty
- Blocked
Greedy solver
11 of my words26 of 35 words filled
Constraint solver
15 of my words30 of 35 words filled

Not a single grid survived untouched
Here is what I did not expect. There was not one grid I generated that I didn’t rework by hand.
I deleted words. I added others. And more than anything, I had fun taking a word the solver had placed, a perfectly ordinary one, and writing a new definition for it that was funnier than the one in the dictionary. A filler word with the right clue becomes a private joke too.
Across the five finished grids, 68 of the 161 ordinary words carry a clue that is not the dictionary’s. A few were only shortened to fit the cell. Most were rewritten.
- DÉRAPAGEDictionary clue: Glissade à skisPrinted clue: Micro resté ouvertA skid on skis, turned into a microphone left on.
- DÉÇUEDictionary clue: Pas satisfaite de ce qu'elle a obtenuPrinted clue: Mais pas étonnéeDisappointed. But not surprised.
- ATDictionary clue: Symbole chimique de l'astatePrinted clue: Pour taguer un poteThe chemical symbol for astatine, turned into what you type to tag a friend.
- EXPERTDictionary clue: Référence en la matièrePrinted clue: De MiamiAn authority on the subject, turned into a television series.
- IADictionary clue: Intelligence artificiellePrinted clue: GPTThe one clue that got shorter.
So the generator was never going to be the product. The editor was.

- Force a word in, repair around it. Put the word where I want it and let the solver rebuild only the neighbourhood.
- Lock and re-roll. Keep the words I like and regenerate everything else.
- See before placing. Hovering a candidate previews it on the grid, with clashes in red.
- Ask why. When a slot has no candidates, the editor says which crossing is to blame.
- Split a stuck slot. Turn one impossible long word into two shorter ones by adding a clue cell.
- Review every clue in one list. All the definitions of a grid on one screen, with the missing ones counted.

There is also a button that proposes clues in a chosen tone: classic, funny, pop culture, trap, or poetic. It is a good source of first drafts.
The ones that made Lo laugh were the ones I rewrote. [True? Or did a generated one land?]Printing them
An arrow-word grid has to look like one. The clue text has to fit a cell a few millimetres wide, and the arrows have to sit on the edge of the cell, pointing at the right row or column. When a single cell carries two clues, one across and one down, each needs its own band and its own arrow. That took more attempts than the solver did.
The tool’s job ends at the grid. It exports each one as an SVG, a drawing made of shapes and text rather than pixels, so nothing is lost when it changes size. I imported those into Figma and did the final layout there by hand: a title for each grid, the type, and a photo in the middle.
The booklet also got a cover, in the style of the puzzle magazines you find at a newsstand. Limited edition, June 2026, “un moment de pure relaxation”.

Then I printed it myself, as an A5 booklet. Five grids, small enough to fit in a bag, and the only copy in existence.
[What happened when he got it? Did he solve them, how long did it take, what did he say?]
What I’d tell someone trying this
The dictionary is the gift. The software is a way to arrange it. The hours that mattered were the ones spent remembering things about a friend.
Get to a hundred words before writing any code. Under that, no solver will help you.
Let the machine do the first eighty percent, and keep the rest for yourself. Filling a grid is a search problem. Deciding what is funny is not.
Build the editor, not just the generator. Every grid needed a second pass. The tools for that pass are the ones I used most.
Stop the software where a design tool starts. I did not need my own page layout. Exporting a clean drawing and finishing in Figma was faster, and it looked better.
One for you
This one has no private jokes, so anyone can solve it. It is the small sheet from earlier in the article, filled in, and in English, which almost nobody does with arrow words. Choose a cell and type. Press the same cell again to turn the corner.

