
There is no TeX Live for Android. No pdflatex to call, and a full TeX distribution is measured in gigabytes. Which is why everyone writes in Overleaf — and why writing on a plane, or in a room with bad Wi-Fi, quietly stops being possible.
WritePaperTeX is a LaTeX editor that compiles on the tablet itself. No compile server, no account, no network. It is the companion to ReadPaper: one reads papers, this one writes them.
A TeX engine inside the APK
The compiler is Tectonic — XeTeX rebuilt around Rust — compiled to a shared library and called from Dart through dart:ffi, running in an isolate. On Linux the app calls latexmk and XeLaTeX instead, because a machine that already has TeX Live does not need a second copy of it.
Tectonic normally downloads packages on demand. On a tablet with no signal that fails, and it fails dishonestly: the error reads failed to open input file hyph-en-us.tex, which never mentions the network at all. So the packages ship inside the APK — 793 files, 14.8 MB compressed. The APK is 85 MB, and 36 MB of that is ICU data alone.
The numbers that matter. First compile on a fresh install: 3.7 seconds. A real dissertation proposal, with Wi-Fi switched off: a full pass in 1 minute 1 second, a quick pass in 8.7 seconds, with no downloads at all.
Two days of being wrong about how hard it was
The first attempt at building Tectonic for Android died at pkg-config has not been configured to support cross-compilation. Tectonic is not pure Rust — it wraps XeTeX and wants seven C libraries: fontconfig, freetype2, graphite2, ICU, libpng, harfbuzz, flate. I wrote in my notes that this was days of work, not an afternoon.
It took one more day. The missing piece was a single environment variable, TECTONIC_DEP_BACKEND=vcpkg: vcpkg has an arm64-android triplet and builds all seven itself. My notes now carry the correction, which I left in rather than quietly editing out. An estimate that wrong is worth keeping visible.
Underneath were four smaller traps that only show up once you try:
- fontconfig needs
gperf present at build time;
- the build must come from Tectonic's own repository at a release tag, not from crates.io, or cargo pulls sub-crates that no longer agree with each other;
- ICU 78's headers require C++17, while Tectonic 0.15 still passes
-std=c++14;
- a pinned version of the
time crate no longer compiles under current rustc.
The bugs that only exist on a device
The app died instead of reporting an error. The first compile on the tablet ended in SIGABRT inside the compile call. Rust was set to abort on panic, so a panic anywhere inside Tectonic took the whole application with it. It unwinds now, so a panic becomes a message.
The font that was missing because I had it. The bundle is assembled on my laptop, where TeX Gyre Termes is installed — so fontconfig found it locally and it never got downloaded into the bundle. On the tablet: The font texgyretermes-regular cannot be found. The fix was to have the bundling document ask for fonts by filename, which forces the lookup through TeX, which means through the bundle.
Every HTTPS connection refused. "The SSL certificate is invalid", for all of them. Android names the files in its certificate store using an older hash format than modern OpenSSL looks for. The certificates were all present; nothing could find them. They are now copied into a single PEM file once, and that file is what gets pointed at.
A timeout that measures being stuck, not being slow
A first compile of a dissertation can genuinely take ten minutes. A timeout that cuts at five kills correct work just before it finishes. So the limit is on silence: three minutes with no progress, not three minutes in total. What deserves suspicion is the app going quiet, not the app taking a while.
Which requires progress to exist in the first place. Tectonic says nothing until it is done. So the Rust side writes each step to a file and flushes it, and Dart reads that file every 400 ms while it waits. A progress bar that sits still for several minutes is indistinguishable from an app that has hung.
Build output belongs outside the project
Every .aux, .log and .fls goes into .writepapertex/build/, and that folder carries a .gitignore that ignores itself — so the author's own .gitignore is never touched. There is a test for it.
That has a consequence worth following through: because the output PDF lives in an ignored folder, it would never be pushed, and someone opening the repository without TeX installed would find nothing readable. So the compiled PDF is copied back into the project folder on purpose.
Git on a tablet, and a decision that changed
ReadPaper does git over the GitHub REST API, because Android has no git binary. WritePaperTeX deliberately does not reuse that. Its scope is different: it has to work with GitHub, GitLab, and a self-hosted Gitea — and writing one adaptor per provider turns every new provider into work forever.
The plan was to implement git's smart HTTP protocol directly. The code does not do that. Writing the protocol yourself is months of work that other people have already done correctly, so it vendors libgit2 instead. I am leaving the original plan in the notes next to what actually happened, because a decision reversed by contact with reality is more useful to read than a decision that was right the first time.
SSH is not supported on purpose: a private key on a tablet raises a storage problem larger than the convenience is worth, and tokens can be revoked one at a time.
Smaller decisions, stated
XeLaTeX, not pdfLaTeX. XeLaTeX reads UTF-8 and system fonts without ceremony, which matters when you write Indonesian. Tectonic is XeTeX-based too, so the desktop engine and the mobile engine behave the same way. The two choices lock together.
The main file is detected from \documentclass, not from its name. Guessing by name picks main.tex even in a project whose entry point is skripsi.tex.
No flutter_rust_bridge. Raw dart:ffi instead: only one function is needed, and that much code generation for one function only adds parts that can break.
Autocomplete reads TeXstudio and Kile's CWL format, loaded according to the document's own \usepackage lines, with nine files bundled. Dangling \refs are reported with line numbers.
No live collaboration. That needs a server, and this is a local editor. Collaborating through git is enough.
Update, 4 October 2026: from a minute to a few seconds
The 61 seconds above were honest, and they were too slow. "One and a half minutes, really long — TeXstudio on the computer is quick." So I measured before changing anything: every step now carries a timestamp, viewable from the Compile menu. On the tablet, on the same proposal, the time was going somewhere I had not expected.
- The quick pass never produced a PDF. It stopped at
.xdv and never ran xdvipdfmx, so every automatic compile ended without a PDF and every real rebuild fell through to the full pass. Now it is one TeX run, BibTeX if needed, then the PDF.
- The full pass ran TeX seven times. Tectonic believed the
.bbl changed on every pass and only stopped at its retry limit. Patched: a state that cannot be shown to have changed is treated as unchanged. 57 seconds became 26.
- Four seconds of every pass went on one font question. The thesis style asks whether Times New Roman exists, and XeTeX answered by opening every font in
/system/fonts, one by one, to read its name. Fontconfig now points at the app's own font folder. Quick pass 11 → 6.9 seconds, full pass 26 → 14.
- Almost three seconds went on compressing a preview that is thrown away at the next compile. The quick pass no longer compresses: 2.7 → 0.9 seconds. The full pass still does, because that is the PDF you send.
- Unchanged source is not compiled at all. A cheap fingerprint — name, size and modification time of each file — sits beside the build. Pressing compile on an unchanged project went from 61 seconds to 0 ms, and a freshly cloned repository that already carries its PDF shows it straight away.
Because the two passes now produce different files, they have two buttons: Lihat (view — fast, uncompressed) and Lengkap (full — compressed, references settled). The mode switch in the menu is gone. Nobody in the middle of writing remembers which mode they are in, and a 10 MB PDF sent to a supervisor is what forgetting costs.

A quick pass of the sample article: 1.6 seconds. The reference is still ??, and the app says so and offers the full pass.

After Lengkap: 2.2 seconds, and "Table 1" is resolved.
The message panel changed too. Red is now reserved for errors that actually stop the compile. An Underfull \hbox is a typesetting complaint and the PDF still comes out, yet a healthy dissertation used to paint the screen red with dozens of them. Those are folded into one neutral line now; every message shows file:line and can be tapped to jump there; and messages can be copied instead of retyped from the screen.
It is documented now as well: a feature list, a user guide — including why Android's system fonts are not used — and a technical guide covering the five patches to Tectonic and how to measure a compile directly on the tablet.
Where it stands
- The APK is signed with a debug key, so Android warns about an unknown source on install.
- The interface is Indonesian only for now.
- No search and replace and no line numbers yet; undo is still the text field's own.
- SyncTeX files are produced, but tapping to jump between source and PDF is not wired up.
- On a phone-width screen only the editor shows; the side-by-side preview needs a tablet.
- Android system fonts cannot be called by name (
\setmainfont{Roboto}). Use the bundled fonts, such as TeX Gyre, or an .otf/.ttf file in the project.
- Android and Linux only. No Windows build and no ready-to-install Linux package yet.
Get it
AGPL-3.0-or-later, same as ReadPaper. Use it, change it, sell it — but anyone you hand a copy to, including over a network, has the right to the source under the same terms. If a compile service ever runs as a server, that licence is what keeps its source open too. Contributions take a git commit -s sign-off and no CLA.
Linux desktop builds from source and needs texlive-xetex and latexmk installed.

Tidak ada TeX Live untuk Android. Tidak ada pdflatex untuk dipanggil, dan distribusi TeX yang lengkap diukur dalam gigabita. Karena itulah semua orang menulis di Overleaf — dan karena itu pula menulis di pesawat, atau di ruangan dengan Wi-Fi buruk, diam-diam berhenti menjadi mungkin.
WritePaperTeX adalah penyunting LaTeX yang mengompilasi di tabletnya sendiri. Tanpa server kompilasi, tanpa akun, tanpa jaringan. Ia pasangan ReadPaper: yang satu membaca paper, yang ini menulisnya.
Mesin TeX di dalam APK
Kompilatornya Tectonic — XeTeX yang dibangun ulang di sekitar Rust — dikompilasi jadi pustaka bersama dan dipanggil dari Dart lewat dart:ffi, berjalan di isolate. Di Linux aplikasinya memanggil latexmk dan XeLaTeX saja, karena mesin yang sudah punya TeX Live tidak butuh salinan keduanya.
Tectonic biasanya mengunduh paket sesuai kebutuhan. Di tablet tanpa sinyal itu gagal, dan gagalnya tidak jujur: pesannya berbunyi failed to open input file hyph-en-us.tex, yang sama sekali tidak menyebut jaringan. Jadi paketnya ikut dibungkus di dalam APK — 793 berkas, 14,8 MB terkompresi. APK-nya 85 MB, dan 36 MB di antaranya hanya data ICU.
Angka yang penting. Kompilasi pertama pada pemasangan baru: 3,7 detik. Proposal disertasi sungguhan, dengan Wi-Fi dimatikan: lintasan penuh 1 menit 1 detik, lintasan cepat 8,7 detik, tanpa satu pun unduhan.
Dua hari keliru menaksir kesulitannya
Percobaan pertama membangun Tectonic untuk Android mati di pkg-config has not been configured to support cross-compilation. Tectonic bukan Rust murni — ia membungkus XeTeX dan menuntut tujuh pustaka C: fontconfig, freetype2, graphite2, ICU, libpng, harfbuzz, flate. Di catatan saya waktu itu tertulis: ini pekerjaan berhari-hari, bukan satu sore.
Ternyata cukup sehari lagi. Yang terlewat hanya satu variabel lingkungan, TECTONIC_DEP_BACKEND=vcpkg: vcpkg punya triplet arm64-android dan membangun ketujuhnya sendiri. Catatan saya sekarang memuat koreksinya, yang sengaja saya biarkan tertulis alih-alih diam-diam dihapus. Taksiran sesalah itu layak tetap terlihat.
Di bawahnya ada empat jebakan kecil yang baru terlihat setelah dicoba:
- fontconfig menuntut
gperf tersedia saat build;
- build harus dari repositori Tectonic sendiri pada tag rilis, bukan dari crates.io, kalau tidak cargo menarik sub-crate yang sudah tidak sejalan;
- header ICU 78 menuntut C++17, sementara Tectonic 0.15 masih menulis
-std=c++14;
- versi crate
time yang terkunci tidak lagi terkompilasi dengan rustc sekarang.
Bug yang hanya ada di perangkat
Aplikasinya mati alih-alih melaporkan kesalahan. Kompilasi pertama di tablet berakhir dengan SIGABRT di dalam panggilan kompilasinya. Rust disetel untuk abort saat panic, jadi satu panic di mana pun di dalam Tectonic membawa serta seluruh aplikasi. Sekarang ia unwind, sehingga panic menjadi pesan.
Font yang hilang justru karena saya memilikinya. Bundelnya disusun di laptop saya, tempat TeX Gyre Termes sudah terpasang — jadi fontconfig menemukannya secara lokal dan font itu tidak pernah ikut terunduh ke dalam bundel. Di tablet: The font texgyretermes-regular cannot be found. Perbaikannya: dokumen penyusun bundel meminta font lewat nama berkas, yang memaksa pencariannya lewat TeX, yang berarti lewat bundel.
Setiap sambungan HTTPS ditolak. "The SSL certificate is invalid", semuanya. Android menamai berkas di penyimpanan sertifikatnya dengan format hash yang lebih tua daripada yang dicari OpenSSL modern. Sertifikatnya ada semua; tidak ada yang bisa menemukannya. Sekarang sertifikat itu disalin jadi satu berkas PEM sekali, lalu berkas itu yang ditunjuk.
Batas waktu yang mengukur kemacetan, bukan kelambatan
Kompilasi pertama sebuah disertasi memang bisa makan sepuluh menit. Batas waktu yang memotong di menit kelima membunuh pekerjaan yang benar tepat sebelum selesai. Jadi yang dibatasi adalah diamnya: tiga menit tanpa kemajuan, bukan tiga menit total. Yang pantas dicurigai adalah aplikasinya membisu, bukan aplikasinya butuh waktu.
Dan itu menuntut adanya kemajuan yang bisa dilihat. Tectonic tidak berkata apa pun sampai selesai. Jadi sisi Rust menulis tiap langkah ke sebuah berkas lalu menyiramnya, dan Dart membaca berkas itu tiap 400 milidetik sambil menunggu. Bilah kemajuan yang diam selama beberapa menit tidak bisa dibedakan dari aplikasi yang menggantung.
Keluaran build tempatnya di luar proyek
Setiap .aux, .log, dan .fls masuk ke .writepapertex/build/, dan folder itu membawa .gitignore yang mengabaikan dirinya sendiri — jadi .gitignore milik penulisnya tidak pernah disentuh. Ada tesnya.
Ada akibat yang perlu ditindaklanjuti: karena PDF hasilnya berada di folder yang diabaikan, ia tidak akan pernah ikut ter-push, dan orang yang membuka repositorinya tanpa TeX terpasang tidak menemukan apa pun yang bisa dibaca. Jadi PDF hasil kompilasi sengaja disalin balik ke folder proyek.
Git di tablet, dan satu keputusan yang berubah
ReadPaper menjalankan git lewat GitHub REST API, karena Android tidak punya biner git. WritePaperTeX sengaja tidak memakai ulang jalan itu. Ruang lingkupnya berbeda: ia harus jalan dengan GitHub, GitLab, dan Gitea yang dipasang sendiri — dan menulis satu adaptor per penyedia membuat setiap penyedia baru menjadi pekerjaan selamanya.
Rencananya menulis sendiri protokol smart HTTP milik git. Kodenya tidak melakukan itu. Menulis protokolnya sendiri adalah pekerjaan berbulan yang sudah diselesaikan orang lain dengan benar, jadi yang dipakai libgit2, di-vendor. Rencana awalnya saya biarkan tertulis di catatan berdampingan dengan apa yang akhirnya terjadi, karena keputusan yang dibalik oleh benturan dengan kenyataan lebih berguna dibaca daripada keputusan yang benar sejak awal.
SSH sengaja tidak didukung: kunci privat di tablet menimbulkan persoalan penyimpanan yang lebih besar daripada kemudahannya, dan token bisa dicabut satu per satu.
Keputusan-keputusan kecil, disebutkan
XeLaTeX, bukan pdfLaTeX. XeLaTeX membaca UTF-8 dan font sistem tanpa upacara, dan itu penting kalau yang ditulis berbahasa Indonesia. Tectonic pun berbasis XeTeX, jadi mesin desktop dan mesin mobile berperilaku sama. Kedua pilihan itu saling mengunci.
Berkas utama dideteksi dari \documentclass, bukan dari namanya. Menebak dari nama akan memilih main.tex bahkan pada proyek yang titik masuknya skripsi.tex.
Tanpa flutter_rust_bridge. Yang dipakai dart:ffi mentah: yang dibutuhkan hanya satu fungsi, dan codegen sebesar itu untuk satu fungsi hanya menambah bagian yang bisa rusak.
Pelengkapan otomatis membaca format CWL milik TeXstudio dan Kile, dimuat mengikuti baris \usepackage dokumennya sendiri, dengan sembilan berkas ikut dibundel. \ref yang menggantung dilaporkan lengkap dengan nomor barisnya.
Tanpa kolaborasi serentak. Itu butuh server, dan ini penyunting lokal. Berkolaborasi lewat git sudah cukup.
Pembaruan, 4 Oktober 2026: dari semenit menjadi beberapa detik
Angka 61 detik di atas jujur, dan terlalu lambat. "1 menit 30 detik, lama banget, di komputer TeXstudio cepet banget." Jadi saya mengukur dulu sebelum mengubah apa pun: setiap langkah kini diberi cap waktu, yang bisa dilihat dari menu Kompilasi. Di tablet, pada proposal yang sama, waktunya habis di tempat yang tidak saya sangka.
- Lintasan cepat tidak pernah menghasilkan PDF. Ia berhenti di
.xdv dan tidak pernah menjalankan xdvipdfmx, jadi setiap kompilasi otomatis berakhir tanpa PDF dan setiap rebuild sungguhan jatuh ke lintasan lengkap. Sekarang: satu kali TeX, BibTeX bila perlu, lalu PDF.
- Lintasan lengkap menjalankan TeX tujuh kali. Tectonic mengira
.bbl berubah di setiap lintasan dan baru berhenti di batas ulangannya. Ditambal: keadaan yang tidak bisa dibuktikan berubah dianggap tidak berubah. 57 detik menjadi 26.
- Empat detik di setiap lintasan habis untuk satu pertanyaan font. Gaya tesisnya menanyakan apakah Times New Roman ada, dan XeTeX menjawabnya dengan membuka satu per satu seluruh font di
/system/fonts untuk membaca namanya. Fontconfig kini diarahkan ke folder font milik aplikasi. Lintasan cepat 11 → 6,9 detik, lintasan lengkap 26 → 14.
- Hampir tiga detik habis untuk memampatkan pratinjau yang dibuang begitu kompilasi berikutnya selesai. Lintasan cepat kini tidak memampatkan: 2,7 → 0,9 detik. Lintasan lengkap tetap memampatkan, karena hasilnya yang dikirim.
- Sumber yang tidak berubah tidak dikompilasi sama sekali. Sidik jari murah — nama, ukuran, dan waktu ubah tiap berkas — disimpan di samping hasil build. Menekan Kompilasi pada proyek yang tidak berubah turun dari 61 detik menjadi 0 milidetik, dan repositori yang baru di-clone dan sudah membawa PDF-nya langsung menampilkannya.
Karena kedua lintasan kini menghasilkan berkas yang berbeda, keduanya punya tombol sendiri: Lihat (cepat, tidak dimampatkan) dan Lengkap (dimampatkan, rujukan sudah mantap). Pilihan mode di menu dihapus. Orang yang sedang menulis tidak pernah ingat sedang di mode mana, dan PDF sepuluh megabita yang terkirim ke pembimbing adalah akibat lupanya.

Lintasan cepat artikel contoh: 1,6 detik. Rujukannya masih ??, dan aplikasinya mengatakan begitu lalu menawarkan lintasan lengkap.

Setelah Lengkap: 2,2 detik, dan "Tabel 1" sudah terisi.
Panel pesannya ikut berubah. Merah kini hanya untuk galat yang benar-benar menggagalkan kompilasi. Underfull \hbox adalah keluhan penataan huruf dan PDF-nya tetap terbit, tetapi disertasi yang sehat dulu memerahkan layar dengan puluhan baris seperti itu. Sekarang semuanya dilipat jadi satu baris netral; setiap pesan menyebut berkas:baris dan bisa diketuk untuk langsung ke sana; dan pesannya bisa disalin, tidak perlu diketik ulang dari layar.
Sekarang juga ada dokumentasinya: daftar fitur, panduan pengguna — termasuk kenapa font sistem Android tidak dipakai — dan panduan teknis yang memuat lima tambalan pada Tectonic serta cara mengukur kompilasi langsung di tablet.
Keadaannya sekarang
- APK-nya ditandatangani kunci debug, jadi Android memperingatkan soal sumber tidak dikenal saat memasang.
- Antarmukanya masih bahasa Indonesia saja.
- Belum ada cari dan ganti, belum ada nomor baris; urungkan masih yang bawaan kolom teks.
- Berkas SyncTeX sudah dibuat, tetapi mengetuk untuk melompat antara sumber dan PDF belum tersambung.
- Di layar selebar ponsel hanya penyunting yang tampil; pratinjau berdampingan butuh tablet.
- Font sistem Android tidak bisa dipanggil lewat nama (
\setmainfont{Roboto}). Pakai font bundel seperti TeX Gyre, atau berkas .otf/.ttf di proyek.
- Baru Android dan Linux. Belum ada build Windows maupun paket Linux siap pasang.
Mengambilnya
AGPL-3.0-or-later, sama dengan ReadPaper. Silakan dipakai, diubah, dijual — tetapi siapa pun yang menerima salinannya, termasuk lewat jaringan, berhak atas sumbernya dengan syarat yang sama. Kalau suatu hari ada layanan kompilasi yang berjalan sebagai server, lisensi itulah yang menjaga sumbernya tetap terbuka. Kontribusi memakai tanda tangan git commit -s, tanpa CLA.
Untuk Linux desktop, dibangun dari sumbernya dan butuh texlive-xetex serta latexmk terpasang.