Skip to content

πŸ“Š Economic Indicators Dashboard - Bazel Polyglot TutorialΒΆ

A comprehensive Bazel-based polyglot application that demonstrates building and orchestrating Go, Python, and React services in a single repository. This project fetches real economic data from the FRED API, serves it through a REST API, and visualizes it in a modern web dashboard.

🎯 What This Project Demonstrates¢

This is a teaching repository that shows:

  • βœ… Polyglot builds with Bazel (Go + Python + React)
  • βœ… Incremental compilation and caching
  • βœ… Hermetic testing without network dependencies
  • βœ… Modern toolchain integration (rules_go, rules_python, npm/vite)
  • βœ… CI/CD with GitHub Actions and Bazel caching
  • βœ… Real-world architecture patterns (data fetcher β†’ API β†’ UI)

πŸ—οΈ ArchitectureΒΆ

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Go Fetch  β”‚  writes β”‚   SQLite DB  β”‚  reads  β”‚  Python API β”‚
β”‚   Service   │────────→│  (econ.db)   │←────────│  (FastAPI)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                         β”‚
                                                         β”‚ HTTP
                                                         ↓
                                                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                                  β”‚  React UI   β”‚
                                                  β”‚   (Vite)    β”‚
                                                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

ComponentsΒΆ

  1. go_fetch/ - Go service that fetches economic indicators from FRED API
  2. Fetches 14 FRED series covering 10 high-ROI macro indicators with 30-year baseline
  3. Stores data in SQLite database (store_sqlite.go)
  4. FRED API client (fred.go)
  5. Rich metadata and categorization (metadata.go)
  6. Comprehensive data dictionary (indicators.md)
  7. Includes mock HTTP tests (fred_test.go)
  8. Bazel build config: BUILD.bazel

  9. py_api/ - Python FastAPI REST service

  10. Reads from SQLite database (db.py)
  11. Computes MoM/YoY deltas (handlers.py)
  12. FastAPI server (main.py)
  13. Exposes normalized JSON endpoints
  14. Includes fixture-based tests (test_api.py)
  15. Bazel build config: BUILD.bazel

  16. web_ui/ - React + TypeScript + Vite frontend

  17. Dashboard view with indicator cards (App.tsx)
  18. Chart component (LineChart.tsx)
  19. Detailed series view with charts
  20. Responsive design
  21. Bazel build config: BUILD.bazel

🌐 Live Demo¢

The Economic Indicators Dashboard is deployed live on GitHub Pages:

πŸš€ View Live Dashboard β†’

  • Automatic updates: Data refreshes daily at 12:00 UTC via GitHub Actions
  • Static hosting: Fully client-side React app with pre-generated JSON data
  • Zero backend: No API servers required - all data served as static files
  • Free hosting: Powered by GitHub Pages and GitHub Actions

How it WorksΒΆ

  1. GitHub Actions workflow runs daily (schedule) or manually (workflow_dispatch)
  2. Bazel builds the Go fetch service and fetches latest FRED data
  3. JSON export generates static data files (summary.json, series-*.json)
  4. React build creates optimized production bundle with data files
  5. GitHub Pages serves the static site

See .github/workflows/update-dashboard.yaml for the complete workflow.


πŸš€ Quick StartΒΆ

PrerequisitesΒΆ

  1. Install Bazel (6.4.0 or later)

    # macOS
    brew install bazel
    
    # Linux
    # Download from https://github.com/bazelbuild/bazel/releases
    
    # Verify installation
    bazel --version
    

  2. Get a FRED API Key (free)

  3. Sign up at: https://fred.stlouisfed.org/docs/api/api_key.html
  4. Set environment variable:
    export FRED_API_KEY=your_api_key_here
    

Running the DashboardΒΆ

# Start everything with one script
./run_all.sh

This will: 1. Fetch latest economic data from FRED 2. Start the Python API server on http://localhost:8000 3. Show instructions for starting the web UI

Then in another terminal:

cd web_ui
npm install  # First time only
npm run dev

Open http://localhost:3000 in your browser πŸŽ‰

πŸ“Š View Live Dashboard

Once running, access the dashboard at:

Option 2: Run Components IndividuallyΒΆ

# 1. Fetch data
bazel run //go_fetch:refresh

# 2. Start API (in one terminal)
bazel run //py_api:server

# 3. Start UI (in another terminal)
cd web_ui && npm install && npm run dev

πŸ§ͺ TestingΒΆ

All tests use fixtures and mocks - no network access required!

# Run all tests
bazel test //...

# Run specific tests
bazel test //go_fetch:fred_test
bazel test //py_api:api_test

# View test output
bazel test //... --test_output=all

πŸ—οΈ BuildingΒΆ

# Build everything
bazel build //...

# Build specific targets
bazel build //go_fetch:refresh
bazel build //py_api:server
bazel build //web_ui:build

# Query the build graph
bazel query //...
bazel query 'deps(//py_api:server)'

πŸ“Š Available IndicatorsΒΆ

The dashboard tracks 10 core high-ROI macroeconomic indicators (14 FRED series total) with 30-year baseline coverage:

Core IndicatorsΒΆ

# Indicator FRED Codes Category Coverage
1️⃣ Real GDP GDPC1 Growth 1947β†’
2️⃣ CPI (Inflation) CPIAUCSL, CPILFESL Inflation 1947β†’
3️⃣ Unemployment Rate UNRATE Labor Market 1948β†’
4️⃣ Fed Funds Rate FEDFUNDS Monetary Policy 1954β†’
5️⃣ Treasury Yield Curve T10Y2Y, DGS10, DGS2 Yield Curve 1976β†’
6️⃣ M2 Money Supply M2SL Liquidity 1959β†’
7️⃣ Brent Crude Oil POILBREUSDM Commodities 1987β†’
8️⃣ Manufacturing MANEMP Manufacturing 1939β†’
9️⃣ Consumer Sentiment UMCSENT Sentiment 1978β†’
πŸ”Ÿ Global Trade IMPCH, EXPCH Trade 1947β†’

Coverage: All indicators have data back to 1990 or earlier βœ…

Detailed Specifications: See go_fetch/indicators.md for complete data dictionary

Economic CategoriesΒΆ

Indicators are organized by economic domain:

  • Growth: Real GDP
  • Inflation: Headline CPI, Core CPI
  • Labor Market: Unemployment Rate
  • Monetary Policy: Federal Funds Rate
  • Yield Curve: 10Y-2Y Spread, Treasury Yields
  • Liquidity: M2 Money Supply
  • Commodities: Oil Prices (also relevant for inflation analysis)
  • Manufacturing: Employment
  • Sentiment: Consumer Confidence
  • Trade: Real Imports/Exports

πŸ”Œ API EndpointsΒΆ

GET /api/healthΒΆ

Health check and service status

GET /api/econ/summaryΒΆ

Summary of all indicators with latest values and deltas

GET /api/econ/series?code=<CODE>&range=<RANGE>ΒΆ

Time series data for a specific indicator - code: Series code (e.g., CPIAUCSL) - range: Time range - 1y, 5y, or max (default)

GET /api/econ/metaΒΆ

Metadata about all available series

API documentation: http://localhost:8000/docs


🧱 Bazel Concepts¢

MODULE.bazelΒΆ

This file defines external dependencies using Bzlmod (Bazel's modern dependency system):

  • rules_go - Go toolchain and build rules
  • rules_python - Python toolchain and pip integration
  • aspect_rules_js - Modern JavaScript/Node.js support

BUILD.bazel FilesΒΆ

Each component has a BUILD.bazel file that defines: - Binaries (go_binary, py_binary) - Executable programs - Libraries (go_library, py_library) - Reusable code - Tests (go_test, py_test) - Test targets

Example from go_fetch/BUILD.bazel:

go_binary(
    name = "refresh",
    srcs = ["main.go"],
    deps = [":go_fetch_lib"],
)

Targets and LabelsΒΆ

Targets are referenced with labels: //package:target - //go_fetch:refresh - Go binary in go_fetch package - //py_api:server - Python server binary - //... - All targets in the repository


πŸ”„ Incremental BuildsΒΆ

Bazel only rebuilds what changed. Try this:

# First build (downloads deps, compiles everything)
bazel build //...

# Edit go_fetch/main.go
# Only Go targets rebuild!
bazel build //...

# Edit py_api/handlers.py
# Only Python targets rebuild!
bazel build //...

πŸš€ Deploy Your Own DashboardΒΆ

Want to deploy your own version on GitHub Pages? Here's how:

Step 1: Fork the RepositoryΒΆ

Fork bazel-tutorial to your GitHub account.

Step 2: Create a Personal Access Token (PAT)ΒΆ

The workflow needs a PAT to bypass branch protection rules when committing data updates.

  1. Go to: https://github.com/settings/tokens/new
  2. Configure the token:
  3. Note: bazel-tutorial-workflow (or any descriptive name)
  4. Expiration: Choose desired expiration (recommend 90 days or longer)
  5. Select scopes:
    • βœ… repo (Full control of private repositories)
    • βœ… workflow (Update GitHub Action workflows)
  6. Click Generate token
  7. Copy the token (you won't see it again!)

Step 3: Configure GitHub SecretsΒΆ

  1. Go to your fork's Settings β†’ Secrets and variables β†’ Actions
  2. Add two repository secrets:

First secret: - Name: FRED_API_KEY - Value: Your FRED API key (get one free here)

Second secret: - Name: WORKFLOW_PAT - Value: The Personal Access Token you created above

Step 4: Enable GitHub PagesΒΆ

  1. Go to Settings β†’ Pages
  2. Under Source, select GitHub Actions
  3. The workflow will automatically deploy your dashboard

Step 5: Trigger the WorkflowΒΆ

  1. Go to Actions tab
  2. Select Update Economic Dashboard workflow
  3. Click Run workflow β†’ Run workflow

Within a few minutes, your dashboard will be live at:

https://YOUR-USERNAME.github.io/bazel-tutorial/

Customization OptionsΒΆ

Change update frequency: Edit .github/workflows/update-dashboard.yaml:

schedule:
  # Run hourly instead of daily
  - cron: '0 * * * *'

Add more indicators: Edit go_fetch/main.go:

defaultSeries = []string{
    "CPIAUCSL",
    "UNRATE",
    "GDPC1",  // Add GDP
    "DEXUSEU", // Add EUR/USD exchange rate
}

Customize UI: Edit web_ui/src/App.tsx and web_ui/src/App.css


πŸŽ“ How to ExtendΒΆ

Adding a New Economic IndicatorΒΆ

  1. Update go_fetch/main.go - Add series code to defaultSeries

    defaultSeries = []string{
        "CPIAUCSL",
        "UNRATE",
        "GDPC1",  // ← Add new indicator
    }
    

  2. Refresh data

    bazel run //go_fetch:refresh
    

  3. Indicator automatically appears in UI - No frontend changes needed!

Adding Go DependenciesΒΆ

  1. Add to go_fetch/go.mod:

    require github.com/some/package v1.0.0
    

  2. Run:

    cd go_fetch && go mod tidy
    bazel run //:gazelle
    

Adding Python DependenciesΒΆ

  1. Add to py_api/requirements.txt:

    requests==2.31.0
    

  2. Update MODULE.bazel pip.parse section

  3. Rebuild:

    bazel build //py_api:server
    


πŸ” TroubleshootingΒΆ

"Database not found"ΒΆ

Solution: Run the data fetcher first:

bazel run //go_fetch:refresh

"FRED_API_KEY not set"ΒΆ

Solution: Get a free API key and set it:

export FRED_API_KEY=your_key_here

"Build is slow"ΒΆ

Solution: First build downloads all dependencies. Subsequent builds are fast due to caching.

"Tests failing"ΒΆ

Solution: Tests are hermetic and don't need network/API keys. If failing, check:

bazel test //... --test_output=errors

"Web UI not loading"ΒΆ

Solution: Ensure API server is running:

bazel run //py_api:server  # In one terminal
cd web_ui && npm run dev   # In another terminal


πŸ“ Repository StructureΒΆ

bazel-tutorial/
β”œβ”€β”€ MODULE.bazel              # Bazel dependencies (Bzlmod)
β”œβ”€β”€ .bazelrc                  # Bazel configuration
β”œβ”€β”€ .bazelversion             # Pin Bazel version
β”œβ”€β”€ run_all.sh               # Convenience script to start all services
β”‚
β”œβ”€β”€ go_fetch/                # Go data fetcher service
β”‚   β”œβ”€β”€ main.go              # CLI entry point
β”‚   β”œβ”€β”€ fred.go              # FRED API client
β”‚   β”œβ”€β”€ store_sqlite.go      # SQLite storage
β”‚   β”œβ”€β”€ fred_test.go         # Tests with mocks
β”‚   β”œβ”€β”€ go.mod               # Go dependencies
β”‚   └── BUILD.bazel          # Bazel build config
β”‚
β”œβ”€β”€ py_api/                  # Python FastAPI service
β”‚   β”œβ”€β”€ main.py              # FastAPI server
β”‚   β”œβ”€β”€ handlers.py          # API endpoints
β”‚   β”œβ”€β”€ db.py                # Database layer
β”‚   β”œβ”€β”€ test_api.py          # Tests with fixtures
β”‚   β”œβ”€β”€ requirements.txt     # Python dependencies
β”‚   └── BUILD.bazel          # Bazel build config
β”‚
β”œβ”€β”€ web_ui/                  # React frontend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ App.tsx          # Main app component
β”‚   β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”‚   β”œβ”€β”€ IndicatorCard.tsx
β”‚   β”‚   β”‚   └── LineChart.tsx
β”‚   β”‚   └── main.tsx
β”‚   β”œβ”€β”€ package.json         # npm dependencies
β”‚   β”œβ”€β”€ vite.config.ts       # Vite configuration
β”‚   └── BUILD.bazel          # Bazel build config
β”‚
β”œβ”€β”€ data/                    # SQLite database (gitignored)
β”‚   └── econ.db              # Created by go_fetch
β”‚
└── .github/workflows/
    └── ci.yaml              # CI/CD pipeline

πŸ” ConfigurationΒΆ

Environment VariablesΒΆ

  • FRED_API_KEY - Required for data fetching
  • ECON_DB_PATH - Database path (default: ./data/econ.db)
  • PORT - API server port (default: 8000)

FilesΒΆ

  • .env - Local environment variables (create yourself, not committed)
  • .bazelrc - Bazel configuration (caching, output options)

🚒 CI/CD¢

The project includes GitHub Actions workflow (.github/workflows/ci.yaml) that:

  1. βœ… Sets up Bazel and caches dependencies
  2. βœ… Builds all targets (bazel build //...)
  3. βœ… Runs all tests (bazel test //...)
  4. βœ… Uses Bazel cache for fast builds

Bazel's hermetic builds ensure CI runs are deterministic and cacheable.


🧠 Why Bazel for Polyglot Repos?¢

Benefits Demonstrated in This ProjectΒΆ

  1. Single Build System
  2. One tool for Go, Python, and JavaScript
  3. Consistent commands across languages

  4. Incremental Builds

  5. Only rebuild what changed
  6. Shared cache across projects

  7. Hermetic Testing

  8. Tests don't depend on network or system state
  9. Use mocks and fixtures

  10. Explicit Dependencies

  11. Clear dependency graph
  12. No hidden dependencies

  13. Scalability

  14. Works for small projects (this) and massive monorepos (Google)
  15. Parallel builds and tests

πŸ“š Learning ResourcesΒΆ

BazelΒΆ

RulesΒΆ

Economic DataΒΆ


🀝 Contributing¢

This is a tutorial project. Contributions welcome!

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure bazel test //... passes
  5. Submit a pull request

πŸ“„ LicenseΒΆ

MIT License - See LICENSE file for details


πŸŽ‰ AcknowledgmentsΒΆ

  • FRED - Federal Reserve Economic Data
  • Bazel - Google's build system
  • FastAPI - Modern Python web framework
  • React - UI library
  • Vite - Fast build tool

Happy Building! πŸš€

For questions or issues, please open a GitHub issue.