İnteraktif Matematik
Eight mathematical ideas you can play with rather than read about: the Towers of Hanoi, the Bridges of Königsberg, a Caesar cipher, the birthday paradox, Collatz, map colouring, Pappus's hexagon theorem and a Galton board. It is free, it has no account, and it was built in Turkish first. It now lives at two addresses — interactivemathematics.org (opens in a new tab) in English and interaktifmatematik.org (opens in a new tab) in Turkish.
The alphabet is not a label
The most interesting thing that happened to this site was translating it into English, and the reason is a single game. The Caesar cipher was built on the Turkish alphabet, which has twenty-nine letters. Translating the interface strings would have produced an English page that still asked an English visitor to type İ, Ş and Ğ.
The alphabet is not decoration around the cipher. It is the cipher. Twenty-nine letters means twenty-nine possible shifts; twenty-six means twenty-six. So the shift slider's range changes, and so does the number it announces to a screen reader, and so does the sentence in the copy that tells you how many shifts there are — all of them derived from the alphabet's length rather than from the number 29 written down somewhere.
Turkish also has a dotted and a dotless i, which means changing a letter's case is a question with a different answer in each language. Case conversion follows the locale too.
And the challenge phrases had to move into the translation files, where each one is verified to contain only letters the cipher can actually shift — a quote with an apostrophe or a digit in it is not a puzzle, it is a bug waiting for the first person who tries it.
Translating a maths site is translating the maths
The cipher was the sharpest case but not the only one. Counters needed real plural rules, because "1 move" and "3 moves" is a grammatical distinction English insists on and Turkish does not. Announcements meant for screen readers had to be translated as carefully as the visible text, since they are the only text some visitors get. The social preview image for each game is rendered per language rather than shipped once — with the honest exception that its alternative text stays in one language, because the framework only allows a static export at that one spot.
Every page was shipping words nobody read
Making the site bilingual exposed something that had been true and invisible while it was monolingual: the whole translation catalogue was being serialised into the HTML of every page. The body of the welcome email. Error strings for the API. Prose that only ever renders on the server. Three kilobytes on the Hanoi page alone, growing with every game added and every string written.
Now a page ships only the strings its interactive parts actually read. It is the sort of weight that never announces itself — nothing is slow, exactly, it is just that everyone was downloading a copy of an email they will never be sent.
A game was taken out
Non-transitive dice — the set where A beats B, B beats C, and C beats A — was built and translated and then removed, nineteen files of it, along with its translations and its entry in the games list. It was not finished enough to be public and it was not what the current work was about.
The commit that removed it says where it went: it is still on its own branch and in that branch's history. Deleting something is easier to do honestly when you write down that it is recoverable.
What is still broken, written down
The repository carries a document of open issues, and its opening line sets the standard for what is allowed in it: every item was written by measuring, with no inherited assumptions, and it is dated so you can tell how stale it is. What is in it:
- A test for the Galton board's physics fails — the exact expectation and the exact wrong number are both recorded, along with the fact that it arrived with the game rather than being caused by the translation work. It is the only failure in the suite: two hundred and forty of two hundred and forty-one tests pass, and that ratio is stated rather than rounded to "tests pass".
- A development subdomain is serving frozen content from a branch that no longer exists, because a setting in a dashboard was never changed. The note explains why it is not urgent — every host that is not the production domain is sent a no-index header — instead of just marking it low priority.
- A feature gate that was never carried over to the main branch.
This is the same instinct as Simple Journal's known-limitations sections, arrived at in a different repository for a different kind of project. A list of what is wrong is only useful if writing an entry is cheaper than hiding one.
Where it is now
Eight games, three releases, and a full second language — which now has a domain of its own rather than a path under the Turkish one. It is free and it is meant to stay free: the audience is people looking up a puzzle their teacher mentioned, and a paywall between a person and the Bridges of Königsberg would be an odd thing to build. Read it in English (opens in a new tab) or in Turkish (opens in a new tab).