Open-source project
mirrorz-org/mirrorz avatar
mirrorz-org/mirrorz

MirrorZ is one catalogue of every mirror site, in one JSON file each

Your next MirrorS is not MirrorS, nor MirrorSes, it's MirrorZ.

771 stars41 forksTypeScriptMIT

At a glance

What is it?
MirrorZ defines a data format, a mirrorz.json per site, and a site that turns a pile of heterogeneous mirrors into a single searchable list, and the status string format is where most of the protocol's cleverness sits.
Who is it for?
MirrorZ suits an operator who runs a mirror site and wants it visible in one list rather than several, and it suits a user of a Linux distribution who needs to find a working mirror without trying four URLs in turn. It is the wrong tool if you run a single mirror with no interest in being indexed, because the whole value is aggregation, and it is the wrong tool if you need a package manager to consume the data directly, since the format is aimed at a web interface.
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 October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is that mirrors are heterogeneous

MirrorZ states the problem in a few sentences. Mirror sites are heterogeneous, and it is hard for a single mirror to provide all mirrors, so differences occur. For end users this is not a good experience, because they need to search for available mirrors. The stated remedy is that MirrorZ is intended to include all mirrorS, so a unified interface is needed, and the project describes itself as a final site for Mirror sites. The live sites are mirrorz.org and the list at mirrors.cernet.edu.cn, so this is a working deployment rather than a proposal. The audience is two sided, the operators of mirror sites who want to be findable, and the users of distributions and package ecosystems who need one address that works rather than a list to try.

Each site publishes one mirrorz.json and that file is the whole contract

The data format is version 1.7, and a mirrorz.json in that format describes all the data of one mirror site. The top level has a version, a site object for the global information, an info array for the category view, and a mirrors array for the list view. The site object carries the url, a logo, a dark mode logo, an abbreviation, a name, a homepage, an issue tracker, a request page, an email, a group, a disk usage note, a note, a big file for speed testing, and a disable flag. Only site.url and site.abbr are mandatory, and the notes add the small constraints that a spec without them would leave ambiguous. The logo should not be in ico format and at least 64 by 64 resolution is required, the dark mode logo should only be set after the main logo, and the url should not end with a slash. A mirrorz.json is therefore a small, self-contained document that a mirror operator can generate and check on its own.

The status string is a protocol in one field

The mirrors.status field is the cleverest part of the format and the part a mirror operator has to get right. It is a concatenation of strings matching the pattern of a capital letter followed by an optional number, and only one main status is allowed, with an unlimited number of auxiliary statuses. The main letters are S for successful, with an optional unix timestamp of when the last successful sync ended, D for pending with the timestamp it is pending to sync, Y for syncing with the timestamp it started, F for failed with the timestamp of the last attempt, P for paused with the timestamp the sync stopped, and then three single-letter variants with no number, C for a reverse proxy with cache, R for a reverse proxy without cache, and U for unknown. The auxiliary statuses are X for the next scheduled sync time, N for a new mirror with the timestamp the repository was added, and O for the old successful timestamp, used only when the mirror is syncing, pending or failed. A single field therefore tells a client both the state of the mirror and when it last moved, which is what lets the site show a fresh mirror without polling every one of them.

Two views over the same data, and why the cname mapping is shared

The format separates the two ways a user browses. The info array is used for the category view, where all its fields are mandatory, though it may be left empty as an empty array, and each entry has a distro, a category and a list of urls with names such as a version and architecture combination. The mirrors array is used for the list view, where each entry has a cname, a description, a url, a status, an optional help path, an optional upstream url, an optional size and an optional disable flag. Two rules tie the two views together. The name of info.distro should be agreed and have a mapping maintained in cname.json, and the same applies to mirrors.cname, so the same distribution appears under the same key across every mirror site. The description may differ from site to site because there are excludes for some mirror sites, and it may be empty. A mirror url beginning with a slash is appended to site.url to form the full url.

One repository per site, and the front end is Parcel based

The repository holds the front end and the protocol, and the build is Yarn with Parcel. For the plain HTML and CSS path, two commands start a local server, and it is convenient for debugging front end features because auto-reload is provided by Parcel.

code
yarn --frozen-lockfile
yarn start

There is a second path for working on the parser and on new site JSON files, using a site json in src/config/json-site, which starts the same local server but requires Python 3 and has no auto-reload feature. The same command pair with full_start is also the way to work on static files and the 404 redirection that emulates GitHub Pages, again requiring Python 3 and with no auto-reload. The package.json shows the shape of the project, with React 17 and react-router-dom for the interface, i18next and react-i18next for translation, sass for styling, Playwright for the tests, posthtml for the HTML transform, octokit for the GitHub API, and a mix of Parcel, TypeScript and Babel for the build.

Each deployment site is a different config and a different link

The scripts directory shows how one codebase serves several sites. The dev_env target links a localhost config into src/config/config.json and a shared config into the i18n directory, and the mirrorz_env, cernet_env and other env targets prepare the configurations for the sites the project maintains, with yarn mirrorz_env preparing for mirrorz.org. For debugging, the readme recommends yarn dev_env with yarn debug_build, which builds the site for http://localhost:1234. The build itself is one command, with a postbuild step run via yarn postbuild or automatically after full_start to copy the static assets, and yarn full_build performs all of the steps together. The repository also depends on other repositories in the same organisation, and the readme explains why they are not submodules, which is a practical note for anyone trying to reproduce a build: submodules would need to be bumped whenever there was an update, which is painful, so the build just uses the latest version of each repository.

Where the catalogue model runs out of road

The limitation is the one implied by the format, which is that a mirror list is only as good as the operators who feed it. The status protocol is precise enough to describe a mirror that is syncing, paused or failed, and the timestamps make the data useful, but there is no mechanism in the format for a client to verify that a mirror actually serves what it claims, so a site that stops syncing quietly is only reported as such after someone updates its file. The second limit is scope, since the protocol describes a catalogue and a web interface rather than a package manager configuration, so a distribution that wants to consume the data directly is left to write a client. The third is the shared vocabulary, and it is the real coordination cost, because cname values are agreed across sites and maintained in a shared cname.json, so adding a distribution name is a decision for the whole group rather than for one operator. The last practical detail is small and costs contributors an hour each time, which is that .json files are ignored in .gitignore except under /static, so a file you want to commit has to be added with git add -f.

Editorial conclusion

MirrorZ suits an operator who runs a mirror site and wants it visible in one list rather than several, and it suits a user of a Linux distribution who needs to find a working mirror without trying four URLs in turn. It is the wrong tool if you run a single mirror with no interest in being indexed, because the whole value is aggregation, and it is the wrong tool if you need a package manager to consume the data directly, since the format is aimed at a web interface. Before contributing a site, read the notes on the status string and on the cname mapping, because the cname values have to be agreed across sites rather than invented locally. The last push was on 2026-10-19 and the repository publishes no releases.

Frequently asked questions

What is the mirrorz.json format?

It is the version 1.7 data format that describes all the data of one mirror site in MirrorZ. A file has a site object for the global information such as url, logo, name and contact details, an info array used for the category view, and a mirrors array used for the list view, where each entry carries a cname, description, url and status.

What do the letters in the MirrorZ status field mean?

The status is a concatenation of strings of the pattern of a capital letter followed by an optional number, with only one main status allowed. S is successful, D pending, Y syncing, F failed, P paused, C a reverse proxy with cache, R a reverse proxy without cache and U unknown, plus auxiliary codes for the next scheduled sync, a newly added mirror and the old successful timestamp.

How do I run the MirrorZ front end locally?

Run yarn --frozen-lockfile followed by yarn start for the HTML and CSS path, which has auto-reload from Parcel. To work on the parser or on new site JSON files, or to serve static files with the 404 redirection, use yarn full_start instead, which requires Python 3 and has no auto-reload. For debugging, yarn dev_env with yarn debug_build builds for http://localhost:1234.

Official sources

  1. Issues
  2. License: MIT
  3. mirrorz-org/mirrorz on GitHub
  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/mirrorz-org-mirrorz.svg)](https://hysenlabs.com/projects/mirrorz-org-mirrorz)

Was this useful?