Add weather to header, collapsible sections, staggered card animation
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-05-16 16:13:10 +02:00
parent 6389e323dd
commit 7bbefaa1f6
6 changed files with 212 additions and 7 deletions
+2
View File
@@ -16,6 +16,7 @@ import qbt from './routes/qbittorrent'
import jellyfin from './routes/jellyfin'
import navidrome from './routes/navidrome'
import romm from './routes/romm'
import weather from './routes/weather'
const app = express()
const PORT = Number(process.env.PORT ?? 3001)
@@ -37,6 +38,7 @@ app.use('/api/qbt', qbt)
app.use('/api/jellyfin', jellyfin)
app.use('/api/navidrome', navidrome)
app.use('/api/romm', romm)
app.use('/api/weather', weather)
// Serve built frontend in production only
if (process.env.NODE_ENV === 'production') {
+37
View File
@@ -0,0 +1,37 @@
import { Router } from 'express'
import axios from 'axios'
const router = Router()
router.get('/current', async (_req, res) => {
try {
const location = process.env.WEATHER_LOCATION
if (!location) {
res.status(503).json({ error: 'WEATHER_LOCATION not configured' })
return
}
const response = await axios.get(
`https://wttr.in/${encodeURIComponent(location)}?format=j1`,
{ headers: { 'Accept': 'application/json' }, timeout: 8000 }
)
const c = response.data.current_condition[0]
const area = response.data.nearest_area?.[0]
res.json({
tempC: Number(c.temp_C),
feelsLikeC: Number(c.FeelsLikeC),
humidity: Number(c.humidity),
windKmph: Number(c.windspeedKmph),
desc: c.weatherDesc[0].value as string,
code: Number(c.weatherCode),
city: area?.areaName?.[0]?.value ?? location,
})
} catch (err: unknown) {
const msg = err instanceof Error ? err.message : 'Unknown error'
res.status(500).json({ error: msg })
}
})
export default router