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

Nusantara Languages

A map of Indonesia's 726 languages, linked to their family tree so each branch lights up its territory

Screenshots
Indonesian languages on one linked map
726
language families in the tree
56
languages with a mapped speaker area
58%
confusable colour pairs fixed for colour-blind readers
48 → 2
On this page

The problem

Indonesia has more than 700 languages, one of the densest concentrations on Earth. For most people, the shape of that diversity is invisible. Which languages are related? How did the families spread across the islands? Language maps exist, and family trees exist, but nothing links the two into one thing you can explore.

I built Nusantara Languages for students, linguists and anyone curious about where Indonesia's language families meet. The clearest example is the seam where the Austronesian and Papuan families touch, which runs through Halmahera. It is a personal, open-source project. It isn't Badan Bahasa's official "Peta Bahasa", so it doesn't use that name or look.

What I built

The map and the family tree are one object

The map and the tree read from the same data. Hover a branch of the tree and every territory in that group lights up on the map. Click a territory and the tree scrolls to it and opens its ancestry. Because both views read one structure, they can't fall out of sync. I wrote the tree and geometry logic as plain functions, so the trickiest parts can be tested without a browser.

I measured speed before styling anything

The site is static and makes no network requests at runtime. A build step fetches the worldwide sources, keeps Indonesia, simplifies the shapes and writes one data bundle with a coverage report. Before any styling, I measured whether hovering would feel instant with 726 languages drawn. It came in at about 0.01 milliseconds against a 2-millisecond budget. That let me keep plain vector drawing and hand-build both the map and the tree parser.

I dropped the planned atlas over its licence

The plan was to draw territories from a 1980s atlas, the source meant to make the map look good. At the licence check, it turned out to allow non-commercial use only. That conflicts with the open licence the site's data is published under. I refused the source, recorded why on the method page, and switched to two openly licensed datasets from 1990 to 2020. The map's era changed with it. Ethnologue is banned entirely, and a test proves none of its data ships. Where a figure exists only there, the page leaves it out and says so.

A language without a territory stays a point

Of the 726 languages, 421 have mapped speaker areas. The other 305 appear as labelled points, drawn differently. I didn't stretch them into shapes to make the map look complete. The build computes that 58% figure from the data, so it can't drift. The coastline comes from a geographic dataset and is never traced from language areas. I chose family colours to stay distinct for three kinds of colour blindness, and show endangerment as hatching over the family colour.

Result

Nusantara Languages is live in English and Indonesian, fully static, and works offline. Beyond the map and tree, it answers three questions from the same data. Which languages are a language's closest relatives? How far does a family spread? Austronesian spans about 5,010 km, Timor-Alor-Pantar about 350 km. Which languages from different families touch? There are 67 such pairs. Each answer prints its rule and its limit next to the number. You can also colour by subgroup, follow guided views of the seams, and export a PNG with attribution built in, as the licence requires. The site states that boundaries between languages are gradual, and how many languages are areas and how many are points. I built it alone between August and September 2026.

Under the hoodTechnical detail for engineers
  • Next.js static export on GitHub Pages; React, strict TypeScript, Tailwind, Zod for the source manifest, Vitest, tsx for pipeline scripts, pnpm. Type is Newsreader for display and prose, IBM Plex Sans Condensed for labels, IBM Plex Mono for data and counts, all self-hosted through next/font.
  • Two browser-only bugs slipped past the type checker and the test suite. A <style> tag with a text child broke hydration, fixed by switching to dangerouslySetInnerHTML. Grouping land by geometry kind silently dropped 273 minor islands; the fix groups by whether a shape has a neighbour instead.
  • No mapping, GIS, Newick or topology library. The Newick parser and the SVG plate with its hover hit-testing are hand-written; lib/tree and lib/geo are pure functions tested in Node.
  • sources:build fetches, licence-gates, filters to Indonesia, simplifies polygons, cross-checks lineages and writes the bundle plus coverage.json. Raw worldwide dumps are never committed.
  • M0 render budget: 19,570 vertices against 60,000, hover about 0.01 ms against 2 ms, so SVG stayed and canvas wasn't needed.
  • The licence gate needs every source to declare a pinned, machine-checked licence. Wurm & Hattori's atlas (republished as GeoJSON by Glottography) is CC-BY-NC-4.0, incompatible with the bundle's CC-BY-SA-4.0, and sits in the manifest as decision: 'refused'. Replacements: asher2007world and schapper2020papuan, both CC-BY-4.0. test:licence asserts no Ethnologue-derived field exists.
  • Point-only languages use Glottolog coordinates, which are often population midpoints. Convex hulls and Voronoi fills are banned by a tested invariant. The Natural Earth coastline was added back mid-project after islands looked "eaten away"; it is pointer-events-none.
  • Family colours come from a curated OKLCH set scored against three colour-vision deficiencies; confusable pairs fell from 15 to 0 in normal vision. Saturation is reserved for the current selection.
  • Accessibility: the tree is a role="tree" with roving tabindex, one tab stop instead of 1,716 when fully expanded. Several ARIA roles without matching keyboard behaviour (tablist, combobox) were removed in favour of native elements.
  • The flaky gate uses Math.max(...samples) against 16 ms; observed runs ranged from 0.57 ms to 27.34 ms.
  • 726 languages, 56 top-level families, 23 isolates. Contact pairs come from a segment-to-segment adjacency check. JS budget: 234 KB gzipped excluding geometry, measured against a 250 KB target.
  • About 21,135 lines of TypeScript, 579 tests across 37 test files, 18 components, about 10 routes, 112 commits from 12 August to 27 September 2026.

Screenshots

Beranda
Maps
Fullscreen Maps
Language Page
Guided Views
Method

Hiring, or building something similar?

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