Summary and goals

Be-Music Source (BMS) is a file format for rhythm game charts

There are many BMS clients that parse BMS files allowing users to play songs. The current BMS ecosystem runs off sites known as Tables. These tables are arrays of Chart objects sorted by difficulty. Chart objects do not actually contain the chart, they instead contain and MD5 hash of the charts corresponding .bms file (as well as other metadata like title & author). It is up to the user to source this file & for their client to link the local file to the Chart object.

Sometimes, the metadata sent along with the Chart object includes a link to a site where the files can be downloaded. Other times, it’s up to the user to hunt down packs or other users who already have the chart.

This app would list all Charts in a Table in a easy to navigate web application. With a majority of the data being driven by metadata provided by the table. Admin users are able to create a corresponding object in the apps database against a Chart, where extra metadata can be included, such as download links & descriptions.

Once a corresponding object has been created, even if the chart is no longer in the table; it can still be viewed on the website.

This site will attempt to mirror an osu-esque style of browsing charts:

Scope Breakdown



Technical Breakdown


External Integrations

Table Objects

Tables consist of two JSON files served from a URL: A header, and a body.

The header file contains the name of the table and assorted information.

The body file contains all charts in the table as an array.

There is no agreed upon schema in the community for these objects. However, most clients handle some defaults.

interface Header {
  // The name of the table
  name: string;
  // The icon to show in clients (usually unicode shape)
  symbol: string;
  // URL or Path to the tables body
  data_url: string;
  // Order levels should be put in in clients, optional?
  level_order?: string[];
  // What mode (7k/14k/PMS/24k) is the table for, optional?
  mode?: string;
type TableBody = {
  // The title of the song
  title: string;
  // The songs artist
  artist: string;
  // MD5 hash used by clients to identify charts
  md5: string;
  // The charts level
  level: string;
  // The URL where the chart can be downloaded
  url?: string;
  // Another URL where the chart can be downloaded (stellabms only?)
  url_diff?: string;
  // SHA256 of the chart (stellabms only?)
  sha256?: string;
  // A comment by the uploader. Completely optional.
  comment?: string;

Local Objects

TableMirror Objects

We should store basic metadata about the table to prevent spamming the table host when users view our site. When users view a table we should show extremely slim amounts of information as well as the related localChart objects in our system. If the user wishes to, they can load the remaining charts we do not have dedicated objects for.


We should store clones of the tables locally to allow users to view the entire tables list of charts in one go. Charts with localChart data associated will be moved to the top &/ displayed separately.

LocalChart Objects

A more complex object containing metadata about the chart. This could include an image, a brief description, links to more reliable downloads, or even note analysis to generate stats like density/chords. We could also include an array of charts that are similar or considered other difficulties.


A chart can be in multiple tables, knowing only the chart we should be able to fetch tables its in, and knowing only the table, we should be able to fetch charts.

If using dynamoDB a linking object would likely have to exist with an index for querying by table identifiers and an index for querying by chart identifiers. Since we expect to be querying this a lot it’s worth making this an index

User activities

Users almost always have read only permissions to all objects.
Admins can read and write

Admin User

End User

User requests

Users will be triggering the bulk of requests in the system

Request system tables

Request system localCharts

Request table charts (non-local)

Implementation timeline

Assuming baseline core starter

  1. Create admin app
  2. Create tableMirror object admin CRUD/UI
  3. Create localChart object admin CRUD/UI
  4. Create linking object admin CRUD
  5. Create auto linking function when tables are updated
  6. Design user table list screen
  7. Design user chart list screen
  8. Design user chart view screen
  9. Create end user app
  10. Allow end users to browse tables
  11. Allow end users to browse local charts
  12. Allow end users to view chart data


Things to keep in mind when scoping work out

© 2024 Pfych 🏳️‍⚧️