@unirate/nuxt
July 8, 2026 ยท View on GitHub
Nuxt module for the UniRate currency-exchange API.
- ๐ Server proxy โ your API key stays on the server; the browser only ever talks to your own app.
- ๐งฉ
useUniRate()composable โ universal (SSR + client) rate/convert/historical/VAT/time-series helpers. - ๐
useCurrency()composable โ detect the visitor's currency fromAccept-Language, persisted to a cookie. - ๐ ๏ธ
useUniRateClient()server util โ a direct, typed client for yourserver/routes. - ๐ฑ
<Currency>+<Rate>components โ locale-awareIntlformatting. - ๐ฆ Zero runtime dependencies.
@nuxt/kitis a peer (it ships with Nuxt). Nuxt 3 and Nuxt 4.
Install
npm install @unirate/nuxt
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@unirate/nuxt'],
unirate: {
// Prefer env: NUXT_UNIRATE_API_KEY (or UNIRATE_API_KEY). Avoid hardcoding.
apiKey: process.env.NUXT_UNIRATE_API_KEY,
},
})
Get a free API key at unirateapi.com. Set it via the
NUXT_UNIRATE_API_KEY environment variable so it never ends up in source control:
# .env
NUXT_UNIRATE_API_KEY=your_key_here
Why a proxy?
A currency API key is a server secret. This module registers a server route
(default /api/_unirate) that injects the key and forwards only an
allow-listed set of UniRate paths. The useUniRate() composable calls that
route โ so the key is never shipped in the client bundle, even during SSR
hydration. Set addProxy: false if you only use the server util.
Usage
Composable (pages / components)
<script setup lang="ts">
const { getRate, convert, listCurrencies } = useUniRate()
// SSR-friendly: wrap in useAsyncData so it runs once and hydrates.
const { data: rate } = await useAsyncData('usd-eur', () => getRate('USD', 'EUR'))
const { data: total } = await useAsyncData('cart', () => convert('USD', 'EUR', 49.99))
</script>
<template>
<p>1 USD = <Rate from="USD" to="EUR" :rate="rate ?? 0" /> EUR</p>
<p>Total: <Currency :amount="total ?? 0" currency="EUR" /></p>
</template>
useUniRate() returns:
| Method | Returns |
|---|---|
getRate(from, to?) | number (pair) or Record<string, number> (all rates from from) |
convert(from, to, amount) | number |
listCurrencies() | string[] |
getHistoricalRate(date, from, to?, amount?) | number or Record<string, number> (Pro) |
getTimeSeries(start, end, base?, currencies?, amount?) | Record<string, Record<string, number>> (Pro) |
getVatRates(country?) | all VAT rates or one country |
getHistoricalLimits() | available historical ranges (Pro) |
Server util (server/ routes)
When you need the typed client directly on the server (key stays server-side):
// server/api/price.get.ts
export default defineEventHandler(async () => {
const unirate = useUniRateClient()
return { eur: await unirate.convert('EUR', 100, 'USD') }
})
Visitor currency
<script setup lang="ts">
const { currency, setCurrency } = useCurrency() // e.g. 'GBP' for an en-GB visitor
</script>
<template>
<select :value="currency" @change="setCurrency(($event.target as HTMLSelectElement).value)">
<option>USD</option><option>EUR</option><option>GBP</option>
</select>
</template>
Components
<Currency :amount="1234.5" currency="EUR" :decimals="2" locale="de-DE" />
<!-- โ 1.234,50 โฌ -->
<Rate from="USD" to="JPY" :rate="157.42" :decimals="2" />
<!-- โ 157.42 -->
Configuration
unirate: {
apiKey: process.env.NUXT_UNIRATE_API_KEY, // or UNIRATE_API_KEY
baseUrl: 'https://api.unirateapi.com', // override for self-host/testing
timeoutMs: 30000,
addProxy: true, // register the server proxy route
proxyRoute: '/api/_unirate', // where the proxy is mounted
allowedPaths: undefined, // restrict the proxy's path allow-list
components: true, // register <Currency> + <Rate>
prefix: '', // e.g. 'Uni' โ <UniCurrency>, <UniRate>
cookieName: 'unirate_currency', // used by useCurrency()
}
All values can also be supplied through Nuxt runtime config env overrides
(NUXT_UNIRATE_API_KEY, NUXT_UNIRATE_BASE_URL, โฆ).
Errors
Server-side calls (useUniRateClient()) throw typed errors:
UniRateError and its subclasses AuthenticationError (401),
ProRequiredError (403 โ historical/time-series are Pro-gated on the free tier),
InvalidCurrencyError (404), InvalidRequestError (400), RateLimitError (429).
Proxy requests surface the upstream status code to useUniRate() via $fetch.
Security
- Zero runtime dependencies;
@nuxt/kitis a peer provided by Nuxt itself. - The API key is read from server runtime config only โ never bundled client-side.
- The proxy forwards an allow-listed set of paths, not arbitrary upstream URLs.
- Published to npm with provenance attestation.
Part of the UniRate ecosystem
Official UniRate clients & framework integrations: Python ยท Node ยท React ยท Next.js ยท SvelteKit ยท NestJS ยท Astro ยท Eleventy ยท MCP server
UniRate ecosystem
UniRate ships official integrations for 40+ ecosystems, all maintained under the UniRate-API org.
Core clients (9 languages) Python ยท Node.js / TypeScript ยท Go ยท Rust ยท Java ยท Ruby ยท PHP ยท .NET ยท Swift
JavaScript / TypeScript React ยท Next.js ยท Remix ยท SvelteKit ยท Vue ยท Angular ยท Nuxt ยท NestJS ยท tRPC
Static-site generators Astro ยท Eleventy ยท Hugo ยท Jekyll
CMS & e-commerce Wagtail ยท WordPress ยท WooCommerce ยท Drupal ยท Strapi ยท Medusa ยท Symfony ยท Laravel ยท Directus
Data, AI & backend LangChain (Python) ยท LangChain.js ยท FastAPI ยท Flask ยท Django REST Framework ยท Apache Airflow ยท dbt
Platform & tools MCP server ยท CLI ยท Cloudflare Workers ยท Home Assistant ยท n8n ยท Google Sheets ยท VS Code ยท Obsidian
Money library bridges money gem (Ruby) ยท NodaMoney (.NET)
Get a free API key at unirateapi.com.
License
MIT ยฉ UniRate API