Skip to content


Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

COVID-19 Self Reporting Tool license Dependabot Status

A website to track global self reported cases and predict future outbreaks. See our About page for more background on the project.


If you are interested in contributing to our project, read our contributing guidelines first.

Local setup

First, copy over the sample.env file to .env

mv sample.env .env

You will need a few API keys for the map, geocoder, authentication, and database to work correctly. Luckily as of this writing, they are all free for development purposes.


Sign up on Mapbox and copy your access token into the REACT_APP_MABPOX_TOKEN variable in the .env file. This is required for the map to render correctly.

Google Places API

Create a Google Developer account and get an API key. Make sure both the Places API and Geocoder API is selected. Set this api key to the REACT_APP_GOOGLE_MAPS_API_KEY variable in the .env file.


Create a Firebase account and a new project. You will only need the Authentication part of Firebase. Copy over the client Javascript SDK variables into the # Firebase section of your .env file.


Finally, setup the API backend and run it in the background. Set the REACT_APP_BACKEND_URL to the local URL that it's running under (most likely http://localhost:8000).


npm start


This uses Cypress and cypress-firebase for integration tests. You will need to get a serviceAccount.json containing your firebase service account credentials in your root directory for the login flow to work. You can get this from the Firebase account you created.

Then, create a test account and copy the UID into the CYPRESS_TEST_UID in your .env file.

Start the Node server (npm start) in the background before running tests.

To run tests in headless mode:

npm run cy:run

To run the Cypress test runner:

npm run cy:open

For cypress tests, add the following property to your HTML elements to be easier to find them:

<div data-cy="example_element"></div>

This is more stable/maintainable than using classes or IDs and assures that they don't change.


File Structure

  • One component per file with the same name as the file
  • One types.ts per directory
  • Shared functions go in utils
  • One index.ts per directory in components directory, that exports all other components. This allows us to do things like:
import { Component1, Component2 } from 'components';

Other Conventions

  • Functional components with React hooks
  • useContext + useReducer used sparingly, only for shared UI state
  • react-query for all backend API calls (queries should go in utils/queries.ts)
  • async/await over Promises
  • type over interface, except for component prop types


Backend API


  • JHU GitHub data (CSVs)
  • JHU Postman API docs (currently scraping the /summary route and adding to DynamoDB daily, the joining on the fly to countries geojson client-side)
  • JHU Counties with geojson + totals, or non-geojson time series. May be useful for scraping.
  • ArcGIS County COVID-19 data with both spatial and time-series data. In case we need an easy way to scrape time-series.


Data notes

Dummy data

Some dummy data w/5k points if needed for clustering style work. Comes back as text and different schema tho, need to parse:

const parsed = JSON.parse(response.text);

User-submitted data

Notes on spatial precision

This is not crazy important since all values are from geocoded sources (as opposed to someone out in the field using GPS), but here are some notes:

  • Google's Geocoding service returns 7 decimal places (e.g. { "lat": 27.6648274, "lng": -81.5157535 }).
  • BUT the actual spec only recommends 6, as does MapBox (at the most).

So we can either POST as-is from the geocode result, or round down to the recommended, or round down even further to save space (we aren't showing data at super-close zooms anyway). If it doesn't affect how the backend schema and POST requests are structured, then let's use the untouched value from Google unless we need to start nickel-and-diming perf gains.