Created
May 24, 2022 02:20
-
-
Save jaylandro/917c76e1c301ed3494f7dfe0d6e9ed73 to your computer and use it in GitHub Desktop.
Geolocation based weather rendered on-demand at the edge with Cloudflare workers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
addEventListener('fetch', event => { | |
event.respondWith(handleRequest(event.request)); | |
}); | |
async function handleRequest(request) { | |
// https://api.weather.gov/points/38.8894,-77.0352 | |
const { latitude, longitude } = request.cf; | |
const headers = { | |
'content-type': 'application/json', | |
'User-Agent': ('landro.dev', '[email protected]') | |
} | |
const weatherLocationResponse = await fetch( | |
`https://api.weather.gov/points/${latitude},${longitude}`, { headers: headers } | |
); | |
console.log(weatherLocationResponse) | |
const weatherLocationData = await weatherLocationResponse.json(); | |
const forecastResponse = await fetch( | |
weatherLocationData.properties.forecast, { headers: headers } | |
); | |
const forecastData = await forecastResponse.json(); | |
const forecast = forecastData.properties.periods; | |
function iconHelper(shortForecastString) { | |
if (shortForecastString.includes("Snow")) | |
return '🌨'; | |
if (shortForecastString.includes("thunderstorms")) | |
return '⛈'; | |
if (shortForecastString.includes("Partly Cloudy")) | |
return '🌤'; | |
if (shortForecastString.includes("Cloud")) | |
return '☁️'; | |
if (shortForecastString.includes("Light Rain")) | |
return '🌦'; | |
if (shortForecastString.includes("Rain")) | |
return '🌧'; | |
return '☀️'; | |
} | |
let html = ` | |
<html> | |
<head> | |
<title>Geolocation: Weather</title> | |
</head> | |
<body> | |
<style> | |
body { | |
padding: 6em; | |
font-family: sans-serif; | |
} | |
h1 { | |
color: #f6821f; | |
} | |
.header { | |
grid-area: header; | |
margin-bottom: 0; | |
} | |
.icon { | |
grid-area: icon; | |
font-size: 3em; | |
font-style: normal; | |
} | |
.detailforecast { | |
grid-area: detailforecast; | |
line-height: 1.4; | |
max-width: 500px; | |
} | |
.day { | |
display: grid; | |
grid-gap: 10px; | |
grid-template-columns: 3.2em 3fr; | |
grid-template-areas: | |
"header header" | |
"icon detailforecast"; | |
margin-bottom: 1.2em; | |
} | |
</style> | |
<div id="container"> | |
<h1>Weather in ${weatherLocationData.properties.relativeLocation.properties.city}, ${weatherLocationData.properties.relativeLocation.properties.state}</h1> | |
<main> | |
<section> | |
${forecast.map(day => ` | |
<div class="day"> | |
<h3 class="header">${day.name}</h3> | |
<i class="icon">${iconHelper(day.shortForecast)}</i> | |
<span class="detailforecast">${day.detailedForecast}</span> | |
</div> | |
`).join(' ')} | |
</section> | |
</div> | |
</body>`; | |
return new Response(html, { | |
headers: { | |
'content-type': 'text/html; charset=UTF-8;', | |
}, | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment