Bygga
Type the product name from the box. Bygga shows every assembly step in 3D, with the parts, screws and tools for each one, and reads it out loud.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
CityScope — search any city for live weather, air quality, currency, and local time in one dashboard. Ballerina API (concurrent upstream calls, TTL caching, rate limiting) + a multi-view vanilla JS frontend.
翻译准备中
正在加载完整 README。
查看完整 README ↗A fast, beautiful city weather and information app. Search any city and see its current weather, hourly and 7-day forecast, air quality, local time, and currency — all in one dashboard, with no account or login required.
Originally built as a small Ballerina "integration" project for the WSO2 Engineering Intern application; rebuilt into a full product: the Ballerina backend now runs a versioned, cached, rate-limited API, and the frontend is a complete multi-view weather app instead of a single search box.
Live demo: https://cityscope-stephan.vercel.app (the first request after a quiet spell takes a few extra seconds while the backend wakes up)
Home dashboard — current weather, hourly/daily forecast, air quality, currency, and analytics for one city:
Compare view — current conditions for 2–4 cities side by side:
localStorage only| Asset | License / tier | Attribution |
|---|---|---|
| Leaflet 1.9.4 (map library, loaded from the unpkg CDN) | BSD-2-Clause | Not required on-page |
| Esri World Dark Gray Base map tiles | Free, keyless basemap tier | Required — rendered automatically by Leaflet's attribution control on the Map view ("Esri — Esri, HERE, Garmin, © OpenStreetMap contributors, and the GIS user community") |
| Open-Meteo (weather, air quality, geocoding) | Free tier | Called server-side only |
| open.er-api.com (currency) | Free tier | Called server-side only |
Icons are hand-authored inline SVG (no icon font/library). No webfonts are loaded — the UI uses the system font stack only. No raster images are used in the frontend. Full detail on what each third party can see, and what CityScope's own hosting logs, is in the Privacy Policy.
flowchart TD
UI["CityScope Frontend<br/>vanilla JS, multi-view"] --> API["Ballerina API<br/>/api/v1 · cache + rate limit"]
API --> GEO["Geocoding<br/>(Open-Meteo)"]
API --> WX["Weather<br/>(Open-Meteo)"]
API --> AQ["Air Quality<br/>(Open-Meteo)"]
API --> FX["Currency<br/>(open.er-api.com)"]
classDef stage fill:#6C5CE7,stroke:#4834B0,color:#fff
class API stage
GET /api/v1/snapshot/{city} geocodes the city once, then fires the weather,
air quality, and currency requests concurrently with Ballerina's
start/wait — none of the three depends on another's result, so they run
in parallel instead of one after another. Weather is essential (its failure
fails the request); air quality and currency are each optional — if one
upstream is down, the snapshot still returns with that field set to null
rather than failing outright.
A small hand-rolled in-memory TTL cache sits in front of every upstream call, keyed by coordinates (weather/air quality) or city name (geocoding) or currency code (FX rates) — never by this service's own derived response shape, so a cache hit still recomputes weather descriptions/AQI categories fresh while skipping the network round-trip.
| Data | TTL | Why |
|---|---|---|
| Geocoding | 24h | A city's coordinates don't move |
| Weather | 5 min | Balances freshness against upstream load |
| Air quality | 10 min | Changes more slowly than weather |
| Currency | 30 min | Exchange rates update a few times a day at most |
A single global fixed-window limiter (60 requests/minute by default,
configurable — see backend/Config.toml.example) protects the free-tier
upstream APIs, which this whole service shares one quota with regardless of
which caller triggered the request. It's deliberately global rather than
per-client: per-IP limiting would need every resource function to switch to
the manual http:Caller-response pattern instead of typed returns, a much
larger change for a demo-scale service.
以上为 README 的开头部分。其余内容请阅读原文。 查看完整 README ↗