# Thoughtworks build-your-own-radar: generate a technology radar from a spreadsheet

> The library renders Thoughtworks-style radar visualisations from a Google Sheet, CSV or JSON file. It is a static front end with a data-source input, not a hosted service, and the AGPL-3.0 licence is the part most teams overlook.

**thoughtworks/build-your-own-radar** — A library that generates an interactive radar, inspired by https://thoughtworks.com/radar/.

- Repository: https://github.com/thoughtworks/build-your-own-radar
- Stars: 2,574 · Forks: 1,122
- Language: CSS
- License: AGPL-3.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/thoughtworks-build-your-own-radar

## The problem: a radar picture nobody wants to redraw by hand

Technology radars are a communication format before they are a diagram. A team agrees on four quadrants, four rings, and a position for each item, and the value is in the shared picture rather than in the SVG. Producing that picture is the tedious part. Someone maintains a spreadsheet, someone else redraws a circular chart, and the two drift apart within a quarter.

build-your-own-radar removes the redrawing step. The README describes it as "a library that generates an interactive radar, inspired by thoughtworks.com/radar", and the demo at radar.thoughtworks.com takes a spreadsheet ID and renders the visualisation. The intended user is a platform team, an architecture group, or an engineering organisation that already has radar-shaped opinions written down somewhere and wants them rendered without commissioning a designer.

The scope is deliberately narrow. The project does not help you decide what belongs in a ring, does not store your data, and does not run a scheduled import. It is the rendering layer plus a thin input form. If your problem is "we cannot agree on what to adopt", this tool will not help. If your problem is "we agreed three weeks ago and the chart is still in a slide deck", it fits.

## How the data flow works: a URL in, an SVG radar out

The application is a client-side bundle built with webpack. The repository layout shows src/ alongside webpack.common.js, webpack.dev.js and webpack.prod.js, and package.json carries build:dev, build:prod and dev scripts that call webpack directly. There is no server-side application framework in the dependency list. The Dockerfile starts from nginx:1.23.0, installs Node, runs npm ci, and ends with CMD ["./build_and_start_nginx.sh"], so the container builds the bundle and serves it as static files through nginx.

The data path follows from that. The first page presents an input field. You paste a Google Sheet URL, or a publicly reachable CSV or JSON URL, and the browser fetches it directly. The README states that CSV and JSON parsing is handled by the D3 library and points readers at the D3 documentation for format details. That is the whole pipeline: fetch, parse, lay out rings and quadrants, render.

Two consequences follow. The first is that the data source must be reachable from the end user's browser, not from your server, because there is no server in the path. A CSV behind an internal VPN will not load for a remote reader. The second is that the schema is the contract. The README requires the column headers name, ring, quadrant, isNew and description, and the optional status column accepts New, Moved In, Moved Out and No Change, case-insensitively. The JSON form is an array of objects with the same fields. Nothing validates your sheet before rendering, so a misspelled header shows up as an empty or broken radar rather than an error message.

## Installing build-your-own-radar and rendering a first radar

The README does not spell out a local install path in the excerpt available, but package.json and the Dockerfile together define one. The npm scripts are the source of truth for the local workflow: npm run dev starts webpack-dev-server in development mode against webpack.dev.js, and npm run build:prod produces the production bundle from webpack.prod.js. The repository pins Node through .nvmrc, so read that file before choosing a runtime version.

```bash
npm ci
npm run dev
```

The first command installs the exact dependency tree from package-lock.json. The second starts the dev server; webpack-dev-server prints the local address it is listening on, and opening that address gives you the input page.

If you would rather not manage Node locally, the Dockerfile builds an nginx image that serves the compiled bundle. The image is also published as wwwthoughtworks/build-your-own-radar on Docker Hub according to the README badge.

```bash
docker build -t byor .
docker run --rm -p 8080:80 byor
```

The build runs npm ci inside the image and then build_and_start_nginx.sh, which compiles the bundle and starts nginx. Port 80 inside the container is the nginx default; map it to whatever host port you prefer.

With the app running, the first real use is a data file. A CSV must carry the five required headers, and description fields containing commas need quoting. The README gives this shape:

```
name,ring,quadrant,isNew,description
Composer,adopt,tools,TRUE,"Although the idea of dependency management ..."
Canary builds,trial,techniques,FALSE,"Many projects have external code dependencies ..."
Apache Kylin,assess,platforms,TRUE,"Apache Kylin is an open source analytics solution ..."
JSF,Caution,languages & frameworks,FALSE,"We continue to see teams run into trouble using JSF ..."
```

Host that file somewhere publicly readable, paste the URL into the input field, and submit. The radar renders in the browser. If you are using Google Sheets instead, the README's sharing steps are: click Share, set General Access to "Anyone with the link", grant Viewer permission, and use the sheet URL. The README notes that only the segment between /d/ and /edit matters, though the full URL also works.

## Where build-your-own-radar breaks down

The public-data requirement is the sharpest constraint. The README's CSV and JSON instructions say the URL must be "publicly accessible (not behind any authentication)". There is an escape hatch for Google Sheets: the README describes a Google One Tap Login popup for private sheets, where the user authorises the app to read the sheet. That is a Google-specific path. For a CSV or JSON file on an internal server, the documented workaround is the Docker image with the file mounted on the host, which the README links to as the advanced option for hosting the file locally on the BYOR instance. That works for a self-hosted deployment and not for a public one.

Schema validation is absent. The README lists required headers and accepted status values but does not describe an error surface for malformed input. Expect to debug by inspecting the rendered output rather than by reading a message.

The quadrant names are free text, which is flexible and also means two teams can produce radars that are not comparable. The README's own example uses "languages & frameworks" as a quadrant value, and the ring values adopt, trial, assess and Caution appear with inconsistent capitalisation in the sample data. Whether that inconsistency is tolerated by the parser is not stated in the README.

Finally, this is a static front end. There are no user accounts, no saved radars, no version history, and no access control beyond whatever your data host provides. If your organisation needs to show different radar views to different groups, the tool gives you no mechanism for it.

## Alternatives and when a different approach fits better

The obvious alternative is to write the visualisation yourself with D3. That is not a hypothetical: build-your-own-radar already depends on D3 for CSV and JSON parsing, and the radar layout is a polar chart with labelled blips. A team with existing D3 experience and unusual requirements, such as non-circular layouts or radar views filtered per audience, may find a bespoke chart faster than adapting this one. The difference in approach is that a bespoke chart gives you control over the data pipeline, including server-side fetching, at the cost of building and maintaining everything the project already provides.

A second alternative is to keep the radar in whatever tool already holds your roadmap, such as a spreadsheet with a chart, or a wiki page with a static image. That is worse for interactivity and better for access control, because it inherits the permissions of the host you already use. The trade-off is explicit: build-your-own-radar gives you an interactive radar with hover and click behaviour, and asks you to make the underlying data public.

A third option is to fork. The licence permits it under AGPL-3.0 terms, and the repository is small enough that a fork is realistic. The cost is that you now maintain the webpack configuration, the Jest suite and the Cypress end-to-end tests, all of which are present in the repository and wired into npm scripts.

## Maintenance, licensing and the upgrade cost you are signing up for

The repository is not archived. The last push was on 2026-04-22, and the most recent release, v1.2.0, was published on 2026-04-15. Before that, v1.1.6 landed on 2024-06-04 and v1.1.5 on 2024-04-25. The gap between v1.1.6 and v1.2.0 is roughly twenty-two months, which is worth knowing if you plan to depend on upstream for fixes: releases arrive when they arrive, and the version in package.json is 1.2.1 while the latest tagged release is v1.2.0.

Upgrading is a build-tool exercise rather than a data migration. The dependency list is dominated by webpack 5, Babel, sass, postcss, eslint and prettier, with Jest for unit tests and Cypress for end-to-end tests. The npm quality script chains lint-prettier:check and test:coverage, and the e2e scripts run Cypress against a host passed through the TEST_URL environment variable. Any upgrade you attempt will be judged by whether that chain still passes. The Dockerfile pins nginx:1.23.0 and installs Node from the setup_24.x script, so a base-image refresh is a separate task from a dependency refresh.

The licence is AGPL-3.0, stated in package.json and in LICENSE.md. AGPL-3.0 is a copyleft licence with a network clause: if you modify the software and let users interact with it over a network, the licence's terms extend to the modified source. Hosting an unmodified copy for internal readers is a different situation from modifying it and exposing it to external users. This is a description of what the licence says, not legal advice; the specific question of whether your deployment triggers the network clause is one for your own counsel.

## Conclusion

Adopt build-your-own-radar if you already keep your radar data in a spreadsheet and want the Thoughtworks visualisation without writing D3 code yourself, and if AGPL-3.0 is acceptable for how you plan to expose it. Do not adopt it if you need per-user permissions, audit trails, or a hosted service with an SLA; the project is a static front end that fetches a data URL, and the README documents no storage layer. Before you commit, verify three things: that your sheet is shared as "Anyone with the link" with Viewer permission, that your column headers match name, ring, quadrant, isNew and description exactly, and that your legal team has read the AGPL-3.0 section of the repository before you offer the rendered radar to users outside your organisation.

## FAQ

### How do I build my own technology radar with build-your-own-radar?

Create a Google Sheet with the columns name, ring, quadrant, isNew and description, share it as "Anyone with the link" with Viewer permission, then paste the sheet URL into the input field on the app's first page and submit. The README states the radar is generated once you click submit.

### What is the main purpose of build-your-own-radar?

It renders an interactive radar visualisation, inspired by thoughtworks.com/radar, from data you supply in a Google Sheet, CSV file or JSON file. It is a rendering and input layer, not a system that decides what belongs on your radar.

### Can I use build-your-own-radar with private data?

The README says CSV and JSON URLs must be publicly accessible and not behind authentication. For a private Google Sheet, the README describes a Google One Tap Login popup where the user authorises the app to read the sheet. For a local CSV or JSON file, the README points to the Docker image option that mounts the file on the BYOR instance itself.

### What licence does build-your-own-radar use?

AGPL-3.0, according to package.json and LICENSE.md. That is a copyleft licence with a network clause, so if you modify the software and let users interact with it over a network, the licence terms extend to the modified source.

### Which columns does the build-your-own-radar spreadsheet need?

The README requires name, ring, quadrant, isNew and description. An optional status column can be added to show blip movement, accepting New, Moved In, Moved Out and No Change, case-insensitively.

## Sources

- [Issues](https://github.com/thoughtworks/build-your-own-radar/issues)
- [License: AGPL-3.0](https://github.com/thoughtworks/build-your-own-radar/blob/master/LICENSE)
- [README](https://github.com/thoughtworks/build-your-own-radar/blob/master/README.md)
- [Releases](https://github.com/thoughtworks/build-your-own-radar/releases)
- [thoughtworks/build-your-own-radar on GitHub](https://github.com/thoughtworks/build-your-own-radar)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/thoughtworks-build-your-own-radar
