Central Bank Rates Demo — central-bank-rates-demo
A sample static site that pulls the official published exchange-rate tables from 34 central banks — one npm package per bank — and renders them as a single self-contained dashboard. Built for developers evaluating the AllRatesToday Central Bank Rates API who want to see the per-bank SDKs actually working before writing any code.
Live site: https://allrates-today.github.io/central-bank-rates-demo/
These are the bank-published reference rates used for tax, customs, audit and compliant invoicing — not market ticks. Each response carries the bank's own publication date (rate_date).
🚀 Features
- 🏦 34 central banks, 34 npm packages — every card on the page is produced by a different SDK; the import is the demo
- 📦 Zero-dependency SDKs — each
*-exchange-rate package is a thin fetch wrapper over the API, no transitive deps
- 🗓️ Daily rebuild — a scheduled GitHub Actions workflow regenerates and redeploys the page daily, scheduled 06:30 UTC (GitHub may delay)
- 🔒 Key never shipped — the API key is read from an Actions secret at build time and never appears in the repo or the published HTML
- 🪶 One static file — the build writes a single
dist/index.html with inline CSS, dark-mode support and a client-side bank filter
- 🧯 Fault tolerant — a bank whose fetch fails renders an error card instead of breaking the build; the build only aborts if every fetch fails
🔑 Get your API key
The build needs an AllRatesToday API key in ALLRATES_API_KEY: the per-bank SDKs used here require one. (Outside the SDKs, every bank's latest table is also available keyless at https://allratestoday.com/api/open/central-bank/{bank}, e.g. /api/open/central-bank/ecb.)
Get a free key (no credit card) at allratestoday.com/register.
For the deployed site the key lives in a repository secret named ALLRATES_API_KEY, injected into the build step by .github/workflows/deploy.yml. Forks must add their own secret under Settings → Secrets and variables → Actions before the workflow will succeed.
📦 Installation
git clone https://github.com/AllRates-Today/central-bank-rates-demo
cd central-bank-rates-demo
npm install
Node.js 18 or newer (the SDKs use global fetch). The repo is private: true — it is a demo, not a published package.
🏁 Quick start
ALLRATES_API_KEY=art_live_your_key npm run build
open dist/index.html
npm run build runs build.mjs, which:
- Reads the bank list from
banks.mjs — npm package name, display name, country, home currency, flag and an example pair per bank.
- Dynamically
import()s each bank's package and calls getLatestRates({ apiKey }) — the bank's full published table for its latest date — six banks at a time.
- Picks up to six representative pairs per bank (the bank's example pair, then
USD, EUR, GBP, JPY, CNY, INR, AUD, CHF).
- Renders everything into one self-contained
dist/index.html, with a per-bank "Use this SDK" snippet and links to npm, GitHub and the bank's API docs page.
Missing the key exits with code 1 and a pointer to the register page. Every fetch failing also exits 1, rather than publishing an empty dashboard.
🔄 How the daily rebuild works
.github/workflows/deploy.yml has three triggers: push to main, workflow_dispatch, and schedule at cron 30 6 * * * — scheduled daily at 06:30 UTC (GitHub may delay), after most banks publish their morning tables.
| Stage | What happens |
|---|
build job | npm ci, then npm run build with ALLRATES_API_KEY from secrets.ALLRATES_API_KEY, then uploads dist/ as a Pages artifact |
deploy job | Publishes that artifact to the github-pages environment via actions/deploy-pages |
| Concurrency | Grouped on pages with cancel-in-progress: true, so a push during a scheduled run supersedes it |
| Permissions | contents: read, pages: write, id-token: write |
Central banks publish once per business day, so building statically once a day costs 34 API calls per build (a deployment that rebuilds daily needs a paid plan). That is the pattern worth copying: cache the daily table, don't call the API per page view.
📚 SDK reference
Every *-exchange-rate package exposes the same four functions. options.apiKey is required on all of them.
| Function | Description | Plan |
|---|
getLatestRates(options) | The bank's latest published table — rate_date plus every rates[] entry | All plans, including free |
getRate(source, target, options) | Latest rate for one pair | All plans, including free |
getRatesForDate(date, options) | Published table for a YYYY-MM-DD date; weekends and holidays return the most recent published date | Paid |
getHistory(query, options) | Daily time series — { symbol } or { source, target }, optional from/to | Paid |
Errors are thrown as Error with .status and .body attached from the API response.
💡 Use one SDK in your own project
npm install ecb-exchange-rate
import { getLatestRates, getRate } from 'ecb-exchange-rate';
const table = await getLatestRates({ apiKey: process.env.ALLRATES_API_KEY });
console.log(table.rate_date, table.rates.length);
const pair = await getRate('USD', 'EUR', { apiKey: process.env.ALLRATES_API_KEY });
console.log(pair);
To add or remove a bank from this demo, edit banks.mjs and add the matching dependency to package.json — nothing in build.mjs is bank-specific.
🗺️ Banks covered
The 34 banks wired into this demo, from banks.mjs. The API itself covers more central banks (plus tax authorities) than the demo installs — see the full coverage list.
🛡️ Error handling
| Symptom | Cause | Fix |
|---|
Missing ALLRATES_API_KEY environment variable. (exit 1) | No key in the environment | Export ALLRATES_API_KEY, or add the Actions secret for CI builds |
| One card reads "Fetch failed during this build" | That bank's request threw; the message is printed to the build log and rendered on the card | Check the log line for the package name and the API error |
Every fetch failed — refusing to build an empty page. (exit 1) | Bad or exhausted key, or no network | Verify the key and your remaining quota |
An apiKey is required thrown by an SDK | options.apiKey not passed | Pass { apiKey } to every SDK call |
Common API statuses: 401 missing or invalid key · 429 rate limit or monthly quota exceeded. Historical dates and time series (getRatesForDate, getHistory) need a paid plan.
🔗 Links
📜 License
MIT, as declared in package.json.