Docs

Everything here is free to use. New to Thaana on the web? Read Displaying Thaana well. Building with an AI agent? Point it at /llms.txt.

Embed a font

The CSS API works like Google Fonts. Each font's page builds the URL for you; this is the format.

HTML
<link rel="stylesheet" href="https://fonts.mv/css2?family=Faruma&family=Bolhu:wght@400;700&display=swap">

<p dir="rtl" lang="dv" style="font-family: 'Faruma', system-ui, sans-serif">ދިވެހިރާއްޖެ</p>
  • family=Name with spaces as +. Old names work too (A_Waheed).
  • :wght@400;700 picks weights; without it you get the default weight.
  • Fonts are split into Thaana and Latin parts, so a Thaana-only page downloads only the Thaana part.
  • Many Dhivehi fonts have no Latin letters, so always list a Latin fallback after the family.
  • Optional: &normalize=1 makes every font the same size (below).

Thaana keyboard

Most people have no Dhivehi keyboard installed. One script turns Latin keystrokes into Thaana with the Divehi Phonetic layout (Microsoft's standard layout, used across Maldivian sites). Try it:

Try it

Type divehi to get ދިވެހި

No build step
<script type="module" src="https://fonts.mv/thaana.js"></script>

<input data-thaana>
<textarea data-thaana></textarea>
<div contenteditable data-thaana></div>

<!-- or a classic script: window.Thaana -->
<script src="https://fonts.mv/thaana.iife.js"></script>
  • Only typed characters change. Paste, IME composition, autocorrect and real Dhivehi keyboards pass through.
  • Brackets work like Microsoft's layout: press the key that looks right on screen () to open on the right). The pairs are swapped, so the stored text keeps ( before the enclosed text and browsers mirror it in RTL.
  • , ; ? type the Dhivehi forms ، ؛ ؟.
  • Works with React, Vue and Svelte controlled inputs; native undo keeps working.

Layout

ޤ ް qޢ އ wޭ ެ eޜ ރ rޓ ތ tޠ ޔ yޫ ު uީ ި iޯ ޮ o÷ ޕ pާ ަ aށ ސ sޑ ދ dﷲ ފ fޣ ގ gޙ ހ hޛ ޖ jޚ ކ kޅ ލ lޡ ޒ zޘ × xޝ ޗ cޥ ވ vޞ ބ bޏ ނ nޟ މ m

Top: with Shift. The raw map is at /keymap.json.

Packages

One install makes Thaana work in your app: keyboard, fonts, bidi and punctuation helpers. The framework packages include everything from @yashau/thaana.

Install
npm i @yashau/thaana
Use
import { attachKeyboard, loadFonts, fontStack } from '@yashau/thaana';
import '@yashau/thaana/thaana.css'; // sane defaults for :lang(dv)

await loadFonts({ family: 'Faruma' });
const input = document.querySelector('#name');
input.style.fontFamily = fontStack('Faruma');

let dv = true; // e.g. bound to a DV/EN toggle
const detach = attachKeyboard(input, { enabled: () => dv });

Same size for every font

Dhivehi fonts differ a lot in size at the same font-size: some draw their letters at half Faruma's size, others at nearly twice. Ask for normalize and each family is scaled with CSS size-adjust so its Thaana letters look as big as Faruma's. Switching fonts then keeps your text the same size. The font files are not changed, and it's off unless you ask for it.

HTML
<link rel="stylesheet" href="https://fonts.mv/css2?family=Bolhu&family=Faiy&display=swap&normalize=1">
JS
import { loadFonts, fontCssUrl } from '@yashau/thaana';

await loadFonts({ family: 'Bolhu' }, { normalize: true });
fontCssUrl([{ family: 'Faiy' }], { normalize: true }); // just the URL
React / Vue
useDhivehiFont('Bolhu', [400], { normalize: true });

Each font's page has a switch that adds it to the embed code. The scale per family is in fonts.json (sizeAdjust).

Helpers

attachKeyboard(el, { enabled })

Phonetic keyboard on an input, textarea or contenteditable. Returns detach().

autoAttach() / import "@yashau/thaana/auto"

Attach to every [data-thaana] field, including ones added later.

<ThaanaText text={…} />

React/Svelte/Vue: show Thaana right-to-left with lang="dv" and numbers isolated, even when it starts with a Latin word.

thaanaForInputEvent(event)

For rich-text editors (Lexical, TipTap, ProseMirror): the Thaana character to insert, or null.

transliterate("divehi")

"ދިވެހި": replays keystrokes in the Divehi Phonetic layout.

convertLegacy(text, { layout })

Text typed in old A_ / phonetic fonts → Unicode Thaana.

repairPdfText(text)

Fix Thaana copied out of PDFs: reversed dates and times, spacing, list markers.

normalizePunctuation(text)

Latin , ; ? → ، ؛ ؟ after Thaana; no space before punctuation or inside brackets.

isolateNumbers(text)

Keep -5, +960 333-1234, 9:00, 1,000, 50% intact inside RTL text (display only).

isolate(value, dir)

Wrap a URL, email or name in a bidi isolate (when you can't use <bdi>).

stripBidiControls(text)

Remove invisible bidi marks before saving or comparing.

hasThaana · hasRtl · isMixedScript

Script detection.

detectDirection(text) · resolveDirection(text, explicit, fallback)

First-strong (like dir="auto") vs rihaPDF's rule: any Thaana → RTL; no letters → fallback.

loadFonts({ family, weights, files }, { normalize })

Load a font; resolves when it can be drawn (canvas, SVG). Options: same size (above) and self-hosting (below).

fontStack(family)

A font-family with a Latin fallback and installed Thaana fonts.

PANGRAMS · LETTERS · ARABIC_LETTERS · FILI

Sample text and the alphabet.

fontFaceCss({ family, files })

@font-face CSS for your own copies of the files (self-hosting).

Plus @yashau/thaana/thaana.css: right-to-left, a line height that doesn't clip fili, no fake italics, and per-paragraph direction for :lang(dv). Also at /thaana.css.

Self-hosting

Every font and collection can be downloaded from its page or the downloads page, to serve from your own server.

With the packages

Pass the URLs of your copies by weight. The packages then register the font from your files and load nothing from fonts.mv. For normalize, also pass the family's sizeAdjust from fonts.json.

JS
import { loadFonts, fontFaceCss } from '@yashau/thaana';

await loadFonts({ family: 'Faruma', files: { 400: '/fonts/faruma-400.woff2' } });

// Or the @font-face rules for your own stylesheet:
fontFaceCss({ family: 'Bolhu', files: { 400: '/fonts/bolhu-400.woff2', 700: '/fonts/bolhu-700.woff2' } });
React / Vue
useDhivehiFont('Faruma', [400], { files: { 400: '/fonts/faruma-400.woff2' } });

For tools and agents

  • /llms.txt: every recipe and the whole font list, for AI agents.
  • /fonts.json: every family with weights, license, CSS URL and file URLs.
  • /keymap.json: the keyboard layout as data.