Skip to content

Repository files navigation

Lukaisu

Lukaisu (Finnish: a quick read-through) is a mobile app for learning languages by reading, in the tradition of LWT — Learning with Texts. Add a language, paste in a text, and read it with every word colour-coded by how well you know it. Tap a word to save a translation, then build your vocabulary with built-in spaced repetition (FSRS-based).

It's local-first: everything is stored on your device and the core read/save/review loop works fully offline, with no account and no server. Connecting a Lukaisu Server is optional, and unlocks the things a phone can't do well on its own: high-quality Chinese/Japanese word splitting, text-to-speech, audio transcription, and discovering new texts online — the same pattern as the Nextcloud mobile client (a free client for a self-hostable free server).

The app is named after lukaisu.org; its package name (org.lukaisu.app) is permanent once published. MIT licensed.

Features

  • Read texts with tap-to-look-up words, colour-coded by how well you know them.
  • Save words and review them with spaced repetition, fully offline.
  • Create your own languages, or start from a built-in preset; a fresh install seeds a few sample texts so you can start reading immediately.
  • Right-to-left languages (Arabic, Hebrew, ...) work offline.
  • Optional: connect a Lukaisu Server for Chinese/Japanese word splitting, text-to-speech, transcription, and online text discovery — including plain-HTTP servers on your LAN.
  • A thin Capacitor shell over the system WebView (no Chrome dependency, no Google Play Services, no tracking) — works on de-Googled phones.

How it works

  1. First run is local. A fresh install seeds a few language presets and sample texts into an on-device database and opens straight to your library — no server picker in the way.
  2. Reading happens on-device. Texts are parsed into words locally (the space-separated and right-to-left parsers run in TypeScript); word status, translations, and review scheduling are stored and updated in the local database (IndexedDB via Dexie).
  3. Connecting a server is optional. A bundled connect screen (reachable from Settings) validates a Lukaisu Server by probing GET /api/v1/version; once connected, the server-enhanced extras light up. With no server, CJK languages fall back to character-by-character parsing — functional, lower quality — and the app never blocks on the network.

This repo owns the reading frontend outright (webapp/ — TypeScript, Svelte 5, CSS themes): reader, library, on-device database, parsers, and the local-first data layer all live and are built here. No other repository checkout is involved in building the app.

Connecting a server (optional)

A server is only needed for the enhanced features above. When you connect one:

  • Point the app at a Lukaisu Server (needs GET /api/v1/version; for multi-user login, the /connect flow). The API originated in LWT 3.x, so compatible LWT 3.1+ servers also work.
  • Plain-HTTP servers (e.g. http://192.168.1.10:8010 on your LAN) work — the app allows cleartext traffic. Self-signed HTTPS certificates do not work in the Android WebView; on a LAN prefer plain HTTP, or use a real certificate (e.g. Let's Encrypt / a reverse proxy).
  • The bundled frontend calls the server cross-origin, so the server must allow the app's WebView origin via CORS_ALLOWED_ORIGINS=https://localhost.

Building

Requirements: Node 20+, JDK 21 (Gradle 8.14 does not run on Java 25), Android SDK (platform 36).

npm install
npm run apk:debug           # build the app, bundle it, assemble the APK
# → android/app/build/outputs/apk/debug/app-debug.apk

apk:debug chains syncbuild (vite build --config webapp.vite.config.tsdist/), build:themes (theme CSS the dark-mode toggle loads at runtime), cap sync — then gradlew assembleDebug. Expects JAVA_HOME/sdk.dir to be set up (android/local.properties holds sdk.dir).

Dev loop: npm run dev (Vite HMR against webapp/). npm test runs the frontend's vitest suite; npm run typecheck/npm run lint cover TS + Svelte.

Additional scripts:

  • npm run apk:release — build a signed release APK (requires keystore setup)
  • npm run e2e — run Cypress end-to-end tests
  • npm run test:watch — vitest in watch mode

To test against a local Lukaisu Server: from a lukaisu-server checkout, docker compose up (http://localhost:8010); set MULTI_USER_ENABLED=true in its .env to exercise the login flow. For phone-on-LAN testing use the machine's LAN IP.

Repository layout

  • webapp/ — the reading frontend (TypeScript, Svelte 5, CSS themes): reader, library, on-device database (IndexedDB/Dexie), parsers, router. webapp.vite.config.ts builds it, webapp-tests/ tests it.
  • webapp/app/ — page entry points (HTML + TS) for each route, Svelte components, and svelte.config.js.
  • webapp/js/ — shared TypeScript modules including client.ts (app bootstrap), sw.ts (service worker for PWA-like behavior), and the offline-first data layer.
  • locale/en/ — a frozen duplicate of lukaisu-server's English strings, bundled at build time as the offline i18n fallback for when no server is connected.
  • public/ — static WebView chrome (error.html, the app icon) copied into dist/ at build time.
  • capacitor.config.ts — app id/name (org.lukaisu.app), WebView navigation policy, cleartext permissions.
  • android/ — the Capacitor Android project (committed per Capacitor convention; local.properties and build outputs are ignored).
  • scripts/ — build utilities (e.g., build-themes.js for dark/light theme CSS).
  • cypress/ — end-to-end test suite.
  • fastlane/ — F-Droid/Play store metadata (title, descriptions, changelog, icon).

Status

Not yet published to F-Droid or the Play Store. See ROADMAP.md for release status and what's next.

Support

Lukaisu is free and non-profit. If you'd like to support its development, you can donate on Open Collective.

About

Lukaisu — Android client for self-hosted LWT (Learning with Texts) language-learning servers

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages