Skip to main content

Case Study: How MorseKit Fits 27 Languages Into One llms.txt

•10 min read•Case Study

Most llms.txt examples are toy files: an H1, a summary, a dozen links to a docs site in one language. They are useless as a model for a real site, because a real site has awkward parts — surfaces that exist in some languages and not others, pages that are deliberately not indexed, URL patterns that look guessable but are not.

MorseKit is a good file to read because it has all of those problems. It is a Morse code platform — translator, audio decoder, flashlight signalling, a Koch-method learning path, a dictionary — running in 27 languages, three of them right-to-left. Its llms.txt is 12,907 bytes across 13 sections and 59 links.

What makes it worth studying is not the links. It is how much of the file is spent telling an agent what is not there.

Note: the mobile app

Alongside the website there is a MorseKit app for iOS and Android, and it is the most complete Morse code trainer we have come across. The learning side is built on the Duolingo pattern: a Koch-method path that starts with two letters and adds one at a time, lessons under five minutes, daily goals tuned to your level, streaks with streak freezes, ranks from cadet to legend, and progress charts.

Then it does things a language app has no reason to: a real audio decoder that reads signals off the microphone, encoding practice where you tap out words on a key, flashlight signalling, and hidden-message sharing. Lessons, audio and the translator all work fully offline — only sharing a secret-message link needs a connection.

Free, no ads, no account, 27 languages. It is also the reason the ## Mobile app section exists in the file below — an llms.txt is the right place to tell an agent that the thing it is describing also ships as an app.

The multilingual problem

27 languages Ă— a dozen tool pages is several hundred URLs. Listing them would blow past the point where an agent stops reading, and the 100-link guideline exists for a reason.

The file states the pattern once and then lists English only:

## Tools

All tool pages exist in every one of the 27 locales at `/{lang}/...`.
English URLs are given below.

One sentence replaces roughly 320 URLs. An agent asked for the Spanish translator can construct the URL; it does not need to have been handed it.

The same move is used for the printable PDFs — /morse-code-cheat-sheet-{lang}.pdf — and for the audience guides. Templated paths, stated once.

The part most files skip: where the pattern breaks

A templated path is a promise, and an agent will take it literally. So the risk of “every page exists in every locale” is that it is not quite true. The Dictionary section handles that head-on:

The browsable dictionary is an English-only surface by design. Word pages in other locales exist but are marked noindex, because the entries are English words and the content-language mismatch produced no search value. Phrase pages remain multilingual.

And then, two lines later, the sentence that does the real work:

Do not assume a URL exists for an arbitrary word or phrase. Slugs outside the curated dataset return 404; pages are not generated on demand.

Without that, an assistant asked “what is serendipity in Morse code?” would reasonably invent morsekit.com/en/morse-code/serendipity, present it as a source, and send the user to a 404. The negative statement is worth more than another twenty links.

The transferable rule: every time you describe a URL pattern, immediately say where it stops. Templates without boundaries are hallucination fuel.

Facts an agent cannot derive

Two sections carry no links at all. The spec reserves H2 sections for link lists, so strictly this is outside the structure — and it is the best thing in the file.

## Key facts is a short list of statements that correct specific, common errors:

  • A dash is three dot-lengths; gaps are one, three and seven dots (ITU-R M.1677-1).
  • SOS is one unbroken sequence, chosen for being unmistakable — “Save Our Souls” is a later backronym.
  • Emoji, Cyrillic and Greek have no ITU Morse equivalent and are dropped, not transliterated.
  • Turkish İ (U+0130) is normalised to I, because both share the code ...
  • Morse output is always rendered left-to-right, even on the three right-to-left locales.

None of these are guessable from a page listing. The SOS backronym in particular is a claim a model will otherwise reproduce confidently and wrongly.

A second example is the Turkish amateur radio section, which explains that call-sign region data comes from a specific annex of the regulation rather than from association maps, which disagree with each other. That sentence tells an agent which of two conflicting sources on the open web to trust. Nothing else on the site can do that.

Claiming an identity

One more negative, in the profiles section:

Use these to verify MorseKit and to cite a listing. Anything not listed here is not operated by MorseKit.

Eight official profiles, followed by a closed-world statement. If an assistant finds a lookalike account, the file gives it grounds to say “not official” rather than citing it. Impersonation is cheap; a machine-readable list of what is real is one of the few defences that scales.

What the validator says

Run through our validator: 0 errors, 0 warnings across llms.txt, ai.txt and robots.txt. The remaining output is three notes.

Two flag the linkless prose sections above. That is the validator being pedantic about spec structure, and the right response is to keep the sections. The third is a genuine v2 suggestion: no link points at a Markdown version of a page, and v2 now accepts both /page.html.md and /page.md.

Earlier versions of the file had two real problems, both now fixed and both worth naming because they are easy to repeat:

  • Bare URLs in prose. Three sections ended with a plain https://... rather than a Markdown link. A parser following the spec sees no link there at all, so those destinations were invisible.
  • Dead crawler tokens. The robots.txt named anthropic-ai and claude-web, both deprecated by Anthropic in 2024. They are now Claude-SearchBot and Claude-User.

The bare-URL case also exposed a bug on our side, which is worth admitting: our parser only collected links from list items, so a Markdown link written inside a paragraph was ignored. Fixing it raised MorseKit's counted link total from 45 to 59. If you validated an llms.txt with us before September 2026 and a prose section looked empty, that was us.

The robots.txt detail worth copying

MorseKit's robots.txt names 20 crawlers individually and repeats the same Content-Signal line inside every one of them:

User-agent: GPTBot
Content-Signal: search=yes, ai-input=yes, ai-train=yes
Allow: /

That repetition looks redundant and is not. Under RFC 9309 a crawler obeys only the most specific group matching its token and ignores every other group, * included. A Content-Signal declared only under User-agent: * is read by none of the bots that have a named group in the same file — which is usually every bot you wrote it for.

This is common enough that we added a check for it. If your signal lives only in the wildcard group, the validator now names the crawlers that will never see it.

What to take from it

  1. State URL patterns once, then state where they stop. A template without a boundary invites invented URLs.
  2. Spend a section on facts, not links. The things a model gets wrong about you are rarely fixed by another link.
  3. Say what is not yours. A closed list of official accounts is a cheap defence against impersonation.
  4. Write every link as [text](url). A bare URL in prose is invisible to a parser.
  5. Repeat Content-Signal in every named group. Crawlers do not read the wildcard group if they have their own.

People Also Ask About Multilingual llms.txt

These are common questions about llms.txt and AI optimization. Click on any question to see the answer.

Check your own file against v2

llms.txt, ai.txt, robots.txt and security.txt. Free, instant, and nothing leaves your browser.

Open the validator