
Research
/Security News
Miasma Mini Shai-Hulud Hits ImmobiliareLabs npm Packages
Miasma Mini Shai-Hulud hits @immobiliarelabs Backstage plugins, targeting GitLab and LDAP auth packages on npm.
@iamjr15/react-currency-localizer
Advanced tools
A React hook to display prices in a user's local currency using HTTPS-compatible IP geolocation with robust validation and error handling
A React hook for automatically displaying prices in a user's local currency using IP geolocation. Built with a robust two-API architecture using specialized services for maximum accuracy and reliability. Perfect for e-commerce sites, pricing pages, and international applications.
ipapi.co for HTTPS-compatible currency detection (no API key required)exchangerate-api.com for real-time conversion rates# npm
npm install @iamjr15/react-currency-localizer @tanstack/react-query
# yarn
yarn add @iamjr15/react-currency-localizer @tanstack/react-query
# pnpm
pnpm add @iamjr15/react-currency-localizer @tanstack/react-query
Note:
@tanstack/react-queryis a peer dependency required for caching and data fetching.
import { CurrencyConverterProvider } from '@iamjr15/react-currency-localizer'
function App() {
return (
<CurrencyConverterProvider>
<YourAppContent />
</CurrencyConverterProvider>
)
}
import { useCurrencyConverter } from '@iamjr15/react-currency-localizer'
function ProductPrice({ price }: { price: number }) {
const {
convertedPrice,
localCurrency,
isLoading,
error
} = useCurrencyConverter({
basePrice: price,
baseCurrency: 'USD',
apiKey: 'your-exchangerate-api-key' // Get free key from exchangerate-api.com
})
if (isLoading) return <span>Loading price...</span>
if (error) return <span>${price}</span> // Fallback to original price
return (
<span>
{new Intl.NumberFormat(undefined, {
style: 'currency',
currency: localCurrency || 'USD'
}).format(convertedPrice || price)}
</span>
)
}
import { LocalizedPrice } from '@iamjr15/react-currency-localizer'
function ProductCard() {
return (
<div>
<h3>Premium Plan</h3>
<LocalizedPrice
basePrice={99.99}
baseCurrency="USD"
apiKey="your-api-key"
/>
</div>
)
}
useCurrencyConverter(options)The main hook for currency conversion.
| Parameter | Type | Required | Description |
|---|---|---|---|
basePrice | number | ✅ | The price in the base currency |
baseCurrency | string | ✅ | ISO 4217 currency code (case-insensitive, e.g., 'USD' or 'usd') |
apiKey | string | ✅ | API key from exchangerate-api.com (validated for helpful error messages) |
manualCurrency | string | ❌ | Override detected currency (case-insensitive) |
onSuccess | function | ❌ | Callback on successful conversion |
onError | function | ❌ | Callback on error |
| Property | Type | Description |
|---|---|---|
convertedPrice | number | null | Price in local currency |
localCurrency | string | null | Detected/manual currency code |
baseCurrency | string | Original currency code |
exchangeRate | number | null | Exchange rate used |
isLoading | boolean | Loading state |
error | Error | null | Error object if any |
<LocalizedPrice />React component for displaying localized prices.
| Prop | Type | Required | Description |
|---|---|---|---|
basePrice | number | ✅ | The price in base currency |
baseCurrency | string | ✅ | ISO 4217 currency code (case-insensitive) |
apiKey | string | ✅ | ExchangeRate API key (validated automatically) |
manualCurrency | string | ❌ | Override detected currency (case-insensitive) |
loadingComponent | ReactNode | ❌ | Custom loading component |
errorComponent | function | ❌ | Custom error component (if not provided, shows original price as fallback) |
formatPrice | function | ❌ | Custom price formatter |
function ProductGrid() {
const products = [
{ id: 1, name: 'T-Shirt', price: 29.99 },
{ id: 2, name: 'Jeans', price: 79.99 },
{ id: 3, name: 'Sneakers', price: 129.99 }
]
return (
<div className="grid">
{products.map(product => (
<div key={product.id} className="product-card">
<h3>{product.name}</h3>
<LocalizedPrice
basePrice={product.price}
baseCurrency="USD"
// Vite: import.meta.env.VITE_EXCHANGE_API_KEY
// CRA: process.env.REACT_APP_EXCHANGE_API_KEY
// Next.js: process.env.NEXT_PUBLIC_EXCHANGE_API_KEY
apiKey={process.env.REACT_APP_EXCHANGE_API_KEY}
/>
</div>
))}
</div>
)
}
function PricingTable() {
const plans = [
{ name: 'Basic', price: 9.99 },
{ name: 'Pro', price: 19.99 },
{ name: 'Enterprise', price: 49.99 }
]
return (
<div className="pricing-table">
{plans.map(plan => (
<div key={plan.name} className="plan">
<h3>{plan.name}</h3>
<LocalizedPrice
basePrice={plan.price}
baseCurrency="USD"
// Vite: import.meta.env.VITE_EXCHANGE_API_KEY
// CRA: process.env.REACT_APP_EXCHANGE_API_KEY
// Next.js: process.env.NEXT_PUBLIC_EXCHANGE_API_KEY
apiKey={process.env.REACT_APP_EXCHANGE_API_KEY}
formatPrice={(price, currency) =>
`${currency} ${price.toFixed(2)}/month`
}
/>
</div>
))}
</div>
)
}
function CurrencySelector() {
const [selectedCurrency, setSelectedCurrency] = useState('')
return (
<div>
<select
value={selectedCurrency}
onChange={(e) => setSelectedCurrency(e.target.value)}
>
<option value="">Auto-detect</option>
<option value="USD">USD</option>
<option value="EUR">EUR</option>
<option value="GBP">GBP</option>
<option value="JPY">JPY</option>
</select>
<LocalizedPrice
basePrice={99.99}
baseCurrency="USD"
// Vite: import.meta.env.VITE_EXCHANGE_API_KEY
// CRA: process.env.REACT_APP_EXCHANGE_API_KEY
// Next.js: process.env.NEXT_PUBLIC_EXCHANGE_API_KEY
apiKey={process.env.REACT_APP_EXCHANGE_API_KEY}
manualCurrency={selectedCurrency || undefined}
/>
</div>
)
}
function PriceWithStates() {
const { convertedPrice, localCurrency, isLoading, error } = useCurrencyConverter({
basePrice: 59.99,
baseCurrency: 'usd', // Case-insensitive! Will be converted to 'USD'
// Vite: import.meta.env.VITE_EXCHANGE_API_KEY
// CRA: process.env.REACT_APP_EXCHANGE_API_KEY
// Next.js: process.env.NEXT_PUBLIC_EXCHANGE_API_KEY
apiKey: process.env.REACT_APP_EXCHANGE_API_KEY,
onSuccess: (result) => {
console.log('Conversion successful:', result)
},
onError: (error) => {
console.error('Conversion failed:', error.message)
// You'll get helpful error messages like:
// "API key is missing. Please provide a valid key from exchangerate-api.com."
// "Currency 'XYZ' was detected from your location but is not supported by the exchange rate provider."
}
})
if (isLoading) {
return (
<div className="price-loading">
<div className="spinner" />
<span>Converting price...</span>
</div>
)
}
if (error) {
return (
<div className="price-error">
<span>$59.99 USD</span>
<small>Unable to convert: {error.message}</small>
</div>
)
}
return (
<div className="price-success">
{new Intl.NumberFormat(undefined, {
style: 'currency',
currency: localCurrency || 'USD'
}).format(convertedPrice || 59.99)}
</div>
)
}
// LocalizedPrice automatically shows original price if conversion fails
function AutoFallbackPrice() {
return (
<LocalizedPrice
basePrice={99.99}
baseCurrency="usd" // Case doesn't matter
apiKey="" // Empty key will show helpful error, then fallback to original price
/>
// If API fails: Shows "$99.99" with tooltip "Conversion failed, showing original price in USD"
)
}
// Or provide custom error component for full control
function CustomErrorPrice() {
return (
<LocalizedPrice
basePrice={99.99}
baseCurrency="USD"
// Vite: import.meta.env.VITE_EXCHANGE_API_KEY
// CRA: process.env.REACT_APP_EXCHANGE_API_KEY
// Next.js: process.env.NEXT_PUBLIC_EXCHANGE_API_KEY
apiKey={process.env.REACT_APP_EXCHANGE_API_KEY}
errorComponent={(error) => (
<div className="price-error">
<span className="price">$99.99</span>
<span className="error-badge">Conversion Error</span>
<small>{error.message}</small>
</div>
)}
/>
)
}
This package uses a carefully designed architecture for maximum reliability and performance:
We use a decoupled, two-API approach for maximum accuracy and flexibility:
Specialized Geolocation Service: ipapi.co
Specialized Financial Data Service: exchangerate-api.com
We use TanStack Query (not basic useEffect/useState) for robust data management:
We implement data-type-specific caching optimized for each type of data:
ExchangeRate-API (Required):
IP Geolocation (Automatic):
# .env
VITE_EXCHANGE_API_KEY=your_exchangerate_api_key_here
# Optional: Enable integration tests with real APIs
VITE_RUN_INTEGRATION_TESTS=true
For different frameworks:
# Vite (browser-exposed)
VITE_EXCHANGE_API_KEY=your_exchangerate_api_key_here
# Create React App (browser-exposed)
REACT_APP_EXCHANGE_API_KEY=your_exchangerate_api_key_here
# Next.js (browser-exposed)
NEXT_PUBLIC_EXCHANGE_API_KEY=your_exchangerate_api_key_here
The package uses TanStack Query for robust state management with optimal caching:
import { QueryClient } from '@tanstack/react-query'
import { CurrencyConverterProvider } from '@iamjr15/react-currency-localizer'
// Custom QueryClient with optimized caching strategy
const queryClient = new QueryClient({
defaultOptions: {
queries: {
// Geolocation queries: 24+ hour stale time (location rarely changes)
staleTime: 1000 * 60 * 60 * 24, // 24 hours
// Exchange rate queries: 1 hour stale time (balance freshness vs performance)
gcTime: 1000 * 60 * 60 * 2, // 2 hours cache time
retry: 1, // Conservative retry to respect API limits
},
},
})
function App() {
return (
<CurrencyConverterProvider queryClient={queryClient}>
<YourApp />
</CurrencyConverterProvider>
)
}
Note: The default configuration already implements the optimal caching strategy. Custom configuration is optional.
When using this library with SSR frameworks (Next.js, Nuxt, SvelteKit), be aware that:
manualCurrency prop or perform geolocation client-side only// For SSR: Disable geolocation on server, enable on client
const [isClient, setIsClient] = useState(false)
useEffect(() => {
setIsClient(true)
}, [])
return (
<LocalizedPrice
basePrice={99.99}
baseCurrency="USD"
apiKey={process.env.NEXT_PUBLIC_EXCHANGE_API_KEY}
manualCurrency={!isClient ? 'USD' : undefined} // Use USD on server, auto-detect on client
/>
)
This library uses HTTPS-only APIs (ipapi.co, exchangerate-api.com) to ensure compatibility with secure deployments. Mixed content (HTTP requests from HTTPS sites) is automatically blocked by modern browsers.
While the library has minimal dependencies, it does include:
@tanstack/react-query (peer dependency for state management)@tanstack/query-sync-storage-persister (for localStorage caching)@tanstack/react-query-persist-client (for persistence integration)Total bundle impact: ~20kB minified, ~6.5kB gzipped.
The package supports 161 commonly circulating world currencies via ExchangeRate-API, covering 99% of all UN recognized states and territories.
All ISO 4217 three-letter currency codes are supported, including:
| Code | Currency Name | Country/Region |
|---|---|---|
| AED | UAE Dirham | United Arab Emirates |
| AFN | Afghan Afghani | Afghanistan |
| ALL | Albanian Lek | Albania |
| AMD | Armenian Dram | Armenia |
| ANG | Netherlands Antillian Guilder | Netherlands Antilles |
| AOA | Angolan Kwanza | Angola |
| ARS | Argentine Peso | Argentina |
| AUD | Australian Dollar | Australia |
| AWG | Aruban Florin | Aruba |
| AZN | Azerbaijani Manat | Azerbaijan |
| BAM | Bosnia and Herzegovina Mark | Bosnia and Herzegovina |
| BBD | Barbados Dollar | Barbados |
| BDT | Bangladeshi Taka | Bangladesh |
| BGN | Bulgarian Lev | Bulgaria |
| BHD | Bahraini Dinar | Bahrain |
| BIF | Burundian Franc | Burundi |
| BMD | Bermudian Dollar | Bermuda |
| BND | Brunei Dollar | Brunei |
| BOB | Bolivian Boliviano | Bolivia |
| BRL | Brazilian Real | Brazil |
| BSD | Bahamian Dollar | Bahamas |
| BTN | Bhutanese Ngultrum | Bhutan |
| BWP | Botswana Pula | Botswana |
| BYN | Belarusian Ruble | Belarus |
| BZD | Belize Dollar | Belize |
| CAD | Canadian Dollar | Canada |
| CDF | Congolese Franc | Democratic Republic of the Congo |
| CHF | Swiss Franc | Switzerland |
| CLP | Chilean Peso | Chile |
| CNY | Chinese Renminbi | China |
| COP | Colombian Peso | Colombia |
| CRC | Costa Rican Colon | Costa Rica |
| CUP | Cuban Peso | Cuba |
| CVE | Cape Verdean Escudo | Cape Verde |
| CZK | Czech Koruna | Czech Republic |
| DJF | Djiboutian Franc | Djibouti |
| DKK | Danish Krone | Denmark |
| DOP | Dominican Peso | Dominican Republic |
| DZD | Algerian Dinar | Algeria |
| EGP | Egyptian Pound | Egypt |
| ERN | Eritrean Nakfa | Eritrea |
| ETB | Ethiopian Birr | Ethiopia |
| EUR | Euro | European Union |
| FJD | Fiji Dollar | Fiji |
| FKP | Falkland Islands Pound | Falkland Islands |
| FOK | Faroese Króna | Faroe Islands |
| GBP | Pound Sterling | United Kingdom |
| GEL | Georgian Lari | Georgia |
| GGP | Guernsey Pound | Guernsey |
| GHS | Ghanaian Cedi | Ghana |
| GIP | Gibraltar Pound | Gibraltar |
| GMD | Gambian Dalasi | The Gambia |
| GNF | Guinean Franc | Guinea |
| GTQ | Guatemalan Quetzal | Guatemala |
| GYD | Guyanese Dollar | Guyana |
| HKD | Hong Kong Dollar | Hong Kong |
| HNL | Honduran Lempira | Honduras |
| HRK | Croatian Kuna | Croatia |
| HTG | Haitian Gourde | Haiti |
| HUF | Hungarian Forint | Hungary |
| IDR | Indonesian Rupiah | Indonesia |
| ILS | Israeli New Shekel | Israel |
| IMP | Manx Pound | Isle of Man |
| INR | Indian Rupee | India |
| IQD | Iraqi Dinar | Iraq |
| IRR | Iranian Rial | Iran |
| ISK | Icelandic Króna | Iceland |
| JEP | Jersey Pound | Jersey |
| JMD | Jamaican Dollar | Jamaica |
| JOD | Jordanian Dinar | Jordan |
| JPY | Japanese Yen | Japan |
| KES | Kenyan Shilling | Kenya |
| KGS | Kyrgyzstani Som | Kyrgyzstan |
| KHR | Cambodian Riel | Cambodia |
| KID | Kiribati Dollar | Kiribati |
| KMF | Comorian Franc | Comoros |
| KRW | South Korean Won | South Korea |
| KWD | Kuwaiti Dinar | Kuwait |
| KYD | Cayman Islands Dollar | Cayman Islands |
| KZT | Kazakhstani Tenge | Kazakhstan |
| LAK | Lao Kip | Laos |
| LBP | Lebanese Pound | Lebanon |
| LKR | Sri Lanka Rupee | Sri Lanka |
| LRD | Liberian Dollar | Liberia |
| LSL | Lesotho Loti | Lesotho |
| LYD | Libyan Dinar | Libya |
| MAD | Moroccan Dirham | Morocco |
| MDL | Moldovan Leu | Moldova |
| MGA | Malagasy Ariary | Madagascar |
| MKD | Macedonian Denar | North Macedonia |
| MMK | Burmese Kyat | Myanmar |
| MNT | Mongolian Tögrög | Mongolia |
| MOP | Macanese Pataca | Macau |
| MRU | Mauritanian Ouguiya | Mauritania |
| MUR | Mauritian Rupee | Mauritius |
| MVR | Maldivian Rufiyaa | Maldives |
| MWK | Malawian Kwacha | Malawi |
| MXN | Mexican Peso | Mexico |
| MYR | Malaysian Ringgit | Malaysia |
| MZN | Mozambican Metical | Mozambique |
| NAD | Namibian Dollar | Namibia |
| NGN | Nigerian Naira | Nigeria |
| NIO | Nicaraguan Córdoba | Nicaragua |
| NOK | Norwegian Krone | Norway |
| NPR | Nepalese Rupee | Nepal |
| NZD | New Zealand Dollar | New Zealand |
| OMR | Omani Rial | Oman |
| PAB | Panamanian Balboa | Panama |
| PEN | Peruvian Sol | Peru |
| PGK | Papua New Guinean Kina | Papua New Guinea |
| PHP | Philippine Peso | Philippines |
| PKR | Pakistani Rupee | Pakistan |
| PLN | Polish Złoty | Poland |
| PYG | Paraguayan Guaraní | Paraguay |
| QAR | Qatari Riyal | Qatar |
| RON | Romanian Leu | Romania |
| RSD | Serbian Dinar | Serbia |
| RUB | Russian Ruble | Russia |
| RWF | Rwandan Franc | Rwanda |
| SAR | Saudi Riyal | Saudi Arabia |
| SBD | Solomon Islands Dollar | Solomon Islands |
| SCR | Seychellois Rupee | Seychelles |
| SDG | Sudanese Pound | Sudan |
| SEK | Swedish Krona | Sweden |
| SGD | Singapore Dollar | Singapore |
| SHP | Saint Helena Pound | Saint Helena |
| SLE | Sierra Leonean Leone | Sierra Leone |
| SOS | Somali Shilling | Somalia |
| SRD | Surinamese Dollar | Suriname |
| SSP | South Sudanese Pound | South Sudan |
| STN | São Tomé and Príncipe Dobra | São Tomé and Príncipe |
| SYP | Syrian Pound | Syria |
| SZL | Eswatini Lilangeni | Eswatini |
| THB | Thai Baht | Thailand |
| TJS | Tajikistani Somoni | Tajikistan |
| TMT | Turkmenistan Manat | Turkmenistan |
| TND | Tunisian Dinar | Tunisia |
| TOP | Tongan Paʻanga | Tonga |
| TRY | Turkish Lira | Turkey |
| TTD | Trinidad and Tobago Dollar | Trinidad and Tobago |
| TVD | Tuvaluan Dollar | Tuvalu |
| TWD | New Taiwan Dollar | Taiwan |
| TZS | Tanzanian Shilling | Tanzania |
| UAH | Ukrainian Hryvnia | Ukraine |
| UGX | Ugandan Shilling | Uganda |
| USD | United States Dollar | United States |
| UYU | Uruguayan Peso | Uruguay |
| UZS | Uzbekistani So'm | Uzbekistan |
| VES | Venezuelan Bolívar Soberano | Venezuela |
| VND | Vietnamese Đồng | Vietnam |
| VUV | Vanuatu Vatu | Vanuatu |
| WST | Samoan Tālā | Samoa |
| XAF | Central African CFA Franc | CEMAC |
| XCD | East Caribbean Dollar | Organisation of Eastern Caribbean States |
| XDR | Special Drawing Rights | International Monetary Fund |
| XOF | West African CFA franc | CFA |
| XPF | CFP Franc | Collectivités d'Outre-Mer |
| YER | Yemeni Rial | Yemen |
| ZAR | South African Rand | South Africa |
| ZMW | Zambian Kwacha | Zambia |
| ZWL | Zimbabwean Dollar | Zimbabwe |
| Code | Currency Name | Country | Reason |
|---|---|---|---|
| KPW | North Korean Won | North Korea | Due to sanctions & lack of international trade |
Note: For KPW data, the only reliable source is Daily NK, which reports actual jangmadang market rates via human sources inside DPRK.
The following currencies experience heightened volatility and substantial differences between official and actual exchange rates. Extra caution is recommended:
| Code | Currency Name | Country | Notes |
|---|---|---|---|
| ARS | Argentine Peso | Argentina | Multiple exchange rates in market |
| LYD | Libyan Dinar | Libya | Political instability affects rates |
| SSP | South Sudanese Pound | South Sudan | High volatility |
| SYP | Syrian Pound | Syria | Ongoing conflict impacts rates |
| VES | Venezuelan Bolívar Soberano | Venezuela | Hyperinflation environment |
| YER | Yemeni Rial | Yemen | Regional instability |
| ZWL | Zimbabwean Dollar | Zimbabwe | Historical hyperinflation legacy |
Important: For volatile currencies, rates default to central bank published rates, which may differ significantly from actual market rates.
// ❌ This will show a helpful error message
useCurrencyConverter({
basePrice: 99.99,
baseCurrency: 'USD',
apiKey: '' // Empty key
})
// ✅ Provide your API key
useCurrencyConverter({
basePrice: 99.99,
baseCurrency: 'USD',
apiKey: process.env.REACT_APP_EXCHANGE_API_KEY
})
// ✅ All of these work the same way (case-insensitive)
useCurrencyConverter({ baseCurrency: 'USD', manualCurrency: 'EUR' })
useCurrencyConverter({ baseCurrency: 'usd', manualCurrency: 'eur' })
useCurrencyConverter({ baseCurrency: 'Usd', manualCurrency: 'Eur' })
// If you get: "Currency 'KPW' was detected from your location but is not supported"
// Solution: Use manual currency override (KPW is the only unsupported currency)
useCurrencyConverter({
basePrice: 99.99,
baseCurrency: 'USD',
apiKey: 'your-key',
manualCurrency: 'USD' // Override KPW with a supported currency
})
// For volatile currencies (ARS, VES, etc.), rates may differ from market reality
useCurrencyConverter({
basePrice: 99.99,
baseCurrency: 'USD',
apiKey: 'your-key',
manualCurrency: 'ARS', // Works, but be aware of potential rate discrepancies
onSuccess: (result) => {
console.log('Note: ARS rates may differ from actual market rates')
}
})
// The package automatically handles rate limits, but you can also:
useCurrencyConverter({
basePrice: 99.99,
baseCurrency: 'USD',
apiKey: 'your-key',
onError: (error) => {
if (error.message.includes('429')) {
// Handle rate limiting gracefully
console.log('Rate limited, showing original price')
}
}
})
Run the standard test suite with mocked APIs:
npm test
Run with coverage:
npm run test:coverage
To test with real API calls, first set up your environment:
# Create .env file with your real API key
echo "VITE_EXCHANGE_API_KEY=your_actual_api_key_here" > .env
echo "VITE_RUN_INTEGRATION_TESTS=true" >> .env
Then run integration tests:
# Run once with real APIs
npm run test:integration
# Watch mode with real APIs
npm run test:integration:watch
⚠️ Note: Integration tests make real API calls and will:
The package includes comprehensive tests covering:
We welcome contributions! Please see our Contributing Guide for details.
# Clone the repository
git clone https://github.com/iamjr15/react-currency-localizer.git
# Install dependencies
npm install
# Run tests
npm test
# Build the package
npm run build
# Run linting
npm run lint
MIT © Jigyansu Rout
This implementation is built on carefully considered architectural choices:
✅ Two-API Architecture - Specialized services for maximum accuracy
✅ TanStack Query Integration - Enterprise-grade state management
✅ Intelligent Caching Strategy - Optimized for each data type
✅ Hook-Based API - Modern React patterns
✅ LocalizedPrice Component - Declarative wrapper component
✅ TypeScript Support - Full type safety and IntelliSense
✅ Free APIs Only - Zero cost barrier to entry
✅ ipapi.co Selection - HTTPS-compatible geolocation service
✅ ExchangeRate-API.com Selection - Reliable currency data provider
Made with ❤️ for the React community
FAQs
A React hook to display prices in a user's local currency using HTTPS-compatible IP geolocation with robust validation and error handling
We found that @iamjr15/react-currency-localizer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Miasma Mini Shai-Hulud hits @immobiliarelabs Backstage plugins, targeting GitLab and LDAP auth packages on npm.

Security News
Rolldown paused Rust React Compiler integration after a 5MB binary size increase raised concerns about shipping React-specific code to all Vite users.

Security News
/Research
Mini Shai-Hulud expands into the Go ecosystem after hitting LeoPlatform npm packages and targeting GitHub Actions workflows.