A Vue 3 + TypeScript web application that translates IP addresses into countries with real-time local clocks.
- Add multiple IP lookup rows
- Lookup on blur (search runs when you leave the input)
- Simultaneous lookups across rows
- Input disabled while searching
- Client-side validation (IPv4/IPv6)
- Real-time local clock (HH:MM:SS) per result that updates every second
- Country flag display
- Friendly error handling
- Response caching (successful results and permanent errors)
- Vue 3 + TypeScript + Vite
- Tailwind CSS
- ip-api.com (via Vercel API proxy)
yarn install
yarn devThe app runs at http://localhost:5173. The /api/geo endpoint is proxied to ip-api.com during development via Vite middleware.
yarn build# Unit tests
yarn test
# Watch mode
yarn test:watch
# Linting
yarn lintEvery push to any branch triggers:
- ✅ Linting (
yarn lint) - ✅ Unit tests (
yarn test) - ✅ Type checking + Build (
yarn build) - 🚀 Auto-deploy to Vercel (if tests pass)
Deployment targets:
- Push to
main→ Production deployment - Push to other branches → Preview deployment
Add these secrets to GitHub repo (Settings → Secrets and variables → Actions):
- VERCEL_TOKEN - Get from https://vercel.com/account/tokens
- VERCEL_ORG_ID - From Vercel team/account settings
- VERCEL_PROJECT_ID - From Vercel project settings
- Build:
yarn build - Output:
dist/directory - API Functions:
api/**/*.ts(serverless functions with rate limiting)
├── api/
│ ├── geo.ts # Vercel serverless function
│ └── geo.test.ts
├── lib/
│ ├── geo-lookup.ts # Shared geolocation logic
│ ├── geo-lookup.test.ts
│ ├── rate-limiter.ts # Rate limiting (10 req/min)
│ ├── rate-limiter.test.ts
│ ├── security.ts # Origin validation & IP extraction
│ └── security.test.ts
├── src/
│ ├── api/
│ │ ├── geoClient.ts # Frontend API client with caching
│ │ └── geoClient.test.ts
│ ├── components/
│ │ ├── IpLookupRow.vue
│ │ ├── IpLookupRow.spec.ts
│ │ └── ZonedClockDisplay.vue
│ ├── composables/
│ │ ├── useIpLookup.ts
│ │ ├── useIpLookup.test.ts
│ │ ├── useZonedClock.ts # Single shared timer for all clocks
│ │ └── useZonedClock.test.ts
│ ├── utils/
│ │ ├── ip.ts # IP validation utilities
│ │ └── ip.test.ts
│ ├── App.vue
│ ├── App.spec.ts
│ └── main.ts
├── vite/
│ └── dev-proxy.ts # Vite dev server API proxy
└── .github/workflows/
└── ci.yml # CI/CD pipeline