From eadb10af7c8b2a159662a5dfdb2eb278ef4d30d3 Mon Sep 17 00:00:00 2001 From: Danyal Prout Date: Mon, 24 Aug 2026 12:11:39 -0500 Subject: [PATCH 1/2] feat(upgrades): combine changelog with upgrades Co-authored-by: Codex --- app/components/AppShell.tsx | 8 +--- app/navigation.ts | 3 +- app/sitemap.ts | 1 - app/upgrades/UpgradesClient.tsx | 64 +++++++++++++++++++----------- app/upgrades/changelog/loading.tsx | 26 ------------ app/upgrades/changelog/page.tsx | 19 --------- app/upgrades/page.tsx | 12 +++++- next.config.mjs | 5 +++ scripts/lib/config.mjs | 1 - 9 files changed, 58 insertions(+), 81 deletions(-) delete mode 100644 app/upgrades/changelog/loading.tsx delete mode 100644 app/upgrades/changelog/page.tsx diff --git a/app/components/AppShell.tsx b/app/components/AppShell.tsx index 3bf130a..caa3773 100644 --- a/app/components/AppShell.tsx +++ b/app/components/AppShell.tsx @@ -206,12 +206,6 @@ function NavGlyph({ name }: NavGlyphProps) { /> ); - case 'changelog': - return ( - - - - ); case 'vibenet': return ( @@ -773,7 +767,7 @@ export function AppShell({ children }: PropsWithChildren) { return ( ); diff --git a/app/navigation.ts b/app/navigation.ts index 2ea0d8f..e4ed414 100644 --- a/app/navigation.ts +++ b/app/navigation.ts @@ -1,7 +1,7 @@ import { BENCHMARK_ENABLED } from './benchmark/flag'; import { TIPS_ENABLED } from './tips/flag'; -export type NavIcon = 'home' | 'snapshots' | 'upgrades' | 'changelog' | 'vibenet' | 'overview' | 'demos' | 'faucet' | 'explorer' | 'tips' | 'benchmark' | 'runs' | 'loadtest'; +export type NavIcon = 'home' | 'snapshots' | 'upgrades' | 'vibenet' | 'overview' | 'demos' | 'faucet' | 'explorer' | 'tips' | 'benchmark' | 'runs' | 'loadtest'; export type NavChild = { label: string; @@ -33,7 +33,6 @@ export const NAV_ITEMS: NavItem[] = [ }, { label: 'Demos', href: '/demos', icon: 'demos', enabled: true }, { label: 'Upgrades', href: '/upgrades', icon: 'upgrades', enabled: true }, - { label: 'Changelog', href: '/upgrades/changelog', icon: 'changelog', enabled: true }, { label: 'Snapshots', href: '/snapshots', icon: 'snapshots', enabled: true }, // TIPS is internal-only; present only in the internal build target // (deploy.config.mjs). See app/tips/flag.ts. diff --git a/app/sitemap.ts b/app/sitemap.ts index d554e82..4fd2a58 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -15,7 +15,6 @@ export default function sitemap(): MetadataRoute.Sitemap { const routes: Array<{ path: string; priority: number; changeFrequency: MetadataRoute.Sitemap[number]['changeFrequency'] }> = [ { path: '/', priority: 1.0, changeFrequency: 'weekly' }, { path: '/upgrades', priority: 0.8, changeFrequency: 'weekly' }, - { path: '/upgrades/changelog', priority: 0.7, changeFrequency: 'weekly' }, { path: '/snapshots', priority: 0.7, changeFrequency: 'daily' }, // TIPS and Benchmark are internal-only and never on the public // chain.base.org, so they are deliberately absent from this public SEO diff --git a/app/upgrades/UpgradesClient.tsx b/app/upgrades/UpgradesClient.tsx index bc53b8a..753b831 100644 --- a/app/upgrades/UpgradesClient.tsx +++ b/app/upgrades/UpgradesClient.tsx @@ -1,7 +1,8 @@ 'use client'; -import { useMemo, useState } from 'react'; +import { useMemo } from 'react'; import Link from 'next/link'; +import { useRouter, useSearchParams } from 'next/navigation'; import { AnimatePresence, motion, useReducedMotion } from 'motion/react'; import { SlideInUp } from '../components/ui/SlideInUp'; @@ -13,6 +14,7 @@ import { Text } from '../components/ui/Text'; import { StatusPill } from './components/Badges'; import { UpgradeIllustration } from './components/UpgradeIllustration'; +import { ChangelogClient } from './changelog/ChangelogClient'; import { changes } from './data/changes'; import { upgrades } from './data/upgrades'; import { @@ -24,7 +26,11 @@ import { formatLifecycleDate } from './library/format'; import { getLifecycleState } from './library/lifecycle'; import type { Lifecycle, LifecycleState } from './library/types'; -type View = 'timeline' | 'upgrade'; +type View = 'timeline' | 'upgrade' | 'changelog'; + +function parseView(value: string | null): View { + return value === 'timeline' || value === 'changelog' ? value : 'upgrade'; +} const GridIcon = ( ); +const ChangelogIcon = ( + +); + const VIEW_TABS = [ { value: 'upgrade', label: 'Grid', icon: GridIcon }, { value: 'timeline', label: 'Timeline', icon: TimelineIcon }, + { value: 'changelog', label: 'Changelog', icon: ChangelogIcon }, ]; const MONTH_NAMES = [ @@ -291,17 +304,28 @@ function UpgradeView({ nowMs }: { nowMs: number }) { } export function UpgradesClient() { - const [view, setView] = useState('upgrade'); + const router = useRouter(); + const searchParams = useSearchParams(); + const view = parseView(searchParams.get('tab')); const reducedMotion = useReducedMotion(); const nowMs = Date.now(); + function handleViewChange(next: string) { + const params = new URLSearchParams(searchParams.toString()); + if (next === 'upgrade') params.delete('tab'); + else params.set('tab', next); + + const query = params.toString(); + router.replace(query ? `/upgrades?${query}` : '/upgrades', { scroll: false }); + } + return (
setView(v as View)} + onChange={handleViewChange} ariaLabel="View mode" />
@@ -309,27 +333,21 @@ export function UpgradesClient() { {/* `initial={false}`: the crossfade is for switching views, not for first paint — on mount it fades up over a just-removed skeleton, leaving the column blank. */} - {view === 'timeline' ? ( - + + {view === 'timeline' ? ( - - ) : ( - + ) : view === 'changelog' ? ( + + ) : ( - - )} + )} +
); diff --git a/app/upgrades/changelog/loading.tsx b/app/upgrades/changelog/loading.tsx deleted file mode 100644 index 08728e1..0000000 --- a/app/upgrades/changelog/loading.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Skeleton } from '../../components/ui/Skeleton'; - -export default function ChangelogLoading() { - return ( -
-
- - -
- - - -
- {[0, 1, 2, 3, 4, 5].map((i) => ( -
- - -
- ))} -
-
- ); -} diff --git a/app/upgrades/changelog/page.tsx b/app/upgrades/changelog/page.tsx deleted file mode 100644 index 4fcf888..0000000 --- a/app/upgrades/changelog/page.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { Metadata } from 'next'; - -import { ChangelogClient } from './ChangelogClient'; - -export const metadata: Metadata = { - title: 'Changelog · Base Upgrades', - description: 'Search and filter Base protocol changes across upgrades and Vibenet testing.', - alternates: { - canonical: '/upgrades/changelog', - }, -}; - -export default function ChangelogPage() { - return ( -
- -
- ); -} diff --git a/app/upgrades/page.tsx b/app/upgrades/page.tsx index 053a3ca..9c7a8ca 100644 --- a/app/upgrades/page.tsx +++ b/app/upgrades/page.tsx @@ -1,11 +1,13 @@ import type { Metadata } from 'next'; +import { Suspense } from 'react'; import { UpgradesClient } from './UpgradesClient'; +import UpgradesLoading from './loading'; export const metadata: Metadata = { title: 'Upgrades · Base Chain', description: - 'Track Base network upgrades and their activation status across Base Sepolia and Mainnet.', + 'Track Base network upgrades and search protocol changes across Base Sepolia and Mainnet.', alternates: { canonical: '/upgrades', }, @@ -14,5 +16,11 @@ export const metadata: Metadata = { export const revalidate = 300; export default function UpgradesPage() { - return ; + // UpgradesClient reads useSearchParams (to sync the grid/timeline/changelog + // tab with `?tab=`), which needs a Suspense boundary per Next 15 App Router. + return ( + }> + + + ); } diff --git a/next.config.mjs b/next.config.mjs index 09ce20b..81580a0 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -9,10 +9,15 @@ const nextConfig = { // were in the published sitemap and /vibenet/demos/account is linked from the // site-wide announcement banner, so they are permanently redirected rather // than left to 404 for existing links and search results. + // + // The changelog listing moved from its own page into a tab on /upgrades + // (grid | timeline | changelog); /upgrades/changelog/[slug] detail pages are + // unaffected and still live at their own route. async redirects() { return [ { source: '/vibenet/demos', destination: '/demos', permanent: true }, { source: '/vibenet/demos/:path*', destination: '/demos/:path*', permanent: true }, + { source: '/upgrades/changelog', destination: '/upgrades?tab=changelog', permanent: true }, ]; }, }; diff --git a/scripts/lib/config.mjs b/scripts/lib/config.mjs index 458d21f..4c4038a 100644 --- a/scripts/lib/config.mjs +++ b/scripts/lib/config.mjs @@ -115,7 +115,6 @@ export const DEFAULTS = { '/snapshots': 'daily', '/vibenet/explorer': 'daily', '/upgrades': 'per release', - '/upgrades/changelog': 'per release', '/vibenet/faucet': 'monthly', }, From d719d2ca674abb5a7fe63b24fa48d18a0aace360 Mon Sep 17 00:00:00 2001 From: Danyal Prout Date: Mon, 24 Aug 2026 12:11:47 -0500 Subject: [PATCH 2/2] docs: refresh agent indexes Co-authored-by: Codex --- public/AGENTS.md | 4 +--- public/llms-full.txt | 3 +-- public/llms.txt | 5 ++--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/public/AGENTS.md b/public/AGENTS.md index 28cf11d..827eaaf 100644 --- a/public/AGENTS.md +++ b/public/AGENTS.md @@ -24,7 +24,6 @@ Machine-readable entry point for agents working with Base Chain network state. | /snapshots | daily | re-fetch every session; never cache across sessions | | /vibenet/explorer | daily | re-fetch every session; never cache across sessions | | /upgrades | per release | re-fetch before stating an activation status | -| /upgrades/changelog | per release | re-fetch before stating an activation status | | /vibenet/faucet | monthly | stable within a session | | /api/snapshots | daily | re-fetch every session; never cache across sessions | | /, /demos, /demos/account, /demos/b20, /vibenet | infrequent | stable within a session | @@ -79,8 +78,7 @@ Discovered from the Next.js app directory. **Network state** - [/](https://chain.base.org/) — Dashboards and tools for Base Chain, in one place. -- [/upgrades](https://chain.base.org/upgrades) — Track Base network upgrades and their activation status across Base Sepolia and Mainnet. -- [/upgrades/changelog](https://chain.base.org/upgrades/changelog) — Search and filter Base protocol changes across upgrades and Vibenet testing. +- [/upgrades](https://chain.base.org/upgrades) — Track Base network upgrades and search protocol changes across Base Sepolia and Mainnet. - [/snapshots](https://chain.base.org/snapshots) — Download the latest Base node snapshots for Mainnet and Base Sepolia to sync a node quickly. **Vibenet developer network** diff --git a/public/llms-full.txt b/public/llms-full.txt index 98e8812..fdb9bb0 100644 --- a/public/llms-full.txt +++ b/public/llms-full.txt @@ -13,8 +13,7 @@ ## Network state - [Base Chain](https://chain.base.org/): Dashboards and tools for Base Chain, in one place. -- [Upgrades · Base Chain](https://chain.base.org/upgrades): Track Base network upgrades and their activation status across Base Sepolia and Mainnet. (changes per release; re-fetch before relying on it) -- [Changelog · Base Upgrades](https://chain.base.org/upgrades/changelog): Search and filter Base protocol changes across upgrades and Vibenet testing. (changes per release; re-fetch before relying on it) +- [Upgrades · Base Chain](https://chain.base.org/upgrades): Track Base network upgrades and search protocol changes across Base Sepolia and Mainnet. (changes per release; re-fetch before relying on it) - [Snapshots · Base Chain](https://chain.base.org/snapshots): Download the latest Base node snapshots for Mainnet and Base Sepolia to sync a node quickly. (changes daily; re-fetch before relying on it) ## Vibenet developer network diff --git a/public/llms.txt b/public/llms.txt index 9720909..9f5893e 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -7,12 +7,11 @@ Use this site for current network state. Use https://docs.base.org for implementation detail: how to write, deploy, and debug code. If the two disagree on an activation date, an upgrade status, or a snapshot URL, this site is authoritative; for API shapes, contract addresses, and code, docs.base.org is authoritative. Do not infer Base chain IDs or RPC URLs from third-party chain lists or from model memory — use the network reference below. -Freshness: /snapshots and /vibenet/explorer change daily. /vibenet/faucet changes monthly. /upgrades and /upgrades/changelog change per release. Re-fetch these within a session rather than reusing an earlier response. Vibenet is ephemeral — never treat an address, balance, block height, or chain ID from it as durable. +Freshness: /snapshots and /vibenet/explorer change daily. /vibenet/faucet changes monthly. /upgrades changes per release. Re-fetch these within a session rather than reusing an earlier response. Vibenet is ephemeral — never treat an address, balance, block height, or chain ID from it as durable. ## Network state - [Base Chain](https://chain.base.org/): Dashboards and tools for Base Chain, in one place. -- [Upgrades · Base Chain](https://chain.base.org/upgrades): Track Base network upgrades and their activation status across Base Sepolia and Mainnet. -- [Changelog · Base Upgrades](https://chain.base.org/upgrades/changelog): Search and filter Base protocol changes across upgrades and Vibenet testing. +- [Upgrades · Base Chain](https://chain.base.org/upgrades): Track Base network upgrades and search protocol changes across Base Sepolia and Mainnet. - [Snapshots · Base Chain](https://chain.base.org/snapshots): Download the latest Base node snapshots for Mainnet and Base Sepolia to sync a node quickly. ## Vibenet developer network