Dev.to WebDev 🛠 Dev 👁 0 📖 3 min read

Printing Urdu worksheets in Nastaliq from the browser: joined letter forms with ZWJ and print-to-PDF

Urdu letters change shape when they join. ب on its own, at the start of a word, in the middle and at the end are four different shapes, and a child who only practises the first one cannot read بلی (cat). Most free Urdu w

Urdu letters change shape when they join. ب on its own, at the start of a word, in the middle and at the end are four different shapes, and a child who only practises the first one cannot read بلی (cat). Most free Urdu worksheets online are the same few scanned PDFs mirrored on spam pages, and almost none show the joined forms.

I built Takhti, a free worksheet maker that prints them correctly, with the child's name on the sheet. Everything runs in the browser. Here are the three tricks that made it work without a server or a PDF library.

1. Ask the font for a joined form with ZWJ

You do not need a table of presentation-form code points. Put a ZERO WIDTH JOINER (U+200D) on the side where the letter should connect, and the shaping engine (HarfBuzz in Chrome, CoreText in Safari) picks the right glyph:

const ZWJ = "‍";
function forms(letter, joins) {
  if (joins === "both") return [letter, letter + ZWJ, ZWJ + letter + ZWJ, ZWJ + letter]; // alone, start, middle, end
  if (joins === "right") return [letter, ZWJ + letter];  // ا د ڈ ذ ر ڑ ز ژ و ے: two shapes only
  return [letter];                                       // ء never joins
}

The ten right-joining letters are the part teachers notice when a sheet gets them wrong: ر has no "start" or "middle" form, so a sheet that shows four shapes for it is teaching a mistake.

The same trick builds a "missing first letter" exercise. Remove the first letter of پتنگ and you get تنگ, which renders with ت in its initial form. Prefix the rest with ZWJ and ت shows its middle form, the way it looks inside the real word. If the removed letter is one of the right-joiners (ریل without ر), skip the ZWJ, because the next letter really does start fresh.

2. Nastaliq needs room, and a real font

Noto Nastaliq Urdu is SIL OFL, so it can be self-hosted. The variable TTF from google/fonts converts to a 260 KB WOFF2 with fontTools. Two things to know:

  • Nastaliq has tall ascenders and deep descenders. A line height under about 1.8 clips dots and the tails of ے and ی.
  • The glyphs are small for their em size compared with Latin text, so Urdu needs a bigger font size next to English to look balanced.

I also offer Noto Naskh Arabic as an option, since many teachers start small children on the simpler Naskh shapes.

3. Print to PDF is the PDF engine

Most client-side PDF libraries draw text glyph by glyph and do not run the shaping engine, so Nastaliq comes out as disconnected letters. The browser's own print path does shape it, and on Android and desktop Chrome "Save as PDF" is in the print dialog. So each sheet is a fixed-size element:

.sheet { width: 210mm; height: 297mm; padding: 11mm 12mm 9mm; box-sizing: border-box; overflow: hidden; }
.letter .sheet { width: 215.9mm; height: 279.4mm; }   /* US Letter for families abroad */
@media print {
  body > :not(#print-root) { display: none !important; }
  .sheet { break-after: page; }
}

On print, the script copies the sheets into #print-root, injects @page { size: A4; margin: 0 } (or letter), waits for document.fonts.ready, then calls window.print(). Headless Chrome's --print-to-pdf gives the same output, which made it easy to test every sheet type: the fonts embed as Type 3 glyphs with the joins intact.

For the on-screen preview on a 390 px phone, the same A4 element is scaled with CSS zoom set to the container width divided by 794 (A4 width in CSS pixels), so what you see is exactly what prints.

What it makes

Letter tracing in all joined forms, the whole alphabet, the child's own name (common names are converted from Roman spelling, and there is a tap keyboard for the rest), letter and picture matching, missing letter, joining letters into words, ginti 1 to 10, opposites, wahid jama and muzakkar muannas, and short graded stories with a Roman Urdu and an English line under each Urdu line for parents abroad who do not read the script.

Every sheet carries the site address in its footer, since worksheets get photocopied and passed around classes. It is free, with no signup: https://takhti.appin60.com

If you teach Urdu, or have children learning it, I would like to hear which sheet is missing: [email protected].

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.