feat(changelogs): port Bluefin Firehose to /changelogs page#702
Conversation
Replace the PackageSummary + CombinedFeedItems layout with a full port of the Bluefin Firehose site (castrojo.github.io/bluefin-releases). Layout: sticky sidebar (RSS links, featured app, filters, statistics) + main column of grouped release cards, sorted newest-first. Data pipeline: - scripts/fetch-firehose.js fetches apps.json from the public Firehose GitHub Pages URL every 6 hours (matches pipeline schedule). - static/data/firehose-apps.json committed as empty seed so builds succeed before the first fetch. - fetch-firehose appended to fetch-data chain. - .gitignore negation added alongside sbom-attestations.json. New components: - FirehoseCard: app icon, version, date, package badge, source/Flathub icon links, brew install copy button, release HTML, older releases toggle. - FirehoseFilters: verification, package type, category, app set, date range filters with result count and clear-all. - FirehoseFeed: orchestrates sidebar + feed, featured app banner, statistics panel, empty/no-match states. Types: - src/types/firehose.ts: full type definitions from Go models. - src/types/firehose-apps.d.ts: ambient module declaration for static import. Dependencies: - react-icons ^5.6.0 (SiFlathub, FaGithub, FaGitlab, FaCopy, FaCheck). Assisted-by: Claude Sonnet 4.6 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Code Review
This pull request introduces the "Bluefin Firehose" feature, which includes a new script to fetch application release data and a set of React components (FirehoseFeed, FirehoseCard, FirehoseFilters) to display and filter this data on the community feeds page. The implementation adds react-icons as a dependency and includes logic for caching and graceful degradation when fetching external data. Feedback highlights a potential XSS vulnerability when rendering HTML descriptions, as well as hydration issues in the SSG environment caused by non-deterministic date formatting and featured app selection.
| <div | ||
| className={styles.releaseBody} | ||
| dangerouslySetInnerHTML={{ __html: latestRelease.description }} | ||
| /> |
There was a problem hiding this comment.
Using dangerouslySetInnerHTML with data from an external source poses a significant XSS risk. The description field (and similarly on line 182) should be sanitized before being rendered. Even if the current source is trusted, this pattern is vulnerable if the upstream data (e.g., scraped GitHub release notes) contains malicious scripts. Consider using a library like dompurify to sanitize the HTML.
| function formatDate(iso: string): string { | ||
| try { | ||
| return new Date(iso).toLocaleDateString(undefined, { | ||
| year: "numeric", | ||
| month: "short", | ||
| day: "numeric", | ||
| }); | ||
| } catch { | ||
| return iso; | ||
| } | ||
| } |
There was a problem hiding this comment.
Using toLocaleDateString(undefined) causes hydration mismatches in SSG/SSR environments like Docusaurus because the server's locale during build may differ from the user's browser locale. This leads to React warnings and potential UI flickering. Use a fixed locale (e.g., 'en-US') to ensure consistency.
| function formatDate(iso: string): string { | |
| try { | |
| return new Date(iso).toLocaleDateString(undefined, { | |
| year: "numeric", | |
| month: "short", | |
| day: "numeric", | |
| }); | |
| } catch { | |
| return iso; | |
| } | |
| } | |
| function formatDate(iso: string): string { | |
| try { | |
| return new Date(iso).toLocaleDateString("en-US", { | |
| year: "numeric", | |
| month: "short", | |
| day: "numeric", | |
| }); | |
| } catch { | |
| return iso; | |
| } | |
| } |
| if (eligible.length === 0) return null; | ||
|
|
||
| // Deterministic hash from today's date string | ||
| const dateKey = new Date().toISOString().slice(0, 10); // "YYYY-MM-DD" |
There was a problem hiding this comment.
Using new Date() for the dateKey will cause hydration mismatches if the date changes between the build time and the user's visit, or if timezones differ. This triggers React warnings. To fix this, use a stable value like firehoseData.metadata.generatedAt as the seed for the deterministic selection, ensuring the featured app remains consistent between server and client for a given build.
Replace the PackageSummary + CombinedFeedItems layout with a full port of the Bluefin Firehose site (castrojo.github.io/bluefin-releases).
Layout: sticky sidebar (RSS links, featured app, filters, statistics)
Data pipeline:
New components:
Types:
Dependencies:
Assisted-by: Claude Sonnet 4.6 via GitHub Copilot