Open-source project
hefengbao/jingmo avatar
hefengbao/jingmo

Jingmo: an offline Android reader for classical Chinese text

『京墨』开源的中华文化阅读 APP,诗(词)文(名句)、汉字、成语、词语、歇后语、绕口令、传统节日、传统色、节气、人物等。

2,218 stars206 forksKotlinGPL-3.0

At a glance

What is it?
A Kotlin and Jetpack Compose app holding roughly a million poems, 42,000 idioms and 24,000 characters, with its data split into three separate repositories after version 1.6.1.
Who is it for?
Jingmo is worth a look if you want a working reference for what a Compose reading app with a large offline corpus looks like in practice, or if you want the corpus itself, since the README invites anyone to take the data. It is not a general-purpose language learning app and the content is Chinese-language only.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 24 days ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A Kotlin reading app for classical Chinese content

Jingmo is an Android app for reading classical Chinese material, and the repository description lists its subject matter as poems and ci, famous lines, individual characters, idioms, words, xiehouyu, tongue twisters, traditional festivals, traditional colours, solar terms and historical figures. The audience is stated plainly in the README as people who like Chinese writing, literature and culture, and the project dedicates itself to them.

Technically it is a native Android application written in Kotlin, with Jetpack Compose listed among the repository topics. The minimum platform is Android 8.0. The tree is the shape you would expect for a single-module Gradle project: an `app/` directory, `build.gradle.kts` and `settings.gradle.kts` using the Kotlin DSL, a `gradle.properties`, the Gradle wrapper in both `gradlew` and `gradlew.bat` form, a `screenshot/` folder, and a `DEVELOPER.md`. There is also a `LICENSE` file carrying GPL-3.0, and a project homepage at jingmo.ruaruan.com.

The naming has a small history worth knowing. The README explains that the app was originally called something more generic, changed because it kept being confused with a well-known dictionary brand, and was renamed after a traditional Chinese medicinal ingredient. That note is dated 2023-09-10, which is roughly when the current identity settled.

Twenty content categories and the counts behind them

The substance of the project is a corpus, and the README enumerates it in twenty numbered categories with counts. Classic curated poems and prose come to 955 pieces. The larger collection of poems, ci, rhapsodies, fragments, couplets and prose is listed at 1.6 million entries. Famous lines number 10,000, historical figures 126,830, individual characters 24,228, and words 422,958.

The idiom and language categories are substantial in the same way: 49,639 idioms, 14,026 xiehouyu, 964 groups of proverbs, and 42,446 groups of riddles. Then come the smaller and more conversational sets, 45 tongue twisters, 490 couplets, 499 song lyrics, 464 groups of knowledge cards, 326 sentences and 45 poems.

The cultural reference material closes the list: 19 traditional Chinese festivals, the 24 solar terms, 161 traditional Chinese colours, and 59 entries from the World Heritage list.

Two things are worth noting about how that data is treated. The README states the data was collected from the internet and may contain errors, and it invites corrections through the project's WeChat public account rather than through the issue tracker. And it names the upstream sources it drew on, which is unusually good practice for a corpus project: cnkgraph.com, the PoetryCrawler and gushiwen repositories, chinese-poetry, the chinese-colors list, hanzi-writer and makemeahanzi for character data, the chinese-xinhua dictionary, the lunar-java calendar library, and ChineseLyrics.

Building from source needs two properties files and three data hosts

The README's build instructions are short, which is a good sign. Clone the repository:

shell
git clone https://github.com/hefengbao/jingmo.git

Then create `local.properties` with a set of keys. Three of them are API base URLs, one per data repository, which tells you the corpus is served over HTTP from three separate hosts:

code
base_url1="https://jingmo-data.pages.dev/api/"
base_url2="https://jingmo-data2.pages.dev/api/"
base_url3="https://jingmo-data3.pages.dev/api/"

The remaining keys are configuration rather than data endpoints: a user agreement URL, a privacy policy URL, an ICP registration value, and a Bugly identifier with its privacy policy URL. Bugly is the crash reporting service wired into the app, so anyone building a fork has to decide whether they want to report crashes to the original project's account or supply their own.

A second file, `keystore.properties` at the project root, carries the four signing fields, and the README leaves the values empty for you to fill in:

code
storeFile=
storePassword=
keyAlias=
keyPassword=

That is the full setup. There is no key generation step, no database to provision and no server to stand up, because the content arrives as static files over HTTP.

Why the corpus moved out of the APK in version 1.6.1

This is the single most useful thing the README says about the architecture, and it is easy to miss. The data used to be bundled inside the application, under `app/src/main/assets`. The README states that through version 1.6.0 it stayed there, and that from 1.6.1 onward it moved into three separate repositories named jingmo-data, jingmo-data2 and jingmo-data3, each on its gh-pages branch. That is what the three base URLs in `local.properties` are pointing at.

The change makes sense for a corpus this size. Shipping hundreds of thousands of characters inside an APK inflates the download and pushes updates to content through the app store, which is the wrong channel for a fix to a mis-transcribed poem. Moving it to static hosts decouples content updates from app releases, and it explains why the release notes for recent versions mention data import progress bars at all.

It also has a consequence for anyone evaluating the app offline. A first launch needs network access to populate content, and the split across three hosts means a partial failure leaves the app with incomplete data. Worth noting that the release history uses 1.15 and 1.16 tags, so confirm which version your checkout corresponds to before assuming a data path.

The README closes that section by inviting anyone who needs the data to take it, which is a considerably more open posture than most apps with private content pipelines.

Compose, desktop widgets and the release cadence

The release notes are the place to see what the project is actually working on, and they are short numbered lists rather than prose. Version 1.16.1 from January 2026 optimised the image generation feature, reworked the widget interface, and added widgets for couplets and for sentences. That is the clearest signal in the repository about direction: the app is moving toward a home screen presence, not only toward an in-app reading experience.

Version 1.15.3 from September 2025 worked on the user agreement and privacy policy confirmation dialogs and updated the data import help text, and 1.15.2 from August 2025 fixed a misaligned import progress bar in the poems and famous lines section. Read together, the last three releases are about polish on the import path and the widget surface rather than about new content, which is what a mature corpus app looks like once the corpus itself is settled.

The README also documents where updates are announced: a WeChat public account and a Bilibili channel, both under the name NowInLife, where the project posts a release note and a demo video for new features. It asks readers who use GitHub or Gitee to star the repository, and it carries WeChat and Alipay donation codes plus a sponsors page. The repository is mirrored on Gitee as well as GitHub, which is a practical detail if you are reading this from outside the usual GitHub path.

The repository is not archived, has no open issues, and the last push was on 2026-09-14.

What GPL-3.0 means if you plan to fork it

GPL-3.0 is the decision in this project that deserves a paragraph of its own, because it is unusual for an Android application and it constrains what you can do with the code in ways that are easy to discover late.

The obligation is not about the data. The corpus came from a range of upstream sources with their own terms, and the README's offer to let anyone take the data is separate from the code licence. The obligation attaches to the application source. If you modify Jingmo and distribute it, you must make your modified source available under GPL-3.0, and linking Jingmo's code into a larger application brings that application under the same terms.

That is a meaningful difference from an MIT or Apache-2.0 Android app. If your plan is to read the source, learn from it, or run it privately, the licence costs you nothing. If your plan is to take the Compose code as a starting point for a differently licensed product, GPL-3.0 is close to disqualifying, and you would be better served by reading the source for the approach and writing your own.

None of this is legal advice, and the LICENSE file in the repository is the text that governs. It is worth reading before you build, not after you have shipped something based on it.

Editorial conclusion

Jingmo is worth a look if you want a working reference for what a Compose reading app with a large offline corpus looks like in practice, or if you want the corpus itself, since the README invites anyone to take the data. It is not a general-purpose language learning app and the content is Chinese-language only. Two things to settle before you build it. First, licensing: GPL-3.0 is the licence to read carefully if you ever intend to fork rather than install, because it reaches code you link against, unlike the permissive licences most Android apps carry. Second, data location: since version 1.6.1 the corpus sits in three separate repositories on their gh-pages branches and is fetched over HTTP, so an offline install is no longer just the APK. The repository is not archived and the last push was on 2026-09-14.

Frequently asked questions

What is the Jingmo app and what does it contain?

Jingmo is an Android reading app for classical Chinese material, written in Kotlin with Jetpack Compose and requiring Android 8.0 or later. Its twenty content categories include 955 curated poems and prose pieces, 1.6 million entries across poems, ci, rhapsodies and prose, 10,000 famous lines, 126,830 historical figures, 24,228 characters, 422,958 words, 49,639 idioms, 14,026 xiehouyu and 24 solar terms.

How do I build Jingmo from source?

Clone the repository, then add a local.properties file containing three data base URLs along with user agreement, privacy policy, ICP and Bugly settings, and create a keystore.properties file at the project root with storeFile, storePassword, keyAlias and keyPassword. There is no database or server to provision, because content is fetched as static files over HTTP from the three data hosts.

Where is the Jingmo content data stored?

Through version 1.6.0 the data lived in the app under app/src/main/assets. From 1.6.1 onward it moved into three separate repositories, jingmo-data, jingmo-data2 and jingmo-data3, each on a gh-pages branch, and the app fetches it from the three base URLs configured in local.properties.

Official sources

  1. hefengbao/jingmo on GitHub
  2. License: GPL-3.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hefengbao-jingmo.svg)](https://hysenlabs.com/projects/hefengbao-jingmo)