Skip to content

Repository files navigation

Currency Converter

wakatime

A lightweight, single-page currency converter built with Vue 3 and the Composition API. Converts between world currencies using real-time exchange rates from CurrencyBeacon.

Tech Stack

  • Vue 3 (Composition API + <script setup>)
  • TypeScript 6
  • Vite 8 (dev server, build, API proxy)
  • ofetch for HTTP requests
  • VueUse for utility composables
  • pnpm as package manager
  • Volta for pinned Node & pnpm versions

Architecture Decisions

No Pinia (no global state)

The app intentionally avoids Pinia or any global store. All state lives inside composables (useCurrencies, useCurrencieConvert) and is passed down through props. This keeps data flow explicit, components self-contained, and eliminates the overhead of a state management layer for what is fundamentally a single-view tool.

No Vue Router

There is only one view, so Vue Router would add complexity with no benefit. The entire app renders through App.vue -> CurrencyConverter without any routing layer.

A potential future enhancement is deep-linking via query parameters (e.g. ?from=USD&to=EUR&amount=100) to allow sharing or bookmarking specific conversions. This can be implemented with vanilla URLSearchParams without needing a router - see IDEAS.md for details.

API Proxy

CurrencyBeacon API calls are proxied through Vite's dev server (/api -> api.currencybeacon.com) and through Vercel rewrites in production. This avoids CORS issues and keeps the API key out of client-side requests.

Component Structure

Components are organized by domain rather than by type:

src/
  components/
    Ui/              # Reusable primitives (UiInput, UiOverlay, UiPopup)
    base/             # App-level layout (Overlay, Popup)
    converter/        # Domain components (AmountInput, CurrencyConverter, ...)
  composables/        # Stateful logic (useCurrencies, useCurrencieConvert, ...)
  services/           # API layer (CurrencyBeacon client + mappers)
  types/              # Shared TypeScript types

Service Layer with Mappers

The CurrencyBeacon API integration is isolated behind a service layer with dedicated mapper functions and types. This decouples the app's internal data model from the external API shape, making it straightforward to swap providers or adapt to API changes without touching component logic.

Getting Started

# Install dependencies
pnpm install

# Start dev server
pnpm dev

# Type-check & build for production
pnpm build

# Skip Type-check & build for production
pnpm build-only

# Preview production build
pnpm preview

Environment Variables

Copy .env.example to .env and fill in your CurrencyBeacon API key.

Linting & Formatting

pnpm format

Lighthouse Scores

Mobile:

Lighthouse mobile score

Desktop:

Lighthouse desktop score

Releases

Packages

Contributors

Languages