7e60343ed50cc13e2bd5e8c8c35b378bb38102a6
- Middleware sets CSP (default-src 'none'; style-src 'self'), HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy on every response - Inline <style> moved to /styles.css so CSP needs no unsafe-inline - /favicon.ico returns a 1x1 GIF (kills 404 noise) - Escape LLM jokes, article title, and URL before HTML rendering (XSS fix)
Wiki Jokes
5 jokes every day, generated by an LLM from Wikipedia's Today's Featured Article.
How it works
- A scheduled job (06:00 Europe/Copenhagen, plus immediately on cold start) fetches the day's featured article from the Wikipedia REST feed and asks any OpenAI-compatible endpoint for exactly 5 jokes as JSON.
- Jokes are stored in SQLite (
/data/jokes.db) and served instantly — no LLM call at request time. - On failure: retries every 15 min, up to 3 attempts per day. If still failing, the page keeps showing the latest batch with a "stale" note.
Run
cp .env.example .env # set OPENAI_BASE_URL / OPENAI_MODEL / OPENAI_API_KEY
docker compose up -d --build
# open http://localhost:8080
Configuration (env vars)
| Var | Default | Purpose |
|---|---|---|
OPENAI_BASE_URL |
https://api.openai.com/v1 |
OpenAI-compatible endpoint (e.g. llamaswap) |
OPENAI_MODEL |
gpt-4o-mini |
Model name |
OPENAI_API_KEY |
(empty) | Bearer token (optional for llamaswap) |
GENERATE_HOUR / GENERATE_MINUTE |
6 / 0 |
Daily generation time |
MAX_ATTEMPTS |
3 |
Retry budget per day |
RETRY_MINUTES |
15 |
Retry interval |
WIKIPEDIA_LANG |
en |
Wikipedia language for the feed |
DB_PATH |
/data/jokes.db |
SQLite location (volume-mounted) |
Endpoints
GET /— today's 5 jokes + link to the featured articleGET /health— JSON: whether today's jokes exist / retries exhausted
Description
5 daily jokes generated from Wikipedia featured article via OpenAI-compatible endpoint
75 KiB
Languages
Python
98.2%
Dockerfile
1.8%