AirGradient Map is a web application for visualizing and analyzing air quality data.
🌍 Explore it live: map.airgradient.com
The old app’s tech stack can’t scale to meet our requirements, so we’ve built this new codebase. First, we’ll migrate all existing features here; once that’s done, we’ll layer on new enhancements and capabilities.
Have questions or want to share feedback? Join our community on Discord to chat, ask questions, and collaborate with other contributors!
- Clone the repository:
git clone https://github.com/airgradienthq/airgradient-map
cd airgradient-map- Configure .env configuration
You have an .env.development.example file in apps/api.
Make a copy next to it and name it .env.development.
From .env.development the only necessary thing that needs to be changed is API_KEY_OPENAQ.
To get the key, please follow steps from OpenAQ here
- Run the containers
We have docker compose files that build and run containers:
postgrex-mono: PostgreSQL database with PostGISdb-migrate-mono: Database migration runner (runs automatically)mapapi-mono: NestJS API backendcron-mono: Background cron jobswebsite-mono: Nuxt.js frontend
To spin them up, run from the root of this repo:
docker compose --env-file apps/api/.env.development -f docker-compose-dev.yml upWhat happens automatically:
- PostgreSQL starts and initializes
- Database migrations run automatically (all tables created)
- API and cron services start (database is ready)
- Frontend starts
This automatically builds and starts the necessary containers. When developing and changing source files, the api service automatically reloads the source files. Use the --build option when you change npm dependencies and need to rebuild the image. Optionally use the -d option for running detached in the background.
To stop the services, run:
docker compose --env-file apps/api/.env.development -f docker-compose-dev.yml down- Database Migrations & Seeding
This project uses Knexjs for database migrations and seeding to keep the schema and test data consistent with project changes.
⚠️ Important for Existing Developers:If you've previously run this project before automated migrations were introduced, it's recommended to start fresh by removing the existing Postgres volume:
docker compose --env-file apps/api/.env.development -f docker-compose-dev.yml down -v
API Errors in Docker can be seen with:
docker logs mapapi-mono --tail 100
- Migrations (Automatic)
Migrations now run automatically when you start the containers. You don't need to run them manually.
If you need to run migrations manually for testing:
docker exec -it mapapi-mono npx knex migrate:latest --knexfile knexfile.ts- Seed Data (Optional)
Populate tables with sample/initial data for development:
docker exec -it mapapi-mono npx knex seed:run --knexfile knexfile.tsExample Output:
Requiring external module ts-node/register
Seeded 1761 owner
Seeded 14176 locations with PostgreSQL timestamps
Processing 65680 measurement records...
Inserted 1000 of 65680 records
Inserted 6000 of 65680 records
Inserted 11000 of 65680 records
Inserted 16000 of 65680 records
Inserted 21000 of 65680 records
Inserted 26000 of 65680 records
Inserted 31000 of 65680 records
Inserted 36000 of 65680 records
Inserted 41000 of 65680 records
Inserted 46000 of 65680 records
Inserted 51000 of 65680 records
Inserted 56000 of 65680 records
Inserted 61000 of 65680 records
Inserted 65680 of 65680 records
Seeded 65680 measurements mapped to the last 6 hours
Ran 3 seed files
- Verify Database Setup
Check that the data has been seeded correctly:
docker exec -it postgrex-mono psql -U postgres -d agmap -c "select count(*) from location;"Expected result (row count may differ if seed data changes):
count
-------
14176
(1 row)- Check the UI
The application is running on http://localhost:3000/ and calls http://localhost:3001/ for the backend. You should see the map with the data showing up.
Please note that the compile log shows running on http://0.0.0.0:3000/ but this will cause CORS issues. So make sure you use http://localhost:3000/.
We welcome contributions from the community!
If you're new to the project:
- Please start by forking this repository and submitting pull requests from your fork.
- If you become an active contributor, we'll be happy to invite you to join as a collaborator.
Every pull request triggers two GitHub Actions workflows:
- Prettier Check (
.github/workflows/format.yml): Runsnpm run format:checkinside each app that changed (website/api). Fix locally vianpm run format. - Lint Code (
.github/workflows/lint.yml): Runsnpm run lintinside each modified app. Resolve issues locally before pushing.
To keep CI green, install dependencies inside the relevant apps/<name> directory and run both commands prior to opening your PR.
We use the GitHub Project board to track issues and development workflow.
Labels like P0, P1, and P2 help guide prioritization. These are visible on the project board, not directly in the issues list.
If you'd like to work on an issue:
- Leave a comment on the issue stating that you'd like to take it.
- A maintainer will assign the issue to you.
If you're working on an issue or it's ready for review, and the project board doesn't reflect that:
- Leave a comment in the issue. We'll move the card to the correct status.
Since this project maintains database migrations using Knexjs, run below command to create new migration file:
cd apps/api
npx knex migrate:make <MIGRATION_NAME> --knexfile knexfile.tsThis creates a new migration file in apps/api/database/migrations/. When you restart the docker-compose stack, the new migration will run automatically.
Please see Knexjs migration documentation for more information.
Thanks for contributing to AirGradient Map! 🚀