{"id":15512921,"url":"https://github.com/glacials/splits-io","last_synced_at":"2025-12-17T10:35:40.277Z","repository":{"id":1365159,"uuid":"14379065","full_name":"glacials/splits-io","owner":"glacials","description":"a speedrunning data store and analysis engine","archived":false,"fork":false,"pushed_at":"2024-10-18T15:31:05.000Z","size":31437,"stargazers_count":133,"open_issues_count":115,"forks_count":27,"subscribers_count":14,"default_branch":"main","last_synced_at":"2024-10-18T20:16:53.842Z","etag":null,"topics":["docker","docker-compose","gaming","highcharts","javascript","livesplit","postgresql","rails","ruby","s3","speedrunning"],"latest_commit_sha":null,"homepage":"https://splits.io","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/glacials.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"patreon":"glacials"}},"created_at":"2013-11-13T23:03:29.000Z","updated_at":"2024-10-18T15:31:09.000Z","dependencies_parsed_at":"2023-07-06T14:17:02.905Z","dependency_job_id":"ad720fbc-b55b-4755-8a24-65a9b827ee49","html_url":"https://github.com/glacials/splits-io","commit_stats":{"total_commits":2439,"total_committers":24,"mean_commits":101.625,"dds":"0.21894218942189425","last_synced_commit":"32c1a5cd53297463bdf5e1fb9e1e2c8cf6820a93"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/glacials/splits-io","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glacials%2Fsplits-io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glacials%2Fsplits-io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glacials%2Fsplits-io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glacials%2Fsplits-io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/glacials","download_url":"https://codeload.github.com/glacials/splits-io/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glacials%2Fsplits-io/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279010939,"owners_count":26084837,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","gaming","highcharts","javascript","livesplit","postgresql","rails","ruby","s3","speedrunning"],"created_at":"2024-10-02T09:53:56.036Z","updated_at":"2025-10-12T09:32:01.839Z","avatar_url":"https://github.com/glacials.png","language":"Ruby","funding_links":["https://patreon.com/glacials"],"categories":["Ruby","Open Source Rails Apps"],"sub_categories":["Articles"],"readme":"# Splits.io has permanently shut down.\n\nSplits.io has shut down for financial reasons.\nPlease see [my blog post](https://twos.dev/splitsio.html) for more info.\n\nIf you are looking for your data,\na data retrieval tool is active in its place at [splits.io](https://splits.io).\n\nThe original README is preserved below.\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://splits.io/\" rel=\"noopener\"\u003e\n    \u003cimg src=\"https://i.imgur.com/PoeNer0.jpg\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch3 align=\"center\"\u003eSplits.io\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n\n  [![View performance data on Skylight](https://badges.skylight.io/typical/l4aQWIYa50pX.svg)](https://oss.skylight.io/app/applications/l4aQWIYa50pX)\n  [![View performance data on Skylight](https://badges.skylight.io/problem/l4aQWIYa50pX.svg)](https://oss.skylight.io/app/applications/l4aQWIYa50pX)\n  [![View performance data on Skylight](https://badges.skylight.io/rpm/l4aQWIYa50pX.svg)](https://oss.skylight.io/app/applications/l4aQWIYa50pX)\n  [![License](https://img.shields.io/github/license/glacials/splits-io.svg)](/LICENSE)\n\n\u003c/p\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n  A speedrun data store, analysis engine, and racing platform.\n\u003c/p\u003e\n\n## About\n\nSplits.io is how speedrunners improve through data. It gives split-by-split\nanalysis of individual runs, viewed through a lens of all runs. On Splits.io,\nspeedrunners share more than their time—they share their entire history of\nattempts, successful or not, and get feedback on how to improve long-term\nthrough statistics and comparisons with themselves and other runners in their\nweight class, both live (via races) and after-the-fact using historical data.\n\nSplits.io works with LiveSplit and more than 15 other speedrunning timers. An\nauto-generated list can be viewed in the [FAQ][faq]; new timers can\nself-integrate using the [Splits.io Exchange Format][exchange].\n\n[exchange]: /public/schema\n[faq]: https://splits.io/faq#programs\n\n## API\nClient libraries exist for the following languages. These are created and maintained by community members:\n- Python: [`jeremander/splitsio`][python-client]\n- Rust: [`livesplit/splits-io-api`][rust-client]\n\nFor full API documentation and when using other languages, see the [API readme][api-docs].\n\n[api-docs]: /docs/api.md\n[python-client]: https://github.com/jeremander/splitsio\n[rust-client]: https://github.com/LiveSplit/splits-io-api\n\n## Local Development\nSplits.io runs on Docker, which makes it easy and consistent to set up and run on any machine despite any unusual\ndependencies. The one downside is that you must first install Docker!\n\n### Requirements\n* [Docker][docker-download]\n* [Docker Compose][docker-compose-download] (on macOS and Windows, this is included in the Docker install)\n\n[docker-download]: https://store.docker.com/search?type=edition\u0026offering=community\n[docker-compose-download]: https://docs.docker.com/compose/install/\n\n#### Special note for Windows\nBecause of how Splits.io uses Docker, Windows requires WSL2 to be installed to run Splits.io. If you haven't done\nso already, follow these instructions when running Splits.io on Windows:\n\n1. [Install Windows Subsystem for Linux (WSL) on Windows 10](https://docs.microsoft.com/en-us/windows/wsl/install-win10)\n2. [Docker Desktop WSL 2 backend](https://docs.docker.com/docker-for-windows/wsl/)\n\nThese steps are not required for Linux or macOS.\n\n### Running\n\n#### First run\nThe first time you run Splits.io will take a while to build, so you should go grab a coffee or something:\n\n```sh\nmake  # shorthand for make build run\n```\n\nOnce the output looks settled (you should see `* Listening on tcp://0.0.0.0:3000`),\nopen another terminal window and type\n```sh\nmake seed\n```\nThis is required, as it sets up a client ID/secret for your local JavaScript to communicate\nwith your local backend. It will also prepopulate your local database with some initial data.\n\nAfter that, you're good to go!\nAccess [localhost:3000][localhost] in your browser.\nThe first page load after a new build may also take a minute.\n\n_Note: If the page has no styling information on first run, try rebooting the server._\n\n\n[localhost]: http://localhost:3000/\n\n#### Subsequent runs\nIf you have already run `make` or `make build` in the past, you usually won't need to rebuild everything again,\nso you can instead just run the faster version:\n\n```sh\nmake run\n```\n\nIf you do need to rebuild (e.g. when adding or upgrading a dependency) but don't necessarily want a server:\n\n```sh\nmake build\n```\n\n#### Further Setup\n\nThese steps are not required for normal operation, but you may want to\nperform them for specific categories of work.\n\n##### OAuth\n\nSome features are built on top of links with other platforms, like Twitch\nsign-in. If you want these features to work, you need to register developer\napplications with the appropriate services. Copy `.envrc.example` to `.envrc`\nand follow the comments inside for details and instructions for various\nplatforms.\n\nAfter following the instructions, run\n```sh\nsource .envrc\nmake build run\n```\nto rebuild the server with your new environment variables. We recommend using\n[direnv][direnv] to automate the first step whenever you change directories!\n\n[direnv]: https://github.com/direnv/direnv\n\n##### Emails\nSplits.io sends emails when users go through the \"I forgot my password\" flow.\nIn development mode, these emails are not actually sent but are instead\ngenerated then saved to `tmp/mails`.\n\nIf you want to preview a demo email in your browser, you can fiddle with the\npreviewers in `spec/mailers/previews` then access a URL like\n```\nhttp://localhost:3000/rails/mailers/:mailer/:action\n```\nsuch as\n```\nhttp://localhost:3000/rails/mailers/password_reset_token_mailer/create_email.\n```\n\n### Debugging\n#### Getting Up and Running\nIf you're having trouble getting Splits.io running at all using the above instructions, please make a GitHub issue so\nwe can work it out! Even if you think it's a silly issue, the fact that it's happening to you means we haven't ironed\nout everything (even if the only thing preventing you from setting up is better documentation!).\n\n#### Working with the Code\nIf you have the app up and running but are looking for insight into debugging your own changes, you can access a Rails\nconsole inside the Docker container with\n```sh\nmake console\n```\n\n#### Attaching to a debugger\nIf you use `binding.pry` anywhere in the code, once you hit the breakpoint specified use the command\n```sh\nmake attach\n```\nin another terminal window to attach to it.  To detach, make sure to exit the debug session then use the docker\nattach escape sequence `ctrl + p` then `ctrl + q`.\n\nIf you need to attach to a container other than `web`, specify a container with the syntax\n```sh\nmake attach container=worker\n```\n\n### Running Tests\nTo run tests from inside the Docker container, use\n```sh\nmake test\n```\nTo run only specific tests, use\n```sh\nmake test path=spec/path/to/test/file/or/dir\n```\n\n### Linting\nWe use [Rubocop][rubocop] for code cleanliness and styling. To run it against changed files, commit your changes and run\n```sh\nmake lint\n```\n\n### Profiling\nSplits.io utilizes a few libraries for profiling our code.\n\n\n[Rack Mini Profiler](https://github.com/MiniProfiler/rack-mini-profiler) is used to find major slowdowns in the code\nthrough the use of the badge in the top left corner of the browser window. There is also a slew of different URL\nparameters that you can use to get more detailed information about various aspects of the request. Details of these are\nexplained in the readme for RMP.\nTo get more detailed information about how code will perform in a production like environment, run\n```sh\nmake profile\n```\nto boot the app in the profiling environment, which has most of the production flags toggled on.\n\n\n[DerailedBenchmarks](https://github.com/schneems/derailed_benchmarks) is used to test memory over lots of requests.\nThe commands that can be run are detailed in the readme for DB. When you have a command you want to run, use the make\ntask like so with the options that you need\n```sh\nmake derailed env=\"-e TEST_COUNT=5000 -e USE_AUTH=true\" command=\"exec perf:mem_over_time\"\n```\nThe env flag is optional, so feel free to leave that blank if you have no environment variables to set.\n\n[rubocop]: https://github.com/rubocop-hq/rubocop\n\n### Updating Gems or Docker\nIf you change the Dockerfile or Gemfile, you'll need to run\n```sh\nmake build\n```\nto rebuild the Docker image for your changes to apply.\n\n### Cleaning Up\nIf you want to reset from scratch, you can run\n```sh\nmake clean\n```\nwhich will run `docker-compose down`, remove the bundler volume, and remove `node_modules/`.\n\n## Things You Probably Don't Need to Know\n### Infrastructure\nSplits.io is built in Ruby on Rails, but has some help from other pieces of infrastructure.\n```\n                             ┌──────────────────────────────────────────────────────────┐\n                             │AWS Application Load Balancer (splits.io)                 │\n                             │┌────────────────────────────────────────────────────────┐│\n                             ││AWS Auto Scaling Group                                  ││\n                             ││┌──────────────────────────────────────────────────────┐││\n                             │││AWS Target Group                                      │││\n    ┌────────────┐           │││┌────────────────┐┌────────────────┐┌────────────────┐│││ Lambda tells Rails\n    │AWS RDS     │           ││││AWS EC2 Instance││AWS EC2 Instance││                ││││ to parse the file\n    │┌──────────┐│           ││││┌──────────────┐││┌──────────────┐││                ││││  │\n    ││PostgreSQL││◀──────┐   │││││Docker        ││││Docker        │││                ││││  │  ┌──────────┐\n    │└──────────┘│       │   │││││┌────────────┐││││┌────────────┐│││                ││││◀────│AWS Lambda│\n    └────────────┘       ├───┼┼┼┼┤│Rails Web   ││││││Rails Web   ││││      ...       ││││     └──────────┘\n ┌───────────────┐       │   │││││└────────────┘││││└────────────┘│││                ││││           ▲\n │AWS Elasticache│       │   │││││┌────────────┐││││┌────────────┐│││                ││││           │\n │┌─────────────┐│       ├───┼┼┼┼┤│Rails Worker││││││Rails Worker││││                ││││           │ New file\n ││Redis        ││◀──────┤   │││││└────────────┘││││└────────────┘│││                ││││           │ trigger\n │└─────────────┘│       │   ││││└──────────────┘││└──────────────┘││                ││││           │\n └───────────────┘       │   │││└────────────────┘└────────────────┘└────────────────┘│││           │\n         ┌───────┐       │   ││└──────────────────────────────────────────────────────┘││       ┌──────┐\n         │AWS SES│◀──────┘   │└────────────────────────────────────────────────────────┘│       │AWS S3│\n         └───────┘           └──────────────────────────────────────────────────────────┘       └──────┘\n             │                                             ▲                                        ▲\n             │                                             │ HTTPS, WebSockets                      │\n             │                                             ▼                                        │\n             │                                          ┌────┐                                      │\n             └─────────────────────────────────────────▶│User│◀─────────────────────────────────────┘\n              Sends \"I forgot my password\" emails       └────┘  File uploads/downloads (runs, race\n                                                                attachments) via S3 presigned URLs\n\nNot pictured:\n\n - beta.splits.io, an AWS Application Load Balancer with an identical hierarchy\n except pegged at 1 instance, pointing to the same external infrastructure\n\n - livesplit-core, a Rust library with Ruby bindings that gets deployed to\n containers so Rails Web can call it to parse run files\n\n - AWS CodePipeline, which calls out to AWS CodeBuild and AWS CodeDeploy to\n build and deploy code on pushes to main\n```\nRails will synchronously parse any unparsed run before rendering it, but the asynchronous Lambda job is the preferred\nway for runs to be parsed because it still catches unvisited runs (e.g. in the case of a multi-file upload via\ndrag-and-drop).\n\nIn development PostgreSQL and S3 are also Docker containers (see [docker-compose.yml][docker-compose.yml]). Lambda is\nnot yet implemented in development mode.\n\n[docker-compose.yml]: docker-compose.yml\n\n### Favicons\nFavicons are generated by [Favicon Generator][favicon-generator] and its Rails gem. To generate favicons from the source\nimage ([public/logo-imageonly.svg][logo]), run\n```sh\ndocker compose run web rails generate favicon\n```\nConfig for this generation is at [`config/favicon.json`][favicon-config].\n\n[favicon-generator]: https://realfavicongenerator.net/\n[logo]: app/assets/images/logo-imageonly.svg\n[favicon-config]: config/favicon.json\n\n### Theme\nSplits.io runs vanilla [Bootstrap 4][bootstrap]. Historically we used one of a few themes to give it some additional\ndistinction and a professionally tailored dark mode, but we decided to switch to vanilla with our own dark mode after\nseveral bad experiences with those themes slowly falling more and more out of date from mainline Bootstrap.\n\n[bootstrap]: https://getbootstrap.com/\n[dashboard]: https://themes.getbootstrap.com/product/dashboard/\n\n## Responsible Disclosure\nIf you find a security vulnerability in Splits.io, please email it privately to security@splits.io, as posting the\nvulnerability in public may allow malicious people to use it before it can be fixed. We take security matters very\nseriously and respond quickly to disclosures.\n\n## Library Information\n### LiveSplit Core\nSplits.io uses [livesplit-core][livesplit-core] for parsing runs. The parser is located in `lib/parser/*`. To upgrade\nit, run\n```sh\nmake update_lsc\n```\nand commit the changes.\n\n[livesplit-core]: https://github.com/LiveSplit/livesplit-core/\n\n### Highcharts\nTo generate run history charts Splits.io uses [Highcharts][highcharts-home], which requires a\n[written license][highcharts-licenses]. Licensing is based on the honor system, so you do not need to enter a key\nanywhere. Highcharts is free to use for testing purposes.\n\n[highcharts-home]: https://www.highcharts.com/\n[highcharts-licenses]: https://shop.highsoft.com/highcharts\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglacials%2Fsplits-io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglacials%2Fsplits-io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglacials%2Fsplits-io/lists"}