Open-source project
electh/ReactFlux avatar
electh/ReactFlux

ReactFlux is a browser front end for Miniflux that you host yourself

A Simple but Powerful RSS Reader for Miniflux

521 stars127 forksJavaScriptMIT

At a glance

What is it?
ReactFlux is a third-party web frontend for Miniflux, and its whole value is the reading experience rather than the feed handling, since all of that stays on the server. It ships as static files, so it deploys to Cloudflare Pages, to any static host, to Vercel or as a Docker image, and it can be served from a subpath if you set one at build time.
Who is it for?
Adopt ReactFlux if you already run Miniflux and want a better reading interface without changing your feed backend, since it talks to the existing Miniflux API and keeps all the data where it is. Skip it if you want to replace Miniflux rather than front it, because it is a frontend and needs a working Miniflux instance behind it.
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 received new commits within the last day.
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 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A frontend, with Miniflux doing the work

ReactFlux is a third-party web frontend for Miniflux, aimed at providing a more user-friendly reading experience. The supported Miniflux versions are 2.3.2 and higher.

That single sentence sets the boundaries of the project. Miniflux is a feed server: it fetches the subscriptions, stores the articles, handles the read state, does the full-text extraction and exposes an API. ReactFlux is the part you look at.

So there is no new feed infrastructure here and no migration. You keep your Miniflux instance, with all its feeds and all its state, and you point a browser at a different front end for it. The API key or the account you log in with is the same one, and the articles you already marked read are the articles that are still marked read.

The quick start makes that concrete in three steps. Ensure you have a working Miniflux instance. Either use the online demo instance or deploy ReactFlux using one of the methods. Then log in using your Miniflux username and password or your API key, with the API key recommended.

The API key is the better option for a reason that is worth stating: a key can be revoked and can be scoped, whereas a shared account password is the credential that also lets you change the Miniflux configuration itself.

The feature list is long and it is all reading-side. The interface is modern, the layout is responsive with touch gestures, long-press context menus and collapsible navigation, and there is dark mode with custom themes.

The reading experience is the deepest part of the list. There are column, list and card layouts with configurable covers and summaries, font family and size settings, article width adjustment, title alignment options, an image viewer with zoom, fullscreen and image navigation, article attachments with image previews and audio and video playback, footnotes enhancement, code syntax highlighting, estimated reading time, and configurable browsing direction and source-link behaviour.

Several of those are things you would not expect from a feed reader at all, which tells you what the project is for. Footnote rendering and code highlighting are article presentation problems, and a feed reader that renders articles well is doing something different from one that lists them.

The project is MIT licensed, JavaScript as the primary language, with the default branch main and the last push on 2026-10-20. There are no GitHub releases, which is consistent with a frontend deployed as static files rather than distributed as a package.

The management features, and the two that stand out

Under article and feed management there is a set of features that go further than a reader usually does.

Miniflux full-text search is exposed with phrases, OR and exclusions, which means the search is the server's search rather than a client-side filter over what happens to be loaded. Filter articles by read status and publish date, and batch operations for feeds, so you can act on many subscriptions at once.

Per-account homepages are the feature that changes how the reader behaves. You can target built-in views, categories or feeds, so the front page is your own selection rather than the server's default.

Full-text fetching support means ReactFlux can ask Miniflux to fetch the full article rather than showing the feed's summary. That is the difference between a reader that shows you a teaser and one that shows you the article, and it is the feature that makes the tool a reader rather than a list.

De-duplicate articles by hash, title or URL is a subscription hygiene feature that most people only notice when they are annoyed by it. The same story syndicated from several feeds appears several times, and the deduplication lets you choose how aggressively to collapse them, from an exact content hash through to matching on the title.

Auto mark articles as read while scrolling is the feature that decides whether the tool becomes a habit. If marking read is a click per article you will stop doing it, and if you never mark anything read the read state becomes useless. Doing it on scroll makes the state accurate at no cost.

The advanced list has four items that are worth naming. Keyboard shortcuts, which are customizable. Settings backup import and export, so your layout and preferences survive a change of machine. Save articles to third-party services. And two batch operations on the server side: batch update the host of filtered subscription URLs, which is useful for replacing RSSHub instances, and batch refresh errored subscriptions.

That RSSHub one is a genuinely specific need. RSSHub is a service that turns a page into a feed, and the instance you use can go down or change domain, and if you have fifty subscriptions pointing at the old host you need a way to repoint them all at once. Very few feed readers think about that, and this one does.

There is also internationalisation with six languages, Deutsch, English, Español, Français, 日本語 and 简体中文, with the reader language separate from the interface language in the same way the deployment path is separate from the build.

Deploying the static build

ReactFlux is built with React and generates a set of static web files after building, which can be directly deployed on Cloudflare Pages. The framework preset to select is Create React App.

That instruction is slightly odd given the project uses Vite, and it is a small example of the friction in the Cloudflare Pages model where the preset has to match how the project was scaffolded. The build command is vite build and the output is a directory of static files, which is the part that matters.

The second option is the pre-built files on the gh-pages branch, which you can deploy to any static hosting service that supports single-page applications.

There is a caveat about those pre-built files that is worth reading carefully. The files in gh-pages are built for this repository's GitHub Pages path, which is /ReactFlux/. If your deployment uses a different path, build from source with VITE_BASE_PATH as described below.

So the pre-built branch is only useful if you are serving from exactly that path, and otherwise you build. That is the standard trade for a static frontend and it is stated plainly rather than left to be discovered.

Then there is the requirement that applies to every static deployment of a single-page application. Make sure to configure URL rewriting to redirect all requests to index.html. If you are deploying using Nginx, you might need to add the following configuration:

nginx
location / {
    try_files $uri $uri/ /index.html;
}

Or using Caddy, you might need to add the following configuration:

caddyfile
try_files {path} {path}/ /index.html

The reason is that the reader is a single-page application, so every deep link is a client-side route. Without the rewrite, a refresh on a URL like /article/123 returns a 404 from the web server rather than handing the route to the application.

Two more deployment routes are given. There is a Vercel deploy button, and there is a Docker image on Docker Hub, which you run with:

bash
docker run -p 2000:2000 electh/reactflux

or with Docker Compose, using the docker-compose.yml in the repository:

bash
docker-compose up -d

And there is a repository at the root that holds the Caddyfile, the Dockerfile, the docker-compose.yml and a .dockerignore, so the container route is a first-class deployment rather than an afterthought.

Deploying under a subpath, which needs a rebuild

The subpath section is the one to read before you deploy, because it contains a constraint that surprises people.

The public path is embedded in the frontend bundle at build time, so changing it requires a rebuild.

That is the whole difficulty. Because the bundle is built with the path baked in, a static build is not relocatable, and there is no way to move it to a different path after the fact. Set VITE_BASE_PATH to a slash, or to an absolute path that starts and ends with a slash. Path segments may contain ASCII letters, numbers and a small set of punctuation characters.

bash
VITE_BASE_PATH=/reactflux/ pnpm run build

The build output goes to a directory named build, and the instruction is to make the contents of that directory available at the same URL path and route SPA deep links to that path's index.html.

The Caddy example shows the shape:

caddyfile
root * /srv
try_files {path} {path}/ /reactflux/index.html
file_server

The root is the parent directory rather than the build directory itself, and the try_files fallback names the index.html with the path prefix in it. That last detail is the one to get right, because a fallback to a bare /index.html would serve the application at the wrong path and the application's own routing would then break.

The Docker image can be built for the same path, and its bundled Caddy configuration places and serves the files automatically:

bash
docker build --build-arg VITE_BASE_PATH=/reactflux/ -t reactflux:subpath .
docker run -p 2000:2000 reactflux:subpath
# Open http://localhost:2000/reactflux/

The build argument is the same VITE_BASE_PATH, passed through to the frontend build, and the container is run with the port mapped. And then the last line of the section is the operational warning: a reverse proxy must preserve the configured prefix.

That is the failure mode to plan for. If you serve ReactFlux at /reactflux/ behind Nginx and the proxy strips the prefix, the application asks for assets at the wrong URLs and the page renders unstyled. The prefix has to survive every hop.

It is a fair amount of care to describe, and the documentation is precise about all of it, which suggests the author has deployed this in several different shapes.

Translations, and how to help with one

The translation guide is unusually detailed for a project of this size, and it is worth reading because it tells you what is actually hard about adding a language.

To help translate ReactFlux into your language, contribute to the locales folder and send a pull request. Additionally, you need to add a README file for the respective language and reference it in all existing README files. And you should modify parts of the source code to include the i18n language packages for Arco Design and Day.js.

That third step is the interesting one and it is not obvious. ReactFlux uses the Arco Design component library and Day.js for dates, and both of those ship their own translation files. So adding a language to ReactFlux is not only translating the app's own strings; you also need the component library and the date library to speak the same language, otherwise your date pickers and empty states stay in English inside an otherwise translated interface.

The documentation then points at a specific pull request, PR number 145, for the detailed changes. That is a helpful convention, because the diff of an existing translation is the clearest possible specification of what a new one needs to touch.

The current translators are listed in a table with links to their profiles, and the five named languages cover the six supported ones, since English is the base.

The READMEs themselves are translated too, with a link row at the top of the main README for Deutsch, Español, Français, 日本語 and 简体中文. So the documentation is part of what gets translated, not an afterthought, and the guide requires that each new language's README is referenced from all the existing ones.

That last rule is the kind of instruction that keeps a translated documentation set from fragmenting. It is a small amount of discipline and it is the difference between six READMEs that stay in step and six that drift apart within a year.

The repository and the tooling

The repository layout shows a modern frontend project with a focus on tooling.

There is src/ for the application, public/ for static assets, scripts/ for the build-time scripts, docs/ for the translated READMEs and images/ for the screenshots. The configuration is modern: vite.config.js for the bundler, eslint.config.mjs for the flat-config lint setup, jsconfig.json for the JavaScript configuration, and .prettierrc with .prettierignore for formatting.

There is a lefthook.yml, which is a git hooks manager that runs the checks on commit rather than relying on each contributor to remember them. That is the same idea as the pre-commit configuration in a Python project and it is worth having in a repository with many contributors.

There is a pnpm-workspace.yaml and a pnpm-lock.yaml, and the package metadata pins the package manager to pnpm 11.21.0 and requires Node 22.22.0 or newer.

The script list is where the interesting engineering shows. There is a dev script and a build script, and an analyze script that builds in a special analyse mode. There is a preview script that builds first and then previews, which is the correct order if you want to preview what will actually ship.

Then there are the font scripts. test:fonts runs the node test runner over the scripts, and validate:fonts runs a dedicated validation script. So the fonts shipped with the application are tested, which is unusual and suggests that font licensing or subsetting has caused problems that needed a check.

There is a lint family with several variants: a plain lint, a cache clear, a fast variant using a cache with a content strategy, and a fix variant. The fast variant with the content strategy is worth noting, because it means the cache invalidates when the file content changes rather than when its timestamp does, which is the correct behaviour for a repository where files are rewritten often.

And there is a knip script, which is a tool for finding unused files, dependencies and exports in a project. Running it as part of the script list is a statement that the project cares about not accumulating dead weight, which matters in a frontend where a dependency nobody notices is easy to leave in place for years.

Editorial conclusion

Adopt ReactFlux if you already run Miniflux and want a better reading interface without changing your feed backend, since it talks to the existing Miniflux API and keeps all the data where it is. Skip it if you want to replace Miniflux rather than front it, because it is a frontend and needs a working Miniflux instance behind it. Verify first which Miniflux version you run, since 2.3.2 and higher are supported, and where you plan to host it, because the public path is baked into the bundle at build time and changing it means a rebuild.

Frequently asked questions

What is ReactFlux and what does it need?

It is a third-party web frontend for Miniflux, aimed at providing a more user-friendly reading experience, and it supports Miniflux versions 2.3.2 and higher. You need a working Miniflux instance, then either use the online demo or deploy ReactFlux yourself, and then log in with your Miniflux username and password or an API key, with the API key recommended. All the feed handling and storage stays on the Miniflux side.

How do I deploy ReactFlux?

It builds into static files with Vite, so it goes to Cloudflare Pages by selecting the Create React App framework preset, to Vercel with the deploy button, to any static host that supports single-page applications using the pre-built files on the gh-pages branch, or as a Docker image with `docker run -p 2000:2000 electh/reactflux`. Whichever you choose, you must configure URL rewriting so all requests go to index.html, and the Nginx and Caddy configurations are given in the documentation.

Can I deploy ReactFlux under a subpath?

Yes, but the public path is embedded in the frontend bundle at build time, so changing it requires a rebuild. Set VITE_BASE_PATH to a slash or to an absolute path that starts and ends with a slash, and build with `VITE_BASE_PATH=/reactflux/ pnpm run build`. Then serve the contents of the build directory at that same path, route deep links to that path's index.html, and make sure any reverse proxy preserves the configured prefix.

Official sources

  1. electh/ReactFlux on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
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/electh-reactflux.svg)](https://hysenlabs.com/projects/electh-reactflux)

Was this useful?