feat: implement docs-site, legal docs, metrics standard, flux manifests

Closes leeworks-agents/api-company#5  (docs-site Astro scaffold)
Closes leeworks-agents/api-company#9  (metrics instrumentation standard)
Closes leeworks-agents/api-company#10 (Gitea Actions openapi aggregation pipeline)
Closes leeworks-agents/api-company#11 (docs-site Flux HelmRelease)
Closes leeworks-agents/api-company#12 (SEO blog posts x3)
Closes leeworks-agents/api-company#13 (legal docs ToS/Privacy/AUP)
Closes leeworks-agents/api-company#14 (DNS documentation)

## Changes

### docs/legal/
- terms-of-service.md — API usage, liability, account termination, governing law
- privacy-policy.md — request log retention (90d), no PII sold, data sharing
- acceptable-use-policy.md — rate limit abuse, scraping prohibition, resale ban

### docs/metrics-standard.md
- Defines api_requests_total, api_response_duration_seconds, api_data_freshness_seconds
- Fastify (TypeScript) and FastAPI (Python) reference middleware implementations
- Prometheus scrape config and Grafana dashboard guidance

### docs/registry.md
- Decision: use Gitea built-in container registry (no new infra)
- Image naming convention, auth, Kubernetes imagePullSecrets, ingress config

### docs/dns.md
- Required A records for all 6 subdomains
- cert-manager ClusterIssuer and Ingress TLS examples
- Verification commands and human-operator action items

### docs-site/
- Astro 4 + MDX + sitemap scaffold
- Base layout with nav linking all APIs, blog, RapidAPI, status
- Landing page with API cards
- Per-API Redoc viewer pages (zip-enrichment, holidays, air-quality)
- Blog index + 3 SEO blog posts (~1000 words each with JSON-LD)
- Dockerfile (multi-stage: node build + nginx serve)
- nginx.conf with gzip, caching, health endpoint

### flux/
- gitea-runner/: gitea-act-runner HelmRelease (org-scope, dind)
- monitoring/: kube-prometheus-stack + Gatus HelmReleases
  - Prometheus with pod annotation scraping
  - Grafana at grafana.leeworks.dev with persistence
  - Gatus status page at status.leeworks.dev, 90-day retention
- docs-site/: Deployment + Service + Ingress via raw chart
- api-company-source/: GitRepository + Kustomization reference manifests
- kustomization.yaml: root kustomize entry point (build validated)

### .gitea/workflows/build-docs.yaml
- Aggregates openapi.yaml from zip-enrichment, holidays, air-quality repos
- Builds Astro docs-site
- Pushes image to registry.leeworks.dev/leeworks-agents/docs-site
- Triggered on push to main, schedule daily 02:00 UTC, workflow_dispatch
This commit is contained in:
agent-company
2026-05-24 23:20:33 +00:00
parent 40631fee7c
commit a615b7ebfd
41 changed files with 2201 additions and 3 deletions
@@ -0,0 +1,178 @@
---
title: "Air Quality API: Real-Time AQI Data for Any Location"
description: "Access real-time Air Quality Index (AQI) data, PM2.5, PM10, and health recommendations for any city worldwide using the leeworks.dev Air Quality API."
date: "2026-05-24"
author: "leeworks.dev"
tags: ["air-quality", "aqi", "api", "tutorial"]
---
import Base from '../../layouts/Base.astro';
<Base title="Air Quality API Guide" description="Access real-time AQI data for any location worldwide.">
<article style="max-width: 800px; margin: 0 auto; padding: 2rem; line-height: 1.75;">
<script type="application/ld+json" set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "Article",
"headline": "Air Quality API: Real-Time AQI Data for Any Location",
"datePublished": "2026-05-24",
"author": { "@type": "Organization", "name": "leeworks.dev" },
"publisher": { "@type": "Organization", "name": "leeworks.dev", "url": "https://docs.leeworks.dev" }
})} />
# Air Quality API: Real-Time AQI Data for Any Location
Whether you're building a fitness app, a travel planner, or a smart home dashboard, air quality data is increasingly essential. The leeworks.dev **Air Quality API** gives you real-time AQI readings, pollutant breakdowns, and health recommendations for any location in the world.
## What Is AQI and Why Does Your App Need It?
The **Air Quality Index (AQI)** is a standardized scale (0500) that communicates how clean or polluted the air is:
| AQI | Category | Health Implication |
|-----|----------|-------------------|
| 050 | Good | Air quality is satisfactory |
| 51100 | Moderate | Acceptable for most people |
| 101150 | Unhealthy for Sensitive Groups | At-risk groups may experience effects |
| 151200 | Unhealthy | Everyone may begin to experience health effects |
| 201300 | Very Unhealthy | Health alert: serious effects possible |
| 301500 | Hazardous | Emergency conditions |
**Use cases for an AQI data API:**
- **Fitness apps** — warn runners when outdoor exercise is unsafe
- **Travel apps** — show air quality forecasts for destination cities
- **Real estate platforms** — display neighborhood air quality scores
- **Smart home apps** — trigger air purifiers based on outdoor AQI
- **Health tracking apps** — correlate symptoms with air quality data
- **News and weather apps** — add AQI to daily weather cards
## Quick Start
```bash
# Get current AQI for a city
curl "https://aqi.leeworks.dev/v1/current?city=Los+Angeles&country=US" \
-H "X-RapidAPI-Key: YOUR_API_KEY"
```
Response:
```json
{
"location": {
"city": "Los Angeles",
"country": "US",
"latitude": 34.0522,
"longitude": -118.2437
},
"aqi": 87,
"category": "Moderate",
"pollutants": {
"pm25": 22.4,
"pm10": 35.1,
"o3": 41.2,
"no2": 18.5,
"so2": 2.1,
"co": 0.4
},
"health_recommendation": "Unusually sensitive people should consider reducing prolonged outdoor exertion.",
"updated_at": "2026-05-24T14:30:00Z"
}
```
## By Coordinates (Lat/Long)
```bash
curl "https://aqi.leeworks.dev/v1/current?lat=48.8566&lon=2.3522" \
-H "X-RapidAPI-Key: YOUR_API_KEY"
```
## Code Examples
### JavaScript
```javascript
async function getAirQuality(city, country = 'US') {
const response = await fetch(
`https://aqi.leeworks.dev/v1/current?city=${encodeURIComponent(city)}&country=${country}`,
{ headers: { 'X-RapidAPI-Key': process.env.RAPIDAPI_KEY } }
);
return response.json();
}
const data = await getAirQuality('Denver');
if (data.aqi > 100) {
console.warn(`Air quality in ${data.location.city} is ${data.category}. Consider staying indoors.`);
}
```
### Python
```python
import httpx
def get_aqi(lat: float, lon: float) -> dict:
resp = httpx.get(
"https://aqi.leeworks.dev/v1/current",
params={"lat": lat, "lon": lon},
headers={"X-RapidAPI-Key": "YOUR_KEY"},
)
resp.raise_for_status()
return resp.json()
# Example: check AQI before recommending outdoor run
aqi_data = get_aqi(37.7749, -122.4194) # San Francisco
if aqi_data["aqi"] <= 100:
print("Good to go for a run!")
else:
print(f"Air quality is {aqi_data['category']} — consider indoor exercise.")
```
### React Hook
```tsx
import { useState, useEffect } from 'react';
interface AQIData {
aqi: number;
category: string;
health_recommendation: string;
}
export function useAirQuality(city: string) {
const [data, setData] = useState<AQIData | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`/api/aqi?city=${encodeURIComponent(city)}`)
.then(r => r.json())
.then(setData)
.finally(() => setLoading(false));
}, [city]);
return { data, loading };
}
```
## Data Source
The leeworks.dev Air Quality API aggregates data from the **OpenAQ** public dataset — a non-profit platform that collects open air quality data from government agencies worldwide. Data is refreshed hourly.
## Pricing
| Plan | Requests/mo | Price |
|------|------------|-------|
| Free | 500 | $0 |
| Basic | 10,000 | $9/mo |
| Pro | 100,000 | $19/mo |
| Ultra | 1,000,000 | $49/mo |
**[Subscribe on RapidAPI →](https://rapidapi.com/leeworks/api/air-quality)**
## Conclusion
Air quality is no longer a niche data point — it's a critical health metric that millions of people check daily. The leeworks.dev **AQI data API** gives your app real-time air quality readings, pollutant breakdowns, and actionable health recommendations with a simple REST interface.
**[Start building for free →](https://rapidapi.com/leeworks/api/air-quality)**
</article>
</Base>