Eleventy plugin for UniRate — fetches a currency exchange rate snapshot at build time, exposes it through unirate global data, and ships currency / rate / convert shortcodes and filters.
- Build-time snapshot: rates resolve to constants in your static HTML; no client-side API key, no runtime fetch.
- Zero runtime dependencies (uses native
fetch). - Cross-pair conversion derived from a single base, so the snapshot stays small.
- Works in Nunjucks and Liquid (Eleventy's default engines).
npm install @unirate/eleventyYou'll need a free UniRate API key — grab one at https://unirateapi.com.
// eleventy.config.mjs
import unirate from "@unirate/eleventy";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(unirate, {
apiKey: process.env.UNIRATE_API_KEY,
baseCurrency: "USD",
currencies: ["EUR", "GBP", "JPY", "CAD", "AUD"],
});
}If apiKey is omitted the plugin reads UNIRATE_API_KEY from the environment.
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
process.env.UNIRATE_API_KEY |
UniRate API key. |
baseCurrency |
string |
"USD" |
Base the build-time snapshot is keyed against. |
currencies |
string[] |
all UniRate currencies | Optional allowlist to shrink the bundled snapshot. |
apiBaseUrl |
string |
"https://api.unirateapi.com" |
API host. Override for self-hosted or testing. |
failOnFetchError |
boolean |
true |
Fail the build if the snapshot fetch fails. Set to false to ship an empty snapshot and let templates fall back gracefully. |
shortcodePrefix |
string |
"" |
Namespace prefix. Set to e.g. "unirate" to register shortcodes/filters as unirateCurrency, unirateRate, unirateConvert. |
{# Convert and format an amount #}
<p>Total: {% currency 100, "USD", "EUR" %}</p>
<p>JPY: {% currency 1234.5, "USD", "JPY", { minimumFractionDigits: 0 } %}</p>
<p>Code style: {% currency 100, "USD", "EUR", { currencyDisplay: "code" } %}</p>
{# Just the rate, fixed precision #}
<p>USD/EUR: {% rate "USD", "EUR" %}</p>
<p>Cross-pair: {% rate "EUR", "GBP", 6 %}</p>
{# Just the converted amount (no currency formatting) #}
<p>50 USD ≈ {% convert 50, "USD", "GBP" %} GBP</p>The same three operations are available as filters for inline use:
<p>Total: {{ 100 | currency("USD", "EUR") }}</p>
<p>Rate: {{ "USD" | rate("EUR") }}</p>
<p>Converted: {{ 50 | convert("USD", "GBP") }}</p>Liquid uses the same names:
{{ 100 | currency: "USD", "EUR" }}The full snapshot is exposed as unirate:
<p>Base: {{ unirate.base }}</p>
<p>EUR rate: {{ unirate.rates.EUR }}</p>
<footer>Rates as of {{ unirate.fetchedAt }}</footer>import { convertCurrency, getRate, formatCurrency } from "@unirate/eleventy/runtime";
const snap = { base: "USD", rates: { USD: 1, EUR: 0.925 }, fetchedAt: null };
formatCurrency(convertCurrency(snap, 100, "USD", "EUR"), "EUR");
// → "€92.50"addGlobalData("unirate", ...) registers an async thunk that fetches /api/rates?from=<baseCurrency>[&to=...] once before any template is rendered. The result is cached, then shared with the shortcode and filter implementations, so every conversion in every template reads from the same in-memory snapshot.
Cross-pair rates are derived: rate(from → to) = rate(base → to) / rate(base → from). This means a snapshot keyed against USD can convert EUR → GBP without an extra fetch.
UniRate ships official client libraries and framework integrations across the ecosystem. The repos below are all maintained under the UniRate-API org.
- Languages: Python · Node.js / TypeScript · Go · Rust · Java · Ruby · PHP · .NET · Swift
- Web frameworks: NestJS · Django / Wagtail · FastAPI · Flask · React · tRPC
- Static-site generators: Astro · Eleventy · Hugo
- Data / orchestration: Airflow · dbt · LangChain
- Workflow / no-code: n8n · Google Sheets · MCP server
- Editors / tools: VS Code · Obsidian
- Specialty bridges: NodaMoney (.NET)
Get a free API key at unirateapi.com.
MIT