Bygga
제품명을 박스에 입력하면 Bygga가 3D로 모든 조립 단계와 부품·스크류·도구를 보여주고 음성으로 안내합니다
아직 감지된 업데이트가 없습니다. 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 전문 보기 ↗