Skip to content
AFM Studio
  • Pages

    AFM Studio
  • Work
  • Lab
  • About
  • CV
  • Contact
  • Projects

    AksaraA searchable library for Otorita IKN's knowledge, where the server checks every reader's access across three levels
  • Daily TaqwaTamper-resistant prayer attendance system for ~2,000 OIKN government employees at Masjid Negara IKN
  • Lantara v2A permit engine for Otorita IKN where administrators add new permit types from a screen, without a developer
  • eKiosk IKNTwo control rooms for Nusantara: kiosk content management and live bus tracking with arrival times that grade themselves
  • E-Monev IKNA monitoring platform for Nusantara's 23-year build, tracking every unit's quarterly progress against 24 national KPIs
  • JDIH OIKNOIKN's public legal document portal, with a controlled publishing workflow and AI summaries that never leave the server
  • Jejak PenanamanA check-in app for IKN tree-planting events that proves each participant was on site with a geofenced selfie
  • Dashboard SAKTIA nightly pipeline and dashboard that replaces OIKN's manual budget downloads for all six of its budget units
  • DoseRxA bedside dose calculator for 127 drugs that rounds each dose to tablets and syrups Indonesian pharmacies sell
  • CubiqA speedcubing trainer with competition-grade timing and a solver I wrote for each of the 8 major puzzles
  • ScimotionAn interactive science library of 86 articles, each explained next to animations the reader can control
  • WA Daily Scrum BotA WhatsApp bot that chases missing standup reports for a 14-person team and flags tasks stuck for days

↑ ↓ to move · Enter to open · Esc to close

Lontara

A Bugis Lontara reader and writer that lists every possible reading when the script leaves the word open

Screenshots
agreement with Bugis Wikipedia pairs, up from 56%
94%
word-list entries, each with its source
1,323
Lontara–Latin pairs written by Bugis users
97
open questions recorded instead of guessed
7
On this page

The problem

Lontara is the script of the Bugis language of South Sulawesi. It has 23 consonants and five vowel signs, but no way to write a consonant on its own. So it never records consonants at the end of a syllable, doubled consonants, a nasal before a consonant, or the glottal stop. The words mata, matta and manta are all written the same way. A reader picks the word from context.

Existing converters hide this. They return one confident Latin spelling, which is a guess presented as an answer. A signmaker can put a misspelled name on a permanent sign. A learner can be taught a rule that doesn't exist. Someone reading family manuscripts gets one reading where six are valid, with no sign that a choice was made.

What I built

The tool lists every reading the script allows

Paste Lontara into the reader and it returns a tree of possible Latin readings. Each branch point is labelled with the kind of ambiguity that caused it: a final consonant, a doubled consonant, a nasal or a glottal stop. Each choice the tool makes must carry a reason, so it can't pick a reading silently. The writer goes the other way. It lays Latin onto a palm-leaf band and marks lost information on the stroke where it was dropped.

The spelling rules live where a reviewer can read them

The eleven spelling rules sit in a data file, each marked as cited, provisional or derived, with its citation. The code only interprets that file. A Bugis reader who doesn't program has to be able to audit the orthography, and one page in the app shows every rule with its source.

Readings come from a word list, never from a guessed rule

The obvious reader would try every consonant that could close each syllable. That needs a list of Bugis final consonants, and I couldn't find one to cite. Guessing it would produce confident readings that aren't Bugis. So a reading counts only if it is a known word that the writer turns back into exactly the same Lontara. The cost is that results are only as complete as the word list, and every result says so.

Real Bugis writing caught a 56% error rate

Bugis Wikipedia has pairs of Lontara and Latin written by people who use the script. I extracted 97 of them and scored my rules against them. They agreed 56% of the time. The test found three mistakes. Two vowel letters were the reverse of what their Unicode names suggested, é was missing entirely, and people write the glottal stop as q. Fixing them raised agreement to 94%. Two other oddities, with two cases each, may be errors in the articles, so I left them for a reviewer.

The word list claims only what it can support

The word list has 1,323 entries, and each one records where it came from. 85% of the source dump turned out to be bot-generated stubs, so the list makes no claim about how common a word is, and the build fails if an entry does. Some entries are Indonesian, English or Vietnamese place names the tool can't tell apart from Bugis, so the reader badges those readings and ranks them low.

Result

Lontara is live and public, in Indonesian and English, and works offline after the first visit. It includes an on-screen Lontara keyboard, because most phones have none. By its own rules it is deployed but not launched. No Bugis reviewer has signed off yet, the code enforces that gate, and every page says so. The spelling page lists seven open questions I recorded instead of guessing. It says plainly that it is a personal project, not an authority, and can be wrong. It transliterates and never translates. I built it alone in six days, from late July to early August 2026.

Under the hoodTechnical detail for engineers
  • Characters come from the Unicode Buginese block (U+1A00–U+1A1F), which has no virama. Latin e is U+1A1B and é is U+1A19, the reverse of what the character names imply.
  • Rules live in data/rules/rules.json: rule set v0.2.0, 11 rules across 4 stages (5 cited, 2 provisional, 4 derived). pnpm rules:report prints them; /ejaan renders them.
  • The engine is pure: (input, direction, options, ruleSet, lexicon) => TransliterationTrace, enforced by an ESLint override and tests/invariants.test.ts. interpret.ts writes; enumerate.ts reads by inverting the writer over the lexicon.
  • An ambiguity is { class, candidates, chosen, reason, spans } with reason required. Classes are the closed set final, gemination, prenasal, glottal.
  • Trace steps carry input and output spans and name which cluster array they index. Mixing the two once pointed connector strokes at the wrong glyph.
  • NFC normalisation and Intl.Segmenter for grapheme clusters; never str[i] or .split('') for glyph logic.
  • The corpus comes from {{multiscript|…}} templates in the Bugis Wikipedia dump (CC BY-SA 4.0). tests/corpus.test.ts pins the 94% rate and requires every remaining disagreement to be explained. The unacted findings are ngp → MPA and nc → NYCA.
  • All 1,323 lexicon entries are attestation: "corpus" and band: "unknown". Before de-botting, nine "common" words appeared in 617–620 articles each because they were the colour key of one repeated map caption.
  • data/rules/reviewers.json is empty and pnpm gate:check exits 1; CI runs it with continue-on-error so the writer and conformance page still build.
  • CI enforces a 200 KB gzipped JS budget and checks the build-time service worker's precache list against the files on disk, then fetches every URL. The worker omits skipWaiting and clients.claim to avoid mixing builds mid-session.
  • Shared text lives after the # in the URL, so it never reaches a server log.
  • Four runtime dependencies: Next.js 14.2.15, React 18.3.1, React DOM and Zod 3.23.8. No transliteration library. Fonts (Noto Sans Buginese, Gentium Plus, Space Mono) are subset to 76 KB of woff2.
  • 281 tests in 6 files; 6 routes in two locales, including the full script reference at /aksara; 12 hard rendering strings on the conformance page.
  • The first spec covered Javanese and Balinese too. I cut it to Bugis because Noto Sans Buginese has 41 glyphs and 2 OpenType features. Nulisa is linked for the other scripts. Urupu, the endonym, is the fallback name.
  • About 9,300 source lines and 35 commits from 30 July to 4 August 2026, across three active days.

Screenshots

Beranda
Baca
Tulis
Aksara
Ejaan

Hiring, or building something similar?

I'm open to full-time roles and select freelance work.