Library / SDK
web-infra-dev/modern.js avatar
web-infra-dev/modern.js

Modern.js puts routing, data acquisition and state management on top of React

A progressive web framework based on React and Rsbuild. Rsbuild: An Rspack-based build tool for the web, rebranded from Modern.js Builder.

5,051 stars425 forksTypeScriptMIT

At a glance

What is it?
Modern.js is a progressive React framework from the ByteDance open source group: you build the UI with React and adopt routing, data acquisition and state management where you need them. The build tool underneath was rebranded from Modern.js Builder to Rsbuild, and the README hands you a link to the Quick Start instead of an install command.
Who is it for?
Modern.js fits teams that want routing, data acquisition and state management without assembling them, and teams that intend to build their own framework layer on top of one, which is what ByteDance does with it. It does not fit an evaluation that has to happen from the repository alone: the install command, the configuration reference and the mapping from the old Modern.js Builder name are all on the documentation site instead.
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 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • web-infra-dev/modern.js5,051 ★ · +21
Star history
Repository2026-07-312026-11-14
web-infra-dev/modern.js5k5.1k

21 Stars in the last 106 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

ByteDance builds its own upper-level frameworks on Modern.js

The provenance matters more here than the feature list. The README states that at ByteDance, Modern.js is used to build upper-level frameworks that have supported the development of thousands of web applications. In other words, the library's shape was decided by people assembling an internal framework for many teams rather than by one application's needs, and that shows up in what it claims to own: routing, data acquisition and state management, which are the three things an internal framework ends up writing for everyone. If you are choosing a React framework for a single product, the question to ask is whether a project designed as a building block for other frameworks hands you more conventions than you wanted. The description calls it a progressive web framework based on React and Rsbuild, written in TypeScript, MIT licensed, with main as the default branch.

React first, then routing, data acquisition and state management on demand

Progressive is the load-bearing word in the design, and it cuts both ways. You build the interface with React and then adopt pieces of Modern.js to solve common application requirements, which the README frames as taking them one at a time rather than all at once. For review, that is useful: a change that imports the framework's routing touches a layer a change that only adds a component never touches. The cost is that nothing forces the framework's conventions on you early, so an application can end up with one screen using the framework's data acquisition and another fetching by hand, and this repository documents no lint rule or codemod that would catch the drift. Progressive adoption is a feature you have to maintain yourself, and it is worth deciding where the line sits before the first screen is written rather than after the twentieth.

The build tool was renamed from Modern.js Builder to Rsbuild

The ecosystem list carries a rename notice in plain sight: Rsbuild is described as an Rspack-based build tool for the web, rebranded from Modern.js Builder. Anyone arriving from an older tutorial, an issue thread or an internal wiki will search for Modern.js Builder and land on a project called Rsbuild instead, and nothing here maps the old configuration keys onto new ones. The practical source of truth for configuration is therefore the documentation site at https://modernjs.dev rather than this file. The other three siblings tell you where the rest of the stack sits: Rspack is the Rust-based bundler underneath, Rspress is a static site generator on the same bundler, and Rslib is a library development tool. All four come from the same group, so a question about where a bug lives can often be answered by which sibling the failing package belongs to.

The Getting Started section is a link, not a scaffold command

If you came for a create command, it is not in this repository. The Getting Started section is a single sentence pointing at the Quick Start guide on the documentation site, and no package list, config file or application version constraint appears anywhere in the README. What the repository does spell out is how its own monorepo is set up, which is the closest thing to a first run you can copy verbatim. The root package.json wires `setup` to a reset followed by a workspace install, and the reset removes node_modules by glob:

bash
npx rimraf --glob ./**/node_modules
pnpm install

Workspaces come from pnpm-workspace.yaml, with pnpm-lock.yaml committed and a .nvmrc pinning the Node version for contributors. One thing to know before you run that install: the root `prepare` script is attached to a build and a git hook install, so any step that triggers prepare compiles every `@modern-js/*` package first. That is a different cost from installing a published framework, and it is why an application install has to come from the docs site.

Every package build runs through Nx with maxParallel=4

The monorepo build is a single Nx invocation, and the flags around it say what a cold build costs. `prepare-build` sets NX_DAEMON=false, so no background daemon survives between runs, sets NX_REJECT_UNKNOWN_LOCAL_CACHE=0, so unknown local cache entries are accepted instead of rejected, then builds every `@modern-js/*` package with the documentation packages excluded and four jobs at a time:

bash
cross-env NX_DAEMON=false NX_REJECT_UNKNOWN_LOCAL_CACHE=0 nx run-many -t build -p @modern-js/* --exclude=@modern-js/main-doc,@modern-js/module-tools-docs --maxParallel=4

There is a narrower sibling for working on one area, `build:required`, which builds `@modern-js/builder`, `@modern-js/bff-core`, `@modern-js/utils`, `@modern-js/i18n-utils` and `@modern-js/runtime-utils` and nothing else. A third variant, `prepare-build-continue`, adds `--nxBail=false` and echoes a message when packages fail, which tells you partial build failures are an expected state during preparation rather than an incident.

biome check and rstest are the two quality entry points

Checks and linting run through `rs check` and `rs lint`, and unit tests run through rstest with rstest.config.mts holding its configuration:

bash
rs check
rstest

Snapshot updates are a flag on the same binary, `rstest -u`. The heavier suites are delegated to a `tests/` directory with its own scripts, `test:framework` and `test:builder`, which the root forwards with `cd tests && pnpm run test:framework`. The examples directory shows the integration range a user is expected to need: examples/test-vitest and examples/test-playwright each wire a different runner into a Modern.js app, next to examples/storybook, examples/react-compiler, examples/sse and examples/module-federation. Two runners in one repository say two things at once: how much a framework absorbs on your behalf, and how many combinations your own upgrade has to keep working.

Rsbuild is the same toolchain without the framework layer

The nearest alternative is Rsbuild, and the answer sits in the rename rather than in a comparison table. Rsbuild is an Rspack-based build tool for the web. Modern.js is the framework layer that reaches for routing, data acquisition and state management and, before the rename, carried its own builder. Taking Rsbuild alone means keeping the bundler and assembling the application layer yourself, and giving up the internal-framework layer that ByteDance says has supported thousands of web applications. Going the other way, staying on plain React with another bundler means you own the rendering story, and the example list shows how much of that story is separate work: examples/modern-js-deploy-csr and examples/modern-js-deploy-ssr are distinct projects, with a deploy example alongside each. The ecosystem list names no other bundler, so no comparison against one is documented in this repository.

Changesets cut the releases, credits explain the surprises

Release cadence is visible in the tags: v3.10.3 on 2026-10-22, v3.10.4 on 2026-10-29 and v3.11.0 on 2026-10-30, three releases in nine days, and the last push to main was on 2026-11-02. Changesets drives that. `change` adds an entry, `bump` runs `pnpm --filter @scripts/check-changeset bump`, `pre:enter` and `pre:exit` manage a prerelease mode, and `gen-release-note` and `get-release-version` live under scripts/. Because versioning happens per package through changesets, adopting the framework in an application is a package-level upgrade rather than a repository-wide one. Read the credits before depending on behaviour: `@modern-js/bundle-require` is modified from bundle-require, `@modern-js/plugin-data-loader` borrows code from remix, `@modern-js/babel-plugin-module-resolver` is modified from babel-plugin-module-resolver, and the plugin hooks API is referenced from farrow-pipeline. MIT covers the framework itself, with third party licences collected in THIRD-PARTY-LICENSE.

Editorial conclusion

Modern.js fits teams that want routing, data acquisition and state management without assembling them, and teams that intend to build their own framework layer on top of one, which is what ByteDance does with it. It does not fit an evaluation that has to happen from the repository alone: the install command, the configuration reference and the mapping from the old Modern.js Builder name are all on the documentation site instead. Before adopting, check two things. Whether your React and Node versions clear what the docs site asks for, because this repository pins a .nvmrc and a pnpm workspace with no framework compatibility table. And whether a cold build of every `@modern-js/*` package through Nx fits your CI budget, since the root `prepare` script hangs that build off install. The last push to main was on 2026-11-02 and the newest tag is v3.11.0 from 2026-10-30.

Frequently asked questions

What is Modern.js?

Modern.js is a progressive web framework based on React and Rsbuild. You build the application UI with React, then adopt Modern.js features for common requirements such as routing, data acquisition and state management.

How does Modern.js compare with Rsbuild?

Rsbuild is an Rspack-based build tool for the web, rebranded from Modern.js Builder, so it is the build layer. Modern.js sits above that layer and adds routing, data acquisition and state management to a React application.

Is Modern.js a replacement for React?

No, it builds on React rather than replacing it. The README describes using React for the application UI and then adopting Modern.js features such as routing, data acquisition and state management as those requirements appear.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
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/web-infra-dev-modern-js.svg)](https://hysenlabs.com/projects/web-infra-dev-modern-js)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/web-infra-dev-modern-js.svg)](https://hysenlabs.com/projects/web-infra-dev-modern-js)

Was this useful?