Fudoki: a browser-based Japanese analyser that reads text back to you
An interactive Japanese text analysis and speech synthesis web app
At a glance
- What is it?
- Fudoki is a JavaScript web app that segments Japanese text with Kuromoji, tags each token with its part of speech, shows readings in kana and romaji, and reads passages aloud through the Web Speech API, all without an account or a server. It is a static site with a vendored dictionary, so most of the engineering is in the interface rather than the plumbing.
- Who is it for?
- Adopt Fudoki if you are learning Japanese, you want your study documents to stay on your own machine, and you want analysis and audio in one place without installing anything. Do not adopt it for a corpus workflow, since the dictionary data is sliced for interactive lookup rather than bulk processing, and do not ship its dictionary data inside a product without checking the share alike terms of the JMdict licence.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: Japanese hides its own structure
Japanese text is difficult for a learner to take apart. There are no spaces between words, the grammar leans on particles that carry no meaning of their own, and reading a sentence aloud means resolving kanji into kana before you can say it. A learner reading an article has to stop every few words to work out where one word ends and the next begins, and that interruption is what makes reading Japanese exhausting.
Fudoki is a browser-based tool that makes that structure visible. It segments Japanese text, shows part-of-speech tags and readings, and reads text aloud through the Web Speech API. The framing is local by design: no account and no cloud sync, with the documents living in the browser.
The audience is Japanese learners and anyone reading Japanese technical or literary text who wants a parser next to the text. The name comes from Japan's ancient regional gazetteers, the Fudoki, which is a nice touch for a tool whose purpose is to make a written language legible.
The scope is a single page application, and that is the key to understanding the engineering. There is no framework, no server component and no build step in the documented workflow. The repository layout is a handful of files, the application is served by a plain static file server, and the whole dictionary is loaded from local files. The complexity is in the interface and in the Japanese, not in the architecture.
The mechanism: Kuromoji segmentation and the Web Speech API
The analysis engine is Kuromoji.js, the JavaScript port of the Kuromoji morphological analyser, and the project package lists it alongside kuroshiro and the kuroshiro-analyzer-kuromoji plugin that combines them with a converter for kana and romaji readings. The package also depends on jmdict-simplified-node.
What that produces is a stream of tokens, each with a surface form, a part of speech and a reading, and the interface renders those tokens as coloured pills. The part-of-speech colours are fixed and simple: noun is green, verb is blue, adjective is orange, adverb is purple, particle is red and interjection is yellow. Each token pill carries a small colour dot and a matching underline.
The particles are the interesting category. A particle such as wa or ga is exactly the thing a learner cannot spot in raw text, and colouring it red in the token stream turns a grammatical marker into a visible object. That single decision is more instructive than any amount of glossary.
Speech comes from the Web Speech API, which is a browser API rather than a bundled model, and that choice has consequences worth naming. The app does not ship a voice, so the available voices are the ones the operating system and browser provide, which is why the interface exposes voice selection and a speed range of 0.5 to 2.0. The quality of the reading, and the set of voices at all, are properties of the machine rather than of the app.
The second consequence is the behaviour of settings during playback. Changing the voice or the speed while something is playing restarts the speech near the current position rather than applying the change live, and the settings persist in localStorage. That is a limitation of the underlying API, absorbed gracefully rather than hidden.
The document model: a sidebar, autosave, and an edit and analyze toggle
The main area is a segmented view with two modes, edit and analyze, and the whole thing hangs off a left sidebar of documents with search, favourites, filters and autosave.
The sidebar is the part that turns a demo into a study tool. Search and filters let you find a document, favourites give you a reading list, and autosave means you do not lose what you typed. The main area switches between editing text and seeing the analysed version, which is the useful loop: write or paste a passage, switch to analyze, and read it with the structure exposed and the audio following along.
The editing experience is a Markdown editor, EasyMDE, with a deliberately minimal toolbar covering bold, italic, heading, quote, lists, link and preview, plus a full-screen side-by-side preview, with entry points for both desktop and mobile. A Markdown editor for a reading tool is a sound choice, since it gives plain text that can be exported and re-imported, and it lets a user paste text from anywhere without fighting a rich text editor's formatting rules.
The rest of the interface work is visible in the feature list. There are dark and light themes, custom dropdowns and dialogs drawn by the application itself rather than native controls, and a multilingual interface covering Japanese, English, Chinese and Spanish. The design tokens, the colours, the radii and the part-of-speech hues, live as CSS variables in the stylesheet, which means the POS palette is a design decision rather than a set of hard coded values scattered through the code.
Data portability is handled with JSON export and import, and a PWA offline pack makes the whole thing work without a network connection.
Dictionary lookup: JMdict slices and Tanaka Corpus examples
Clicking a token opens a word card with translations, the reading and example sentences from the Tanaka Corpus, and the documentation is specific about how that is delivered: offline slices, lazy-loaded.
That detail is the design decision worth pausing on. The dictionary data is not shipped as one large file that is parsed at startup. It is split into slices under the dictionary directory in the static files, and a slice is fetched only when a word is looked up. For a language with tens of thousands of entries, that is the difference between an app that starts instantly and one that downloads a large archive before it can be used.
The development notes also say where the data comes from and how the example sentences are produced: updated JMdict data goes under the dictionary directory, and the example sentences come from a build script in the tools directory. So the dictionary is a build artefact of the project rather than something fetched at runtime from a third party.
The corpus choice is the Tanaka Corpus, credited to EDRDG and tatoeba.org, which is a well known source of example sentences in Japanese study. Sentences from a real corpus are more instructive than invented ones, because they show the word in a context someone actually wrote.
The lazy loading has a cost. The first lookup of a word in a slice pays for the download, so a study session that hops across many words will fetch many slices. On a slow connection that is a visible pause, and it is the main reason to use the offline pack rather than the hosted site.
Reading mode: an overlay that follows the spoken line
Reading mode is a distraction-free overlay that follows the line currently being spoken, with a close button and a toggle that stays reachable while the mode is active.
That is a genuinely useful idea for a language learner, because the failure mode of any read-aloud feature is that you end up looking at the whole page while a voice reads somewhere inside it. Following the spoken line means your eyes stay in sync with the audio, and the overlay removes the surrounding document from view so the only thing competing for attention is the sentence in front of you.
The playback controls around it are careful in small ways. Pause and resume have their own separate button, and the play button turns into a stop icon while something is playing. Those are the kind of details that separate a control that works from one that is merely present.
The speech itself can be triggered at three granularities: a single word, a line, or the whole text. Combined with the speed control, that gives a study workflow where you replay one word, listen to a sentence at a slower speed, and then hear the passage at normal pace.
The interface also records the state of the player in localStorage, and the application is mobile-first with a document drawer, a bottom action dock and safe-area handling, with 390 by 844 treated as a first-class size. The documentation for the mobile layout is backed by screenshots in the repository, taken across desktop, tablet and mobile widths in both dark and light themes.
Running it locally, and what the repository actually holds
There is no build step to run the application. The documentation gives one command:
python3 -m http.server 8000and then you open the site on port 8000. The package.json reflects the same thing, with the start, dev and serve scripts all pointing at the same static server, and the main field pointing at index.html.
The repository layout is small and flat:
fudoki/
βββ index.html
βββ static/
β βββ main-js.js
β βββ segmenter.js
β βββ styles.css / mobile.css
β βββ libs/
β βββ kuromoji.js
β βββ dict/
β βββ *.dat.gz
βββ README.mdTwo files carry most of the application logic, main-js.js and segmenter.js, with the third-party libraries vendored under static/libs, including the compressed dictionary data files. The top-level entries add a manifest.json and a service-worker.js, which are the PWA pieces, along with a CNAME for the hosted site, an AGENTS.md, a package-lock.json, a tools directory, a docs directory and a screenshots directory.
Two development habits in the documentation are worth copying. After editing the JavaScript, run node --check static/main-js.js to catch a syntax error before opening the browser, and keep localStorage keys behind the fudoki: prefix so that the app's stored state does not collide with anything else on the same origin.
The quality process is visible too. There is a UI audit document from 2026-10-08 with findings numbered UA-01 to UA-20 and before and after evidence per round, and the screenshot directory holds images at several breakpoints, from 1920 by 1080 down to 320 by 720, in both themes. A project that keeps its own audit trail like that is one that takes its interface seriously.
Licences, the data question, and where the tool stops
The application code is MIT licensed, and the repository also ships a LICENSE file and contribution guidance in the project documentation.
The data is where the licence obligations are not uniform, and this is the part to read carefully if you plan to redistribute. The project lists four components: the MIT licence for the app, Kuromoji.js under the Apache License 2.0, JMdict under Creative Commons Attribution-ShareAlike 3.0, and the Tanaka Corpus example sentences under CC BY 2.0 FR from EDRDG and tatoeba.org.
The share alike term on JMdict is the one that matters for anyone thinking about shipping this. A share alike licence asks that derivatives carry the same terms, and a dictionary file embedded in a product is a different situation from a dictionary file sitting in a personal browser cache. This is not legal advice, and the practical advice is simply to read the licence text for JMdict before you put the data anywhere other than your own machine.
As a tool, the limits are equally clear. It is a single-purpose app for reading and studying Japanese, and the dictionary is tuned for interactive lookup rather than for analysing a large corpus. The speech depends on the browser and operating system, so the voice list and the Japanese voice quality differ between platforms, and the offline pack, while useful, is something you have to download before you need it.
The repository is not archived, the last push was on 2026-10-08, and the project has no GitHub releases, so the hosted site at fudoki.iamcheyan.com is the artefact most people will actually use, and the source is the thing to read if you want to extend it.
Editorial conclusion
Adopt Fudoki if you are learning Japanese, you want your study documents to stay on your own machine, and you want analysis and audio in one place without installing anything. Do not adopt it for a corpus workflow, since the dictionary data is sliced for interactive lookup rather than bulk processing, and do not ship its dictionary data inside a product without checking the share alike terms of the JMdict licence. Before you rely on it, run it locally with python3 -m http.server 8000, check the speech voices on your own platform, because the Web Speech API implementation differs between browsers and operating systems, and confirm the offline pack works before you need it.
Frequently asked questions
How do I run Fudoki locally?
Serve the repository directory with python3 -m http.server 8000 and open http://localhost:8000. The package.json scripts named start, dev and serve all run the same static server, and there is no build step to run first.
Does Fudoki send my Japanese text anywhere?
No. The project describes Fudoki as a fully local tool with no account and no cloud sync, and the documents live in your browser, with settings persisted in localStorage behind a fudoki: prefix. The dictionary data is served from local files in the static directory.
Which dictionary does Fudoki use?
JMdict for entries, with example sentences from the Tanaka Corpus credited to EDRDG and tatoeba.org. The data is stored as compressed slices under the dictionary directory in the static files and loaded lazily when a word is looked up.
What licences apply to Fudoki and its data?
The application is MIT licensed, Kuromoji.js is under the Apache License 2.0, JMdict is under Creative Commons Attribution-ShareAlike 3.0 and the Tanaka Corpus sentences are under CC BY 2.0 FR. The share alike terms on the dictionary data are the ones to check before redistributing it.
Can Fudoki read Japanese aloud?
Yes, through the Web Speech API, with play controls for a word, a line or the whole text, a speed range of 0.5 to 2.0 and voice selection. Because the voices come from the browser and operating system, the available voices differ by platform.
Official sources
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.
[](https://hysenlabs.com/projects/iamcheyan-fudoki)Was this useful?