Publishing Arabic documentation: what RTL-first actually takes
What it takes to publish Arabic documentation well: logical CSS, bidirectional text, Arabic search tokenization, per-language trees, hreflang, and fonts.
· 7 min read · The Nibleaf team
Most documentation platforms treat Arabic as a translation problem. It is not. It is a layout problem, a typography problem, a text-rendering problem, and a search problem — translation is the easy part. If you have ever flipped dir="rtl" on an English-first docs theme and watched the sidebar detach, the code blocks mirror, and search return nothing for a word that is plainly on the page, you already know this.
This is a reference for the five problems that actually matter when you publish Arabic documentation: what each one is, how to solve it by hand, and how Nibleaf — an open-source documentation platform with Arabic as a first-class language — handles it natively.
Layout: logical properties, not a mirrored stylesheet
Physical CSS properties encode a direction: margin-left, padding-right, left: 0, text-align: left. Logical properties encode intent: the start of the line, the end of the block. When the document switches to RTL, logical properties flip themselves; physical ones do not.
/* Physical — sidebar indent breaks in RTL */
.nav-item {
margin-left: 12px;
border-left: 2px solid var(--accent);
}
/* Logical — correct in both directions */
.nav-item {
margin-inline-start: 12px;
border-inline-start: 2px solid var(--accent);
}
The substitution list is longer than most teams expect: text-align: left becomes text-align: start, left/right positioning becomes inset-inline-start/end, corner radii become border-start-start-radius and friends. Tailwind has shipped logical utilities (ms-*, me-*, ps-*, pe-*, start-*, end-*) since v3.3, so there is no excuse for ml-4 in a docs theme anymore.
One thing logical properties do not fix: directional icons. Breadcrumb chevrons, "next page" arrows, and sidebar expanders must be flipped explicitly (transform: scaleX(-1) or swapped assets), while icons depicting real objects should not be.
Nibleaf's reader theme is built RTL-first, so an Arabic project renders mirrored navigation, table of contents, and pagination without any theme surgery.
Bidirectional text: LTR code inside RTL prose
Arabic technical writing is inherently bidirectional: the prose runs right-to-left, but every command, file path, flag, and identifier runs left-to-right. The Unicode bidirectional algorithm (UAX #9) resolves this automatically — and gets technical content wrong constantly, because characters like -, /, and . are directionally neutral and inherit direction from their surroundings.
The classic failure: a sentence like «شغّل الأمر docker compose up -d ثم افتح المتصفح» renders with the -d flag visually detached from its command, because the hyphen binds to the surrounding Arabic. Paths get worse — segment order can appear reversed while each segment reads correctly.
The fix is bidi isolation. Give inline code an explicit direction and isolate it from the paragraph:
code {
direction: ltr;
unicode-bidi: isolate;
}
pre {
direction: ltr;
text-align: left; /* code blocks never mirror */
}
In content, <bdi> or dir="ltr" on the inline element achieves the same. Block-level code must always stay LTR and left-aligned, even on an RTL page — mirrored code is unreadable and un-copyable.
Nibleaf applies this in both the reader and the editor: its Notion-style editor keeps inline code and code blocks LTR-isolated inside Arabic paragraphs while you type, and because the editor round-trips plain Markdown rather than a proprietary format, the bidi behavior you see while writing is exactly what gets published.
Search: why naive full-text search fails Arabic
This is the problem teams discover last, and it is the worst one. A search index built with an English-default pipeline — whitespace tokenizer, Porter stemmer, Latin-oriented fuzzy matching — will silently fail on Arabic in two ways.
First, orthographic variation. Arabic writers are inconsistent (and correct) in ways an exact-match index cannot survive:
| Variation | Written forms | Normalize to |
|---|---|---|
| Alef with hamza or madda | أ ، إ ، آ | ا |
| Alef maqsura vs ya | ى | ي |
| Ta marbuta vs ha | ة | ه |
| Diacritics (tashkeel) | ـَ ـُ ـِ ـّ ـْ | stripped |
| Tatweel (elongation) | ـ | stripped |
A reader who types اعدادات (settings, with a bare alef) will never match a page that spells it الإعدادات (with hamza below the alef) unless the index normalizes both sides.
Second, morphology. Arabic attaches conjunctions, prepositions, and the definite article directly to the word: للمستخدمين is one token meaning "for the users," built from the same stem as مستخدم ("user"). Without light stemming — stripping prefixes like وال، لل، بال and common suffixes — every inflected form is a distinct term and recall collapses. English stemmers do none of this, and the multi-language plugins bolted onto client-side search libraries vary widely in quality.
Nibleaf ships search as part of the platform: Orama-powered full-text and fuzzy matching with a dedicated Arabic tokenizer that handles this normalization, behind a Cmd+K UI. There is no Algolia account to configure and no search index to host separately — it works the same on the hosted cloud and when you self-host the stack.
One tree per language, not a mirrored folder
Most docs generators model translation as a mirrored directory: docs/ and i18n/ar/docs/, same files, same structure, per-locale builds. Docusaurus does this well for what it is — but the mirror assumption rarely survives contact with a real Arabic docs effort.
Arabic documentation almost never launches as a 1:1 copy. It starts as a curated subset — quickstart, installation, core concepts — and grows. Some pages only make sense in one language; grouping and ordering that read naturally in English sometimes deserve restructuring in Arabic. A mirrored tree forces you to either stub out untranslated pages or break the build.
Nibleaf models languages as first-class: each project has per-language page trees, so the Arabic tree and the English tree are edited, organized, and published independently. Publishing is an immutable snapshot per publish, so shipping an updated English section never exposes a half-translated Arabic one, and rolling back is a republish.
hreflang: making ar/en pairs legible to search engines
If the same page exists in Arabic and English, search engines need to be told, or they will treat the versions as competing duplicates and send Arabic-speaking users to English pages.
<link rel="alternate" hreflang="ar" href="https://docs.example.com/ar/guides/deploy" />
<link rel="alternate" hreflang="en" href="https://docs.example.com/en/guides/deploy" />
<link rel="alternate" hreflang="x-default" href="https://docs.example.com/en/guides/deploy" />
The rules that trip people up: annotations must be reciprocal (the Arabic page must link back to the English one, or both are ignored), every page must include a self-referencing entry, and x-default should point at the version you want unmatched locales to receive. Use generic ar rather than ar-SA or ar-EG unless you genuinely publish region-specific content.
Because Nibleaf knows which pages across its language trees correspond, it emits hreflang pairs, canonicals, sitemaps, and localized OG metadata automatically — no per-page frontmatter bookkeeping.
Fonts: Arabic type is not a fallback
Arabic is a connected script. Letters take different shapes depending on position — initial, medial, final, isolated — and rendering depends on OpenType shaping, not just glyph coverage. Practical consequences:
- Never rely on fallback. A Latin webfont with no Arabic glyphs silently falls back to whatever the OS provides, producing mismatched weight, size, and baseline mid-sentence. Pair fonts deliberately: families like IBM Plex, Noto, Cairo, Tajawal, and Rubik ship Arabic companions designed to sit next to their Latin counterparts.
- Give it room. Arabic has taller ascenders, deeper descenders, and optional diacritics above and below the line. Body line-height that looks fine for Latin (1.5) clips Arabic; 1.7–1.9 is a safer range.
- Check your weights. Many Arabic families ship fewer weights than their Latin siblings; a missing weight means browser-synthesized faux bold, which distorts the letterforms.
Nibleaf's reader UI is localized, so the chrome around your content — navigation labels, search placeholder, feedback prompts — renders in Arabic too, not just the prose.
Where existing tools stand
To be fair to the field: Docusaurus has genuine RTL support — set direction: 'rtl' in a locale's config and it builds a mirrored locale — but search, Arabic-capable editing workflow, and hosting are yours to assemble. Mintlify offers multi-language docs with a language switcher. GitBook approaches multilingual content through its own structure; the comparison covers the details. Arabic search tokenization and bidi-aware editing, though, are rarely treated as native concerns.
Nibleaf's position is narrower and deliberate: per-language trees, RTL layout, an Arabic search tokenizer, hreflang emission, and a bilingual (English/Arabic) UI are built into the platform rather than assembled from plugins. It is AGPL-3.0 open source; you can run the whole stack — app, API, worker, PostgreSQL, cache, object storage — with one docker compose up -d, or start on the hosted beta, which is currently free.
The short version
Publishing Arabic documentation properly means: logical CSS properties everywhere, bidi isolation on every inline code span, an Arabic-normalizing search tokenizer, a page tree per language instead of a mirrored folder, reciprocal hreflang pairs, and a font stack chosen for Arabic rather than falling back into it. Each is solvable by hand. The argument for a platform that does them natively is that these are exactly the kind of details that regress silently — and Arabic readers are the ones who notice.
Nibleaf is open source under AGPL-3.0 at github.com/lord007tn/nibleaf. Self-hosting is free forever with no feature gates.
Frequently asked questions
- Why does search on my Arabic documentation site return nothing, even for words that are on the page?
- Most search pipelines tokenize for English. Arabic needs orthographic normalization (collapsing alef variants, stripping diacritics and tatweel) and light stemming to remove attached prefixes like al- and wa-. Without both, the indexed form and the query form never match.
- Does Docusaurus support Arabic and RTL layouts?
- Yes. Docusaurus lets you set direction: rtl per locale in localeConfigs and builds each locale separately. You still need to solve Arabic-aware search, fonts, and an editing workflow yourself.
- Should Arabic docs mirror the English page tree one-to-one?
- Usually not. Arabic documentation typically starts as a curated subset and may need different grouping or ordering. A per-language page tree lets each language grow independently, with hreflang linking the pages that do correspond.
- Which hreflang codes should I use for Arabic documentation?
- Use the generic ar unless you publish genuinely region-specific content. Every page must self-reference and link back to its counterpart, and an x-default should point at the version you want unmatched visitors to get.