Library / SDK
odota/web avatar
odota/web

OpenDota web: a React front end that runs entirely against the production API

OpenDota: React web UI for Dota 2 statistics using the OpenDota platform

1,191 stars419 forksTypeScriptMIT

At a glance

What is it?
opendota-web is the React and Redux interface to the OpenDota platform, a Dota 2 statistics site built on a separate open source core API. The distinguishing property is that the UI points at the live API by default, so a contributor needs no database and no starter data to see real matches.
Who is it for?
opendota-web fits a contributor who wants to work on a large, real React and Redux application without standing up any infrastructure, and a team that needs a worked example of a data-dense interface at production scale. It is the wrong choice if you need the interface to run against your own data on day one without a deployment, and the wrong choice for a project that wants a current React stack, since the dependencies here are from the React 17 and Redux 4 era.
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 TypeScript, 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

No database, no fixtures, real data on the first run

opendota-web is the web interface for viewing Dota 2 data, and it utilises the OpenDota API, which is also an open source project in its own right. The site is at opendota.com.

The decision that shapes everything else is in the notes section. You do not have to set up the entire stack, databases and so on, or worry about getting starter data, since the UI points to the production API.

That is a big deal for the intended reader, which is a contributor. The quickstart is five steps: clone the repo with `git clone [email protected]:odota/web.git`, install Node.js v16 or greater, run `npm install`, run `npm start`, and visit port 5173 on your development machine. There is no database to provision, no seed script, no docker compose file with a dozen services. The clone runs and you are looking at real matches from real games.

The cost of that convenience is the flip side, and the documentation says so. The configuration is there to point to your own API if you are working on a new feature and want to start building the UI before it is deployed to production. So there is a window during development where the UI for a new feature is running against an API that does not have that feature yet, and the practical consequence is that some views will show errors or empty states until the backend catches up.

The two environment variables are `VITE_API_HOST`, which changes the API the UI requests data from, with the default being `https://api.opendota.com`, and `SSL_CRT_FILE` with `SSL_KEY_FILE`, which cause the development server to use HTTPS.

The stack is React and Redux with styled-components and MUI

The tech stack section of the project summary is short: the view is React and Redux, and the CSS is styled-components.

The dependency list shows what that means in practice, and it is a substantial one. The React side is React 17.0.2 with react-dom at the same version, react-redux 7.1.3, redux 4.2.1, redux-thunk 2.4.2, and reselect 4.0.0 for memoised selectors. Routing is react-router-dom 5.1.2, and there is a `history` package at 4.10.1 for the history API, plus `querystring` for URL parsing.

The data visualisation side is where a Dota statistics site earns its keep, and there are two libraries doing different jobs. `recharts` at 2.15.4 is the React charting library, and `@mars3d/heatmap.js` is a mapping and heatmap library, which is how a site about a five versus five game with a global map plots where players are and where the heat is.

The component libraries are both present, which is an unusual combination. `@mui/material` at 7.3.6 with `@mui/icons-material` at 7.3.5 is the Material UI set, and `styled-components` at 4.4.1 with `@emotion/react` and `@emotion/styled` at 11.14 are the CSS-in-JS stack. So the project uses Material UI components and styled-components for custom styling.

The rest of the list tells you what a data-heavy site needs. `ace-builds` is the Ace editor, which is how you display a replay or a raw payload. `react-content-loader` is the skeleton placeholder pattern, `react-countup` animates numbers, `react-helmet` manages the document head, `react-markdown` renders markdown, `react-tooltip` and `react-transition-group` handle the small interactions, and `melloware/react-logviewer` renders log output. `papaparse` parses CSV, `fuzzy` does fuzzy matching for a search box, `air-datepicker` is the date range picker, `nanoid` generates identifiers, and `dota2-emoticons` is the in-game chat emote set.

The last dependency in the list is the one that connects this UI to the game, `dotaconstants` at 10.8.0, which is the shared package of Dota constants, item data, and abilities that the whole OpenDota ecosystem uses so the numbers match.

`react-ga` is there too, for the analytics.

Vite for the build, and a bundle analyser for the people who care

The build tooling is Vite, and the package.json scripts show a project that has settled into it.

`start` is `vite --host`, which serves the development app and, with the host flag, makes it reachable from other devices on the network rather than only from localhost. `preview` is `vite preview --host`, which serves the production build. `build` is `vite build && npm run typecheck`, so the type check runs after the bundle and a type error fails the build.

The typecheck script is `tsc --project tsconfig.json --noEmit`, and the project has a `tsconfig.json` at the root alongside `vite.config.ts` and an `index.html`, which is the Vite layout with the HTML file at the root rather than in a public directory.

The `analyze` script is the interesting one. It runs `npx source-map-explorer 'build/assets/*.js' --html result.html --no-border-checks`, which takes the built bundles and the source maps and produces an HTML report showing what is actually in each chunk. For a front end with this many dependencies, that report is how you find out that a charting library is pulling in a moment.js, or that a date picker is half the bundle.

The linting and formatting are separate from the build. `lint` runs eslint over ts, tsx, js, and jsx files, and `lintfix` is the same with `--fix`. `prettier` runs prettier over the whole repository. There is an `.eslintrc`-style configuration implied by the scripts, an `.env_example` file at the root documenting the environment variables, and a `crowdin.yaml` for the translations.

There is one more script that tells you about the project. `update:emoticons` runs `npm r dota2-emoticons && npm i dota2-emoticons && node dev/updateEmoticons.js`, so the emote set is regenerated from the upstream package by a script in the `dev/` directory rather than being vendored by hand.

TestCafe walks every route, because a data site breaks in the data

The test setup is the part of this project that is most distinctive, and it comes straight from the contributing instructions.

The contribution flow asks you to make some changes, run `npm run typecheck` to check your code for typing errors, run `npm test` to check all app routes for uncaught JavaScript errors, and then submit a pull request and wait for review and merge. The last two lines are Congratulations, You're a contributor.

So `npm test` is not a unit test suite. The script is `testcafe -c 4 chrome:headless testcafe/ --app "vite preview --host --port 5000 "`, which is TestCafe driving a headless Chrome, with the concurrency set to 4, running the files in the `testcafe/` directory, and starting the app itself with a vite preview on port 5000.

Testing every route for uncaught JavaScript errors is a well-chosen test for this kind of application. A Dota statistics site has a route per match, per player, per item, per hero, and each one fetches from the API and renders data whose shape depends on the API. A change that breaks one route does not break the app, it breaks that page, and a unit test suite written against components would not catch it. A crawler that visits every route and fails on an uncaught exception does catch it.

Running against `vite preview` rather than the dev server is the other half of that choice. The preview server serves the production bundle, so the test exercises the built output rather than the unbundled source, which is where the code splitting and the chunk boundaries are.

The `testcafe/` directory is at the repository root, alongside `dev/`, `public/`, `src/`, and `index.html`. The `public/` directory holds the static assets that are copied verbatim into the build, and `dev/` holds the scripts that are development tooling rather than application code, such as the emote updater.

The project expects you to talk to the team

There is a short section in the project summary about contributing regularly, and it is more specific than most.

The Discord is at a link, and it is strongly recommended for active developers, with the reason given: we move fast and it is helpful to be up to speed with everything that's happening. That is an admission worth reading literally. A project with an active contributor base and a fast-moving roadmap means the code you read on a Monday may differ from the code on Thursday, and the Discord is where you find out what changed and why.

The second line is an offer of organisation membership. If you are interested in contributing regularly, let us know and we'll add you to the organization. In a project that has a CodeTriage badge for helping new contributors, the maintainers are explicitly building a contributor funnel, and the organisation membership is the next step in it.

The project is also open to translation work, given the `crowdin.yaml` file at the root, which is the configuration for a translation management service. A statistics site with a global audience and a lot of hero and item names has a genuine translation burden, and Crowdin is the standard way to handle it.

The CodeTriage badge in the project header points to a tool that finds issues that are good for newcomers to work on, and it is there in the same header as the CI and coverage badges. The combination of badges tells you the shape of the project: a large public application with automated coverage, a translation pipeline, an onboarding path for new contributors, and an active chat.

The licence is MIT, and the repository description records the package as a Dota 2 Data Web UI at version 1.0.1, marked private since it is an application rather than a published library.

Where opendota-web is the wrong starting point

The limits are mostly about currency and about what you are actually getting.

First, the dependency versions are from an earlier era. React is at 17.0.2, react-router-dom at 5.1.2, redux at 4.2.1, and styled-components at 4.4.1, while the Material UI and emotion packages are current at 7.3.x and 11.14. So the project is a mix: the React ecosystem parts are two majors behind, and the styling parts are not. That combination tells you the project has been maintained rather than modernised, and it means the code you read demonstrates working patterns for a version of React that is no longer what a new project would install. If you are learning React from this repository, you are learning a pattern that has since been superseded,

Second, the library is heavy. The dependency list is long, and some of the entries exist for one specific feature, the heatmap library, the log viewer, the Ace editor. A production application of this size can afford that. A small project copying its dependency list cannot, and the `analyze` script exists precisely because the bundle size needs watching.

Third, and this is the practical one, pointing at the production API means your development environment is coupled to somebody else's uptime and somebody else's rate limits. The convenience that makes the contribution experience good, no database and real data, becomes a liability the moment you want to work offline, or you want to test a new API shape that does not exist in production yet, or the API is having an incident while you are mid-feature.

Fourth, the route-crawling test is a good fit for catching uncaught errors, and it is not a substitute for unit tests. There is no `npm run test:unit` script in the list, so the type check and the route crawl are the entire verification story. A project that adopts this repository as a starting point inherits a testing strategy that finds crashes and does not find logic errors.

Fifth, the release history is a single tag, v1 from 2017, and the package version is 1.0.1 with no releases. There is nothing to compare against, no changelog to read before upgrading, and no version to pin in a deployment.

Editorial conclusion

opendota-web fits a contributor who wants to work on a large, real React and Redux application without standing up any infrastructure, and a team that needs a worked example of a data-dense interface at production scale. It is the wrong choice if you need the interface to run against your own data on day one without a deployment, and the wrong choice for a project that wants a current React stack, since the dependencies here are from the React 17 and Redux 4 era. Check three things before you start: that your Node.js is 16 or newer, that you understand the UI reads the production API by default and that a change you make is immediately visible against live match data, and that the `VITE_API_HOST` variable is set if you are building a feature against an API that is not yet deployed.

Frequently asked questions

How do I run the OpenDota web UI locally?

Clone the repository with `git clone [email protected]:odota/web.git`, install Node.js v16 or greater, then run `npm install` and `npm start` and visit port 5173. You do not need to set up databases or starter data, because the UI points at the production API by default.

How do I point the OpenDota web UI at a different API?

Set the `VITE_API_HOST` environment variable, which changes the API the UI requests data from, with the default being `https://api.opendota.com`. The `SSL_CRT_FILE` and `SSL_KEY_FILE` variables cause the development server to use HTTPS, which is useful when the page needs to reach an HTTPS API from a local server.

What does npm test do in the OpenDota web project?

It runs TestCafe against a headless Chrome with concurrency 4 over the files in the `testcafe/` directory, starting the app itself with a vite preview on port 5000. The contributing guide describes it as checking all app routes for uncaught JavaScript errors.

What front-end stack does opendota-web use?

The view layer is React with Redux, and the CSS is styled-components, alongside Material UI components. The data visualisation uses recharts for charts and the mars3d heatmap library for mapping, with dotaconstants supplying the shared Dota constants, items, and abilities.

Official sources

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

Was this useful?