mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-07 11:54:59 -04:00
111 lines
4.4 KiB
Markdown
111 lines
4.4 KiB
Markdown
|
|
# Phase 19B Paddock Briefing RSS Backend Spike
|
||
|
|
|
||
|
|
## Goal
|
||
|
|
|
||
|
|
Prototype the backend foundation for a future fan-facing Paddock Briefing module
|
||
|
|
without scraping article pages or touching Race Hub UI. The spike keeps news as a
|
||
|
|
local-first cache: feeds can be fetched and normalized by backend code, stored in
|
||
|
|
SQLite, and read through a small API shape.
|
||
|
|
|
||
|
|
## Source Evaluation
|
||
|
|
|
||
|
|
Recommended first-party or publisher-owned feeds:
|
||
|
|
|
||
|
|
- FIA official RSS, `https://www.fia.com/rss/news`: keep as the official source
|
||
|
|
for federation announcements and regulatory context.
|
||
|
|
- BBC Sport F1, `https://feeds.bbci.co.uk/sport/formula1`: strong free headline
|
||
|
|
source for UK-centered coverage.
|
||
|
|
- Autosport F1, `https://www.autosport.com/rss/f1/news/`: useful motorsport
|
||
|
|
specialist feed; retain summaries only when provided by the feed.
|
||
|
|
- RaceFans F1, `https://www.racefans.net/category/f1-news/feed/`: useful
|
||
|
|
independent specialist feed with a clean WordPress RSS surface.
|
||
|
|
- Guardian Formula One,
|
||
|
|
`https://www.theguardian.com/sport/formulaone/rss`: broad editorial coverage
|
||
|
|
and stable RSS conventions.
|
||
|
|
|
||
|
|
Optional sources to evaluate before shipping:
|
||
|
|
|
||
|
|
- RACER F1, `https://racer.com/f1/feed`: reasonable supplemental specialist
|
||
|
|
feed.
|
||
|
|
- Formula 1 YouTube Atom,
|
||
|
|
`https://www.youtube.com/feeds/videos.xml?channel_id=UCB_qr75-ydFVKSF9Dmo6izg`:
|
||
|
|
video-only briefing cards, separate from article news.
|
||
|
|
- Motorsport.com F1, `https://www.motorsport.com/rss/f1/news/`: not included in
|
||
|
|
the default prototype list until terms and caching expectations are reviewed.
|
||
|
|
|
||
|
|
Avoid Formula1.com scraping or hidden endpoints, X/Twitter scraping, Reddit as a
|
||
|
|
primary news source, and feed aggregator products such as RSS.app or Feedspot.
|
||
|
|
|
||
|
|
## Legal And Product Caveats
|
||
|
|
|
||
|
|
Only fetch publisher-provided RSS/Atom XML. Do not fetch article bodies, bypass
|
||
|
|
paywalls, scrape Open Graph metadata, or store full article content. The product
|
||
|
|
surface should show source, title, canonical URL, publish time, category, and a
|
||
|
|
short feed-provided summary/snippet when available. Each card should link users
|
||
|
|
to the publisher site for the article.
|
||
|
|
|
||
|
|
Before enabling a source by default, review the publisher feed terms, robots/TOS
|
||
|
|
language around caching, and whether feed summaries are intended for display.
|
||
|
|
Keep TTLs conservative and make source attribution visible in the UI.
|
||
|
|
|
||
|
|
## Implemented Proof
|
||
|
|
|
||
|
|
This spike adds:
|
||
|
|
|
||
|
|
- `internal/news`: a standard-library RSS/Atom parser and polite fetch helper
|
||
|
|
with a 10-second default timeout and a box-box User-Agent.
|
||
|
|
- URL-based deduplication with UTM parameter stripping.
|
||
|
|
- `news_sources` and `news_items` tables in SQLite migration `003_news.sql`.
|
||
|
|
- Store/query methods for upserting cached feed metadata/items and listing
|
||
|
|
newest cached items.
|
||
|
|
- `GET /api/v1/news`, with optional `limit` and `source` query params.
|
||
|
|
- Unit tests using local XML fixtures only.
|
||
|
|
|
||
|
|
The endpoint is intentionally read-only against the local SQLite cache. It does
|
||
|
|
not fetch feeds during web requests, avoiding unexpected network work in the
|
||
|
|
product UI path. A later ingestion command can call `internal/news.Fetch`, upsert
|
||
|
|
sources/items, and mark `fetched_at`/`expires_at` according to a TTL policy.
|
||
|
|
|
||
|
|
## API Shape
|
||
|
|
|
||
|
|
`GET /api/v1/news?limit=25&source=racefans-f1`
|
||
|
|
|
||
|
|
Response:
|
||
|
|
|
||
|
|
```json
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"source": "racefans-f1",
|
||
|
|
"title": "Example headline",
|
||
|
|
"url": "https://publisher.example/story",
|
||
|
|
"published_at": "2026-05-25T14:00:00Z",
|
||
|
|
"summary": "Feed-provided snippet",
|
||
|
|
"category": "news",
|
||
|
|
"fetched_at": "2026-05-25T14:10:00Z"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
```
|
||
|
|
|
||
|
|
Default limit is 25; maximum accepted limit is 100.
|
||
|
|
|
||
|
|
## Follow-Up Frontend Plan
|
||
|
|
|
||
|
|
Add a Paddock Briefing surface outside Race Hub while Race Hub redesign work is
|
||
|
|
active. Recommended first UI slice:
|
||
|
|
|
||
|
|
- Query `/api/v1/news?limit=12`.
|
||
|
|
- Group by recency with source badges and external-link treatment.
|
||
|
|
- Show snippets only when present, with clear publisher attribution.
|
||
|
|
- Add source filters after the cache refresh command exists.
|
||
|
|
- Treat video feed items as a separate rail or filter, not mixed into hard-news
|
||
|
|
headlines by default.
|
||
|
|
|
||
|
|
## Open Questions
|
||
|
|
|
||
|
|
- Should news refresh live behind an explicit CLI command, opportunistic startup
|
||
|
|
refresh, or a manual button in an admin/data-health screen?
|
||
|
|
- What default TTL should each source use? A 15-30 minute TTL is reasonable for
|
||
|
|
race weekends; longer may be enough outside live sessions.
|
||
|
|
- Should the cache keep historical briefing items indefinitely, or prune after a
|
||
|
|
rolling window such as 30-90 days?
|