A full-stack weather dashboard built for the Weather-AI developer platform take-home. Skye consumes the Weather-AI REST API through a small Express proxy and presents forecasts, plan usage, and optional AI insights in a responsive React UI.
| Link | |
|---|---|
| Application | https://skye-alpha.vercel.app/ |
| API | https://skye-hufs.onrender.com/v1/docs/ |
| Repository | https://github.com/fu-ry17/skye |
- API integration — Authenticated calls to Weather-AI (
/weather,/weather-geo,/usage) with query validation and error handling on the server. - Product thinking — Forecast length respects plan
maxDaysfrom the usage endpoint; AI insights can be toggled; shareable URL state for locations and preferences. - Separation of concerns — Frontend talks only to your API; API keys stay on the backend.
- Operator experience — Health check, Swagger docs, Vitest coverage on weather routes, and setup docs for local and production runs.
flowchart LR
Browser[Skye UI\nReact + Vite]
API[Skye API\nExpress]
WA[Weather-AI API]
Browser -->|VITE_API_URL| API
API -->|Bearer WEATHER_API_KEY| WA
Browser -.->|City search only| Nominatim[OpenStreetMap\nNominatim]
| Layer | Role |
|---|---|
Frontend (frontend/) |
Dashboard, geocoding search, URL-synced state, themes |
Backend (backend/) |
Proxy, Zod validation, CORS, Swagger at /v1/docs |
| Weather-AI | Source of truth for weather, geo-IP, and usage data |
- Local weather via IP (
get_user_weather) - Search any city (geocoding via Nominatim, weather via coordinates)
- Forecast picker: 3 / 7 / 14 / 21 days, capped by plan limits from
/usage - Plan & usage panel — quotas,
maxDays, AI toggle - Shareable links via
nuqsURL state:?lat=&lon=&place=&days=&ai= - Dark, light, and system themes
- Node.js 18+ (frontend also runs on Bun 1.1+)
- pnpm 10+ (backend)
- Weather-AI API key — see developer docs
Run the API first, then the UI.
cd backend
pnpm install
cp .env.example .envEdit .env:
PORT=3001
WEATHER_API_KEY=your_weather_ai_api_key
BASE_URL=https://api.weather-ai.co/v1pnpm gen
pnpm devAPI: http://localhost:3001 · Docs: http://localhost:3001/v1/docs
cd frontend
bun install # or: npm install
cp .env.example .env
bun run dev # or: npm run devDefault VITE_API_URL is http://localhost:3001 (no trailing slash).
weather_ai/
├── README.md # This file
├── frontend/ # Skye UI — see frontend/README.md
└── backend/ # Skye API — see backend/README.md
| Method | Path | Weather-AI upstream |
|---|---|---|
GET |
/v1/health |
— |
GET |
/v1/weather/get_weather |
/weather |
GET |
/v1/weather/get_user_weather |
/weather-geo |
GET |
/v1/weather/get_usage |
/usage |
GET |
/v1/docs |
Swagger UI |
Detailed parameters and env vars: backend/README.md.
Deploy backend and frontend separately. The frontend must be built with the production API base URL.
Backend (Render, Railway, Fly.io, etc.)
- Set
PORT,WEATHER_API_KEY,BASE_URL pnpm install && pnpm build- Start:
node dist/index.js
Frontend (Netlify, Vercel, Cloudflare Pages, etc.)
- Set
VITE_API_URLto your deployed API origin (build-time variable) bun run build(ornpm run build)- Publish the
frontend/distdirectory
Update the Live demo table at the top of this README before you email your submission.
| Package | Docs | Dev command |
|---|---|---|
| Frontend | frontend/README.md | bun run dev |
| Backend | backend/README.md | pnpm dev |
Backend tests: cd backend && pnpm test
| Frontend | Backend |
|---|---|
| React 19, TypeScript, Vite | Express 5, TypeScript |
| TanStack Query, nuqs, Axios | Axios, Zod, Swagger UI |
| Tailwind CSS 4, Framer Motion | Vitest, supertest |
- API key security —
WEATHER_API_KEYis server-only; the browser never sees it. - Geocoding — City search uses Nominatim (OSM); all weather and usage data comes from Weather-AI.
- Assignment scope — Intentionally small BFF layer so integration patterns (auth header, params, errors, usage limits) are easy to review.
Private submission for Weather-AI. All rights reserved unless otherwise agreed.