Skip to content

feat(developer-hub): unified cross-product changelog at /changelog - #3910

Open
aditya520 wants to merge 4 commits into
mainfrom
feat/changelog-hub
Open

feat(developer-hub): unified cross-product changelog at /changelog#3910
aditya520 wants to merge 4 commits into
mainfrom
feat/changelog-hub

Conversation

@aditya520

@aditya520 aditya520 commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

Turns the market-data-only changelog into a unified, cross-product Changelog at /changelog, covering Pyth Pro, Pyth Core, and Entropy. Inspired by the Massive and Twilio changelogs.

The page has two tabs:

  • Product Updates — hand-authored entries (one MDX file per entry under content/changelog/), filterable and shareable.
  • Market Data — the existing automated feed-change stream, unchanged.

Features

  • Filter by Product / Area / Type, multi-select, with live faceted counts (each chip shows how many entries it would match given the other selections). Filter state is URL-synced.
  • Share a single entry — every card has a copy-link button that yields a clean #slug deep link; opening one scrolls to, reveals (past pagination), and highlights the entry, dropping any filters that would hide it.
  • Subscribe (RSS)/changelog/feed.xml plus per-product feeds (?product=…), surfaced via a Subscribe menu and advertised through <link rel="alternate"> auto-discovery on the page.

Authoring model

Entries are validated at build time by the changelog collection schema in source.config.ts:
product (one of pyth-pro/pyth-core/entropy), type (one of feature/fix/breaking-change/deprecation/docs), optional area, plus title and date. The filename (<YYYY-MM-DD>-<slug>.mdx) is the entry's stable share anchor.

Wiring

  • Page moved from /price-feeds/changelog to top-level /changelog (permanent redirect; removed from Price Feeds nav; ChangelogBar now links to /changelog?tab=market-data; BasePage PageActions hidden for the new path).

Design & accessibility

  • Full WAI-ARIA tabs pattern (roving tabindex, Arrow/Home/End, role="tabpanel" + aria-controls).
  • Labelled filter groups, focus-visible rings matching the design system, role="group" Subscribe popover with focus restoration on Escape.
  • Design-system tokens throughout; verified in light, dark, and mobile.

Testing

  • tsc, biome, and stylelint clean; production build passes.
  • Runtime: /changelog 200, /price-feeds/changelog → 308, feed.xml 200 (well-formed XML; per-product item counts correct; unknown ?product= → 400).
  • Exercised in-browser: filtering + URL sync, tab keyboard nav, subscribe menu, and the deep-link reveal (including a filtered-out entry beyond page 1, validated with a temporary PAGE_SIZE=2).

Review pass (follow-up — commit 162466037)

A standards/correctness review of the branch produced these fixes:

  • SSR / first paint: the feed was client-only rendered — useSearchParams() behind a fallback-less <Suspense> bailed the whole feed out of the static prerender. Removed the hook from HubTabs/ProductUpdates; they now default to the updates tab with no filters (so the full feed renders into the static HTML) and reconcile URL state after mount. Dropped the now-unnecessary Suspense boundary. The no-JS HTML now contains every entry.
  • Date bug: relativeDate was off by one for any render at/after 12:00 UTC (it folded the current time-of-day into a Math.round); it now diffs whole UTC calendar days.
  • RSS: a bare ?product= returned 400 — it now serves the all-products feed (genuinely unknown non-empty values still 400). This refines the "unknown ?product= → 400" note above for the empty case.
  • Deep-link scroll: the auto-scroll used a fixed 100 ms timer that could fire before the target card mounts; it now gates a one-shot scroll on the card's presence.
  • DRY: the RSS route imports SITE from lib/changelog instead of redefining it.
  • a11y: the "Link copied" confirmation is announced via an sr-only role="status" live region.
  • Tests: added unit tests for the pure helpers (matchesFilters, filterEntries, feedUrl, fmtEntryDate, relativeDate incl. the noon-UTC regression, and parseListParam) and wired the missing test:unit script so jest actually runs in CI.

Re-verified: tsc · biome · stylelint · jest (20/20) · next build all clean; light/dark/mobile plus filtering, deep-link reveal, and URL-state reconciliation exercised in-browser with no hydration errors.

🤖 Generated with Claude Code


Open in Devin Review

Extend the market-data-only changelog into a cross-product hub covering
Pyth Pro, Pyth Core, and Entropy.

- Move the page from /price-feeds/changelog to top-level /changelog
  (308 redirect; nav, ChangelogBar, and BasePage repointed).
- Product Updates tab: hand-authored MDX entries under content/changelog/,
  filterable by Product / Area / Type with live faceted counts, date-grouped
  cards with semantic type badges, and per-entry deep-link + copy.
- Market Data tab: reuses the existing automated stream.
- RSS: /changelog/feed.xml plus per-product feeds, a Subscribe menu, and
  <link rel="alternate"> auto-discovery on the page.
- Full WAI-ARIA tabs (roving tabindex + arrow keys, tabpanel wiring),
  labelled filter groups, focus-visible rings, and a robust deep-link
  reveal that survives filter clearing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
component-library Ready Ready Preview, Comment Jul 20, 2026 4:36pm
developer-hub Ready Ready Preview, Comment Jul 20, 2026 4:36pm
5 Skipped Deployments
Project Deployment Actions Updated (UTC)
api-reference Skipped Skipped Jul 20, 2026 4:36pm
entropy-explorer Skipped Skipped Jul 20, 2026 4:36pm
insights Skipped Skipped Jul 20, 2026 4:36pm
proposals Skipped Skipped Jul 20, 2026 4:36pm
staking Skipped Skipped Jul 20, 2026 4:36pm

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bcb7a4116b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- Provider-configurable fee schedules
- Batch reveal for high-volume apps

See [contract addresses](/entropy/contract-addresses) for the new deployments.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point the Entropy entry to the existing chainlist page

This link leads to a 404 because there is no /entropy/contract-addresses page or redirect in the Developer Hub. The contract-address table is provided by content/docs/entropy/chainlist.mdx at /entropy/chainlist, so readers following this new changelog entry cannot reach the referenced deployment details.

Useful? React with 👍 / 👎.

Comment on lines +241 to +245
{
destination: "/changelog",
permanent: true,
source: "/price-feeds/changelog",
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the legacy raw-markdown changelog URLs

This redirect only matches the extensionless route. The documented raw-doc URLs /price-feeds/changelog.mdx and /price-feeds/changelog.md are explicitly excluded from the generic Price Feeds redirect below, so they instead rewrite through /mdx/price-feeds/changelog after the old document has been deleted and return 404. Add redirects for these variants to the corresponding /changelog.mdx or /changelog.md endpoints.

Useful? React with 👍 / 👎.

"description": "Real-time financial market data",
"icon": "ChartLine",
"pages": ["core", "pro", "changelog"],
"pages": ["core", "pro"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the unified changelog to the top-level page tree

Removing changelog here eliminates its only sidebar entry, but content/docs/meta.json still lists only price-feeds, express-relay, entropy, and api-reference. Because DocsLayout renders source.pageTree, the new cross-product page is absent from navigation even though it is now a top-level product-wide destination; add changelog to the root metadata when removing it from this section.

Useful? React with 👍 / 👎.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment on lines +16 to +17
const slugOf = (entry: CollectionEntry): string =>
entry.info.path.replace(/\.mdx$/, "");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 slugOf relies on info.path being relative to the collection dir

slugOf in apps/developer-hub/src/lib/changelog-data.ts:16-17 derives the entry's stable anchor slug (used as id={entry.slug} on the card and in #slug deep links and RSS item links) from entry.info.path.replace(/\.mdx$/, ""). This is only correct if fumadocs-mdx's info.path is relative to the collection dir (content/changelog) rather than an absolute or project-root-relative path; otherwise slugs would contain slashes and break the anchor/deep-link behavior. Given the collection's flat content/changelog/ directory and that tsc is reported clean, this is consistent with fumadocs-mdx v14 behavior, but worth confirming against the generated .source output if deep links ever misbehave.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

- Date groups now hang off a continuous vertical timeline rail with a node
  marker per date (Linear/Vercel-style changelog layout).
- Each entry card carries a type-keyed left accent (feature/fix/breaking/
  deprecation/docs) so the feed scans by change-type at a glance.
- Slightly tightened the filter bar (chip padding + row gap).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the /changelog Product updates UI to match the Pyth Lazer
(@pythnetwork/components) design language, built on the developer-hub
component library and its design tokens:

- Large editorial tabs plus a solid violet Subscribe (component-library
  Button + Popover), scoped to the Product updates tab.
- Faceted checkbox filter (Product / Type / Area) with live counts,
  Clear all, and a mobile disclosure — modelled on ItemListFilter.
- Tinted semantic type tags via states.* tokens; the entry date doubles
  as a permalink (useCopy); titles link to their anchor.
- Relative-time labels computed at build time to avoid hydration drift.

The docs shell already renders the page title and description, so the
component renders no hero. The Market data tab is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…11y, tests

Review-pass fixes for the cross-product changelog:

- SSR: drop useSearchParams from HubTabs/ProductUpdates (it bailed the whole
  feed out of the static prerender). Default tab/filters and reconcile URL
  state after mount so the full feed renders into static HTML; remove the
  now-unnecessary Suspense boundary.
- fix: relativeDate was off by one for any render at/after 12:00 UTC; diff
  whole UTC calendar days instead of folding in the current time-of-day.
- fix: RSS route returned 400 for a bare `?product=`; treat empty as absent
  and serve the all-products feed.
- fix: deep-link auto-scroll used a fixed 100ms timer that could fire before
  the target card mounts; gate the one-shot scroll on the card's presence.
- DRY: import SITE from lib/changelog instead of redefining it in the RSS route.
- a11y: announce "Link copied" via an sr-only role=status live region.
- tests: add unit tests for the pure changelog helpers and parseListParam, and
  wire the missing test:unit script so jest runs in CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@aditya520
aditya520 requested a review from a team as a code owner July 20, 2026 16:32
@vercel
vercel Bot temporarily deployed to Preview – entropy-explorer July 20, 2026 16:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – insights July 20, 2026 16:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – api-reference July 20, 2026 16:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – staking July 20, 2026 16:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – proposals July 20, 2026 16:32 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant