diff --git a/.gitignore b/.gitignore
index 0f36f54fa..938c6fae1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ drizzle/migrations
.DS_Store
.cache
.env
+.env.*
.vercel
.output
.vinxi
diff --git a/docs/performance-plan-home-library-docs.md b/docs/performance-plan-home-library-docs.md
new file mode 100644
index 000000000..32b505bd2
--- /dev/null
+++ b/docs/performance-plan-home-library-docs.md
@@ -0,0 +1,216 @@
+# Homepage, Library Landing, and Docs Performance Plan
+
+## Goal
+
+Make the homepage, library landing pages, and docs materially faster, lighter, and cheaper to render without regressing content quality or navigation UX.
+
+## Current Baseline
+
+- Homepage route chunk: `dist/client/assets/index-Bq0A5jmY.js` at `564.79 kB / 172.14 kB gzip`
+- Shared shell chunk: `dist/client/assets/app-shell-BikUtTEO.js` at `349.55 kB / 110.08 kB gzip`
+- Search modal chunk: `dist/client/assets/SearchModal-Bl-tUxqr.js` at `195.54 kB / 54.27 kB gzip`
+- Docs shell chunk: `dist/client/assets/DocsLayout-Bga1-HA9.js` at `17.61 kB / 6.05 kB gzip`
+- Markdown chrome chunk: `dist/client/assets/MarkdownContent-ia2V1dk8.js` at `19.37 kB / 6.39 kB gzip`
+- Global CSS: `dist/client/assets/app-CBMELhsb.css` at `319.24 kB / 40.48 kB gzip`
+
+## Main Problems
+
+- Homepage ships too much in one route chunk.
+- Library landing pages pay docs-shell and docs-config cost before the user asks for docs.
+- Docs still do too much work per request even with GitHub content caching.
+- Hidden docs UI still mounts and runs effects/queries.
+- Anonymous docs users still trigger auth-related client queries for framework preference.
+- Some "lazy" controls are effectively eager.
+
+## Success Targets
+
+- Cut the homepage route chunk hard enough that it is no longer one of the top client payloads.
+- Remove docs-config and docs-layout from the critical path for landing pages.
+- Turn docs page rendering into mostly cached work.
+- Avoid client queries on first paint for content that can be rendered server-side.
+- Reduce hidden-work JS on docs mobile and desktop layouts.
+
+## Workstreams
+
+### 1. Homepage route diet
+
+Targets:
+
+- `src/routes/index.tsx`
+- `src/components/OpenSourceStats.tsx`
+- `src/components/ShowcaseSection.tsx`
+- `src/components/PartnersGrid.tsx`
+- `src/components/MaintainerCard.tsx`
+
+Changes:
+
+- Break below-the-fold homepage sections into viewport-triggered lazy boundaries.
+- Move recent posts off client `useQuery` and into route loader or server-rendered data.
+- Stop client-fetching OSS stats on initial paint. Render a server snapshot first.
+- Keep `DeferredApplicationStarter` deferred by visibility or interaction, not just idle timeout.
+- Avoid eagerly importing large static datasets into the first route chunk where possible.
+- Stop rendering both light and dark hero image variants eagerly.
+
+Expected win:
+
+- Lower homepage JS, lower hydration cost, lower first-load network.
+
+### 2. Dedicated library landing shell
+
+Targets:
+
+- `src/routes/-library-landing.tsx`
+- `src/components/DocsLayout.tsx`
+- landing components under `src/components/landing/`
+
+Changes:
+
+- Introduce a dedicated `LibraryLandingLayout`.
+- Remove `DocsLayout` from landing pages.
+- Stop fetching docs `config.json` in the landing-page critical path unless a landing section actually needs it.
+- Keep framework/version/docs navigation lightweight on landing pages and hand off to docs only when needed.
+
+Expected win:
+
+- Better landing-page TTFB, less landing-page JS, less docs chrome on non-docs surfaces.
+
+### 3. Docs render caching
+
+Targets:
+
+- `src/utils/docs.functions.ts`
+- `src/utils/github-content-cache.server.ts`
+- `src/utils/markdown/renderRsc.tsx`
+- `src/utils/markdown/processor.rsc.tsx`
+- `src/components/markdown/renderCodeBlock.server.tsx`
+
+Changes:
+
+- Cache rendered docs artifacts, not just raw GitHub files.
+- Persist `title`, `description`, `headings`, and rendered output keyed by repo, ref, docs root, and path.
+- Reuse existing docs artifact cache infra instead of adding a second caching path.
+- Make docs requests mostly cache hits unless the source changed.
+
+Expected win:
+
+- Better docs TTFB, less server CPU, fewer repeated markdown and Shiki passes.
+
+### 4. Docs layout mount discipline
+
+Targets:
+
+- `src/components/DocsLayout.tsx`
+- `src/components/RightRail.tsx`
+- `src/components/RecentPostsWidget.tsx`
+
+Changes:
+
+- Do not mount mobile docs menu on desktop.
+- Do not mount desktop docs menu on mobile.
+- Do not mount right rail when hidden by breakpoint.
+- Gate animated partner strip work by actual viewport and reduced-motion preference.
+- Ensure hidden rails do not issue queries or observers.
+
+Expected win:
+
+- Lower docs runtime cost, especially on mobile.
+
+### 5. Remove anonymous auth work from docs and landing
+
+Targets:
+
+- `src/components/FrameworkSelect.tsx`
+- `src/hooks/useCurrentUser.ts`
+- `src/components/SearchModal.tsx`
+- `src/components/NavbarAuthControls.tsx`
+
+Changes:
+
+- Make framework preference local-first for anonymous users.
+- Only sync framework preference to server when user state is already known.
+- Avoid triggering `getCurrentUser` on docs and landing pages just to resolve a preference.
+- Audit other shell components for accidental auth fetches during anonymous browsing.
+
+Expected win:
+
+- Fewer unnecessary client requests, cleaner anonymous docs navigation.
+
+### 6. Shared shell cleanup
+
+Targets:
+
+- `src/routes/__root.tsx`
+- `src/router.tsx`
+- `src/components/Navbar.tsx`
+- `src/components/markdown/MarkdownContent.tsx`
+
+Changes:
+
+- Verify why some intended dynamic imports are not splitting effectively.
+- Trim eager shell work around Sentry boot where possible.
+- Fix `MarkdownContent` so `CopyPageDropdown` only loads on real interaction.
+- Review navbar asset duplication and avoid eager light/dark image duplication where possible.
+
+Expected win:
+
+- Smaller app shell, less global cost paid by every route.
+
+## Suggested Implementation Order
+
+1. Fix obviously accidental eager work.
+2. Make docs layout mount only what is visible.
+3. Remove anonymous auth fetches from docs and landing flows.
+4. Add dedicated library landing shell and remove docs-config from landing critical path.
+5. Move homepage content and stats to server-first data flows and split below-the-fold sections.
+6. Add rendered docs artifact caching.
+7. Rebuild and compare chunks, request timings, and interaction cost.
+
+## PR Breakdown
+
+### PR 1
+
+- Fix `MarkdownContent` eager copy-dropdown load
+- Stop hidden docs rails and menus from mounting
+- Gate mobile partner strip animation correctly
+
+### PR 2
+
+- Remove anonymous auth fetches from framework selection and related docs shell code
+
+### PR 3
+
+- Add `LibraryLandingLayout`
+- Remove `DocsLayout` and docs config dependency from landing critical path
+
+### PR 4
+
+- Split homepage below the fold
+- Server-render recent posts and stats
+- Tighten app-starter deferral
+
+### PR 5
+
+- Cache rendered docs artifacts
+- Measure docs TTFB and server CPU improvement
+
+### PR 6
+
+- Shared shell follow-up: Sentry boot, navbar assets, remaining bundle outliers
+
+## Verification
+
+- Run `pnpm build` after each major phase.
+- Track homepage, a representative library landing page, and a representative docs page.
+- Compare:
+- route chunk size
+- app shell size
+- docs TTFB
+- number of client requests on first load
+- whether anonymous docs visits trigger user/auth requests
+- smoke-check desktop and mobile docs navigation
+
+## Notes
+
+- `LazyLandingCommunitySection` and `LazySponsorSection` already use the right pattern. Reuse that pattern more aggressively.
+- `StackBlitzEmbed` is already `loading="lazy"`, but a poster-plus-click model may still be worth it for landing pages.
+- Do not spend time micro-optimizing heading observers or tiny docs chunks before fixing the homepage and landing-page architecture.
diff --git a/docs/proposals/npm-watchlist-registry-draft.md b/docs/proposals/npm-watchlist-registry-draft.md
new file mode 100644
index 000000000..1e6a4f612
--- /dev/null
+++ b/docs/proposals/npm-watchlist-registry-draft.md
@@ -0,0 +1,694 @@
+# Draft: NPM Watchlist Registry
+
+## Purpose
+
+Define a source-of-truth registry for tracked npm entities, rollups, and curated watchlists.
+
+This registry should replace the idea that `popular comparisons` are the canonical list. Popular comparisons can still exist, but they should derive from this registry.
+
+Rollups should be the reusable grouping abstraction.
+
+Watchlists should remain the primary user-facing saved and subscribed surface. Categories are metadata on entities, not the source of truth for ranking surfaces.
+
+## Design Goals
+
+- Model logical libraries, not just raw package names.
+- Support legacy package rollups.
+- Support reusable rollup definitions for ecosystems and grouped chart views.
+- Keep curation explicit and reviewable in code.
+- Make it easy to derive chart `packageGroups` for the existing UI.
+- Leave room for future time-aware lineage rules without requiring them in v1.
+
+## Suggested File
+
+- `src/utils/npm-watchlists.ts`
+
+## Proposed Types
+
+```ts
+export type NpmTrackedEntity = {
+ id: string
+ label: string
+ shortLabel?: string
+ description?: string
+ categories: Array<
+ | 'tanstack'
+ | 'data-fetching'
+ | 'routing'
+ | 'state'
+ | 'table'
+ | 'form'
+ | 'virtualization'
+ | 'testing'
+ | 'styling'
+ | 'build'
+ | 'validation'
+ | 'docs'
+ | 'framework'
+ | 'animation'
+ | 'tooling'
+ | 'database'
+ >
+ color?: string
+ packages: Array<{
+ name: string
+ from?: string
+ to?: string
+ }>
+ lineageStrategy?: 'sum-all' | 'time-bounded'
+ benchmarkEligible?: boolean
+ popularComparisonEligible?: boolean
+ hidden?: boolean
+}
+
+export type NpmWatchlist = {
+ id: string
+ title: string
+ description?: string
+ kind: 'curated-category' | 'curated-benchmark' | 'curated-tanstack'
+ entityIds?: string[]
+ rollupIds?: string[]
+ featured?: boolean
+ public?: boolean
+ popularComparison?: boolean
+ benchmark?: boolean
+}
+
+export type NpmRollup = {
+ id: string
+ title: string
+ description?: string
+ kind: 'ecosystem' | 'category' | 'benchmark' | 'editorial'
+ entityIds: string[]
+ membershipMode?: 'exclusive' | 'overlap'
+ color?: string
+ public?: boolean
+}
+```
+
+## V1 Simplification
+
+Even though the entity type allows `from` and `to`, v1 can treat almost all tracked entities as:
+
+- `lineageStrategy: 'sum-all'`
+- all packages included for the full period
+
+That matches the current stats architecture and keeps the first implementation simple.
+
+## Derivations
+
+The registry should support these outputs:
+
+1. `getWatchlist(id)`
+2. `getTrackedEntity(id)`
+3. `getRollup(id)`
+4. `getFeaturedWatchlists()`
+5. `toPackageGroups(watchlist)` for existing chart routes
+6. `toPopularComparisons()` to replace hand-maintained duplication
+7. `groupEntitiesByRollup(entityIds, rollupIds)` for charting and digest summarization
+
+## Curation Rules
+
+### Tracked entities
+
+- One entity should represent one logical product or library line.
+- One entity can belong to multiple categories.
+- Legacy package names should be included when they clearly map to the same product lineage.
+- Do not merge adjacent but meaningfully different products just because users might compare them.
+
+### Watchlists
+
+- A curated category watchlist should feel category-coherent.
+- A benchmark watchlist should be broad, stable, and slow-changing.
+- A featured watchlist should be editorially maintained and reviewed regularly.
+
+### Rollups
+
+- A rollup is a reusable editorial grouping of entities.
+- Rollups are explicit, not inferred from npm scopes or package naming.
+- Some rollups can overlap.
+- Some rollups should be exclusive where double counting would distort rankings.
+- Rollups should be stable enough to support long-term historical views.
+
+### Review cadence
+
+- Featured watchlists: monthly review
+- Benchmark watchlists: quarterly review
+- Ecosystem rollups: quarterly review
+- Entity lineage changes: only when we have high confidence
+
+## Starter Tracked Entities
+
+This is not exhaustive. It is the first pass for v1.
+
+```ts
+export const trackedEntities: NpmTrackedEntity[] = [
+ {
+ id: 'tanstack-query',
+ label: 'TanStack Query',
+ categories: ['tanstack', 'data-fetching'],
+ color: '#FF4500',
+ packages: [{ name: '@tanstack/react-query' }, { name: 'react-query' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'swr',
+ label: 'SWR',
+ categories: ['data-fetching'],
+ color: '#ec4899',
+ packages: [{ name: 'swr' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'apollo-client',
+ label: 'Apollo Client',
+ categories: ['data-fetching'],
+ color: '#6B46C1',
+ packages: [{ name: '@apollo/client' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'trpc-client',
+ label: 'tRPC Client',
+ categories: ['data-fetching'],
+ color: '#2596BE',
+ packages: [{ name: '@trpc/client' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'tanstack-router',
+ label: 'TanStack Router',
+ categories: ['tanstack', 'routing'],
+ color: '#32CD32',
+ packages: [{ name: '@tanstack/react-router' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'react-router',
+ label: 'React Router',
+ categories: ['routing'],
+ color: '#FF0000',
+ packages: [{ name: 'react-router' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'wouter',
+ label: 'Wouter',
+ categories: ['routing'],
+ color: '#8b5cf6',
+ packages: [{ name: 'wouter' }],
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'tanstack-table',
+ label: 'TanStack Table',
+ categories: ['tanstack', 'table'],
+ color: '#FF7043',
+ packages: [{ name: '@tanstack/react-table' }, { name: 'react-table' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'ag-grid',
+ label: 'AG Grid',
+ categories: ['table'],
+ color: '#29B6F6',
+ packages: [{ name: 'ag-grid-community' }, { name: 'ag-grid-enterprise' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'mui-data-grid',
+ label: 'MUI Data Grid',
+ categories: ['table'],
+ color: '#1976D2',
+ packages: [{ name: '@mui/x-data-grid' }, { name: 'mui-datatables' }],
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'tanstack-form',
+ label: 'TanStack Form',
+ categories: ['tanstack', 'form'],
+ color: '#FFD700',
+ packages: [
+ { name: '@tanstack/form-core' },
+ { name: '@tanstack/react-form' },
+ ],
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'react-hook-form',
+ label: 'React Hook Form',
+ categories: ['form'],
+ color: '#EC5990',
+ packages: [{ name: 'react-hook-form' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'conform',
+ label: 'Conform',
+ categories: ['form'],
+ color: '#FF5733',
+ packages: [{ name: '@conform-to/dom' }],
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'tanstack-virtual',
+ label: 'TanStack Virtual',
+ categories: ['tanstack', 'virtualization'],
+ color: '#8B5CF6',
+ packages: [{ name: '@tanstack/react-virtual' }, { name: 'react-virtual' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'react-window',
+ label: 'react-window',
+ categories: ['virtualization'],
+ color: '#4ECDC4',
+ packages: [{ name: 'react-window' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'react-virtualized',
+ label: 'react-virtualized',
+ categories: ['virtualization'],
+ color: '#FF6B6B',
+ packages: [{ name: 'react-virtualized' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'redux',
+ label: 'Redux',
+ categories: ['state'],
+ color: '#764ABC',
+ packages: [{ name: 'redux' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'zustand',
+ label: 'Zustand',
+ categories: ['state'],
+ color: '#764ABC',
+ packages: [{ name: 'zustand' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'jotai',
+ label: 'Jotai',
+ categories: ['state'],
+ color: '#6366f1',
+ packages: [{ name: 'jotai' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'valtio',
+ label: 'Valtio',
+ categories: ['state'],
+ color: '#FF6B6B',
+ packages: [{ name: 'valtio' }],
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'vite',
+ label: 'Vite',
+ categories: ['build', 'tooling'],
+ color: '#008000',
+ packages: [{ name: 'vite' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'webpack',
+ label: 'Webpack',
+ categories: ['build', 'tooling'],
+ color: '#8DD6F9',
+ packages: [{ name: 'webpack' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'rollup',
+ label: 'Rollup',
+ categories: ['build', 'tooling'],
+ color: '#e80A3F',
+ packages: [{ name: 'rollup' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'esbuild',
+ label: 'esbuild',
+ categories: ['build', 'tooling'],
+ color: '#FFCF00',
+ packages: [{ name: 'esbuild' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'rspack',
+ label: 'Rspack',
+ categories: ['build', 'tooling'],
+ color: '#8DD6F9',
+ packages: [{ name: '@rspack/core' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'zod',
+ label: 'Zod',
+ categories: ['validation'],
+ color: '#ef4444',
+ packages: [{ name: 'zod' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'valibot',
+ label: 'Valibot',
+ categories: ['validation'],
+ color: '#f97316',
+ packages: [{ name: 'valibot' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'yup',
+ label: 'Yup',
+ categories: ['validation'],
+ color: '#06b6d4',
+ packages: [{ name: 'yup' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'react',
+ label: 'React',
+ categories: ['framework'],
+ color: '#61DAFB',
+ packages: [{ name: 'react' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'vue',
+ label: 'Vue',
+ categories: ['framework'],
+ color: '#41B883',
+ packages: [{ name: 'vue' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'angular-core',
+ label: 'Angular',
+ categories: ['framework'],
+ color: '#DD0031',
+ packages: [{ name: '@angular/core' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'svelte',
+ label: 'Svelte',
+ categories: ['framework'],
+ color: '#FF3E00',
+ packages: [{ name: 'svelte' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+ {
+ id: 'solid-js',
+ label: 'Solid',
+ categories: ['framework'],
+ color: '#2C4F7C',
+ packages: [{ name: 'solid-js' }],
+ benchmarkEligible: true,
+ popularComparisonEligible: true,
+ },
+]
+```
+
+## Starter Curated Watchlists
+
+```ts
+export const watchlists: NpmWatchlist[] = [
+ {
+ id: 'data-fetching',
+ title: 'Data Fetching',
+ kind: 'curated-category',
+ entityIds: ['tanstack-query', 'swr', 'apollo-client', 'trpc-client'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'routing-react',
+ title: 'Routing (React)',
+ kind: 'curated-category',
+ entityIds: ['react-router', 'tanstack-router', 'wouter'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'tables-data-grids',
+ title: 'Tables and Data Grids',
+ kind: 'curated-category',
+ entityIds: ['ag-grid', 'tanstack-table', 'mui-data-grid'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'forms',
+ title: 'Forms',
+ kind: 'curated-category',
+ entityIds: ['react-hook-form', 'tanstack-form', 'conform'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'virtualization',
+ title: 'Virtualization',
+ kind: 'curated-category',
+ entityIds: ['react-virtualized', 'react-window', 'tanstack-virtual'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'state-management',
+ title: 'State Management',
+ kind: 'curated-category',
+ entityIds: ['redux', 'zustand', 'jotai', 'valtio'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'build-tools',
+ title: 'Build Tools',
+ kind: 'curated-category',
+ entityIds: ['webpack', 'vite', 'rollup', 'esbuild', 'rspack'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'validation',
+ title: 'Validation',
+ kind: 'curated-category',
+ entityIds: ['zod', 'valibot', 'yup'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'frameworks',
+ title: 'Frameworks',
+ kind: 'curated-category',
+ entityIds: ['react', 'vue', 'angular-core', 'svelte', 'solid-js'],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'all-tanstack',
+ title: 'All TanStack Libraries',
+ kind: 'curated-tanstack',
+ entityIds: [
+ 'tanstack-query',
+ 'tanstack-router',
+ 'tanstack-table',
+ 'tanstack-form',
+ 'tanstack-virtual',
+ ],
+ featured: true,
+ public: true,
+ popularComparison: true,
+ },
+ {
+ id: 'javascript-ecosystem-leaders',
+ title: 'JavaScript Ecosystem Leaders',
+ kind: 'curated-benchmark',
+ entityIds: [
+ 'react',
+ 'vue',
+ 'angular-core',
+ 'svelte',
+ 'vite',
+ 'webpack',
+ 'rollup',
+ 'esbuild',
+ 'react-router',
+ 'tanstack-query',
+ 'apollo-client',
+ 'redux',
+ 'zustand',
+ 'react-hook-form',
+ 'zod',
+ ],
+ featured: true,
+ public: true,
+ benchmark: true,
+ },
+]
+```
+
+## Starter Rollups
+
+These are the new reusable grouping layer.
+
+```ts
+export const rollups: NpmRollup[] = [
+ {
+ id: 'tanstack-ecosystem',
+ title: 'TanStack Ecosystem',
+ kind: 'ecosystem',
+ entityIds: [
+ 'tanstack-query',
+ 'tanstack-router',
+ 'tanstack-table',
+ 'tanstack-form',
+ 'tanstack-virtual',
+ ],
+ membershipMode: 'exclusive',
+ color: '#FF4500',
+ public: true,
+ },
+ {
+ id: 'data-fetching-ecosystem',
+ title: 'Data Fetching Ecosystem',
+ kind: 'category',
+ entityIds: ['tanstack-query', 'swr', 'apollo-client', 'trpc-client'],
+ membershipMode: 'overlap',
+ public: true,
+ },
+ {
+ id: 'router-ecosystem',
+ title: 'Router Ecosystem',
+ kind: 'category',
+ entityIds: ['react-router', 'tanstack-router', 'wouter'],
+ membershipMode: 'overlap',
+ public: true,
+ },
+ {
+ id: 'javascript-ecosystem-index',
+ title: 'JavaScript Ecosystem Index',
+ kind: 'benchmark',
+ entityIds: [
+ 'react',
+ 'vue',
+ 'angular-core',
+ 'svelte',
+ 'vite',
+ 'webpack',
+ 'rollup',
+ 'esbuild',
+ 'react-router',
+ 'tanstack-query',
+ 'redux',
+ 'react-hook-form',
+ 'zod',
+ ],
+ membershipMode: 'overlap',
+ public: true,
+ },
+]
+```
+
+Future ecosystem rollups can include:
+
+- `vercel-ecosystem`
+- `remix-ecosystem`
+- `shopify-ecosystem`
+
+Those should be explicit editorial definitions, not guessed from npm scopes.
+
+## Notes On Specific TanStack Entities
+
+### Query
+
+- Roll up `react-query` into `@tanstack/react-query`.
+- This is a clear lineage case.
+
+### Table
+
+- Roll up `react-table` into `@tanstack/react-table`.
+- This is also a clear lineage case.
+
+### Virtual
+
+- Roll up `react-virtual` into `@tanstack/react-virtual`.
+- Clear lineage case.
+
+### Router
+
+- Do not automatically roll `react-location` into `@tanstack/react-router` in v1.
+- They are adjacent and related, but this one is more semantically debatable than Query, Table, or Virtual.
+- Keep this as an explicit later decision if we want lineage continuity there.
+
+### Form
+
+- It may be useful to define separate tracked entities for `@tanstack/form-core` and `@tanstack/react-form` later.
+- For now, a single `TanStack Form` entity is probably fine if the goal is product-level visibility.
+
+## Migration From Existing Popular Comparisons
+
+Recommended path:
+
+1. Create the entity, rollup, and watchlist registry.
+2. Rebuild `getPopularComparisons()` from curated watchlists and rollups marked for that purpose.
+3. Keep route behavior and `packageGroup` format unchanged at first.
+4. Add optional rollup grouping to chart UI later.
+5. Remove duplication once parity looks good.
+
+## Open Decisions
+
+1. How aggressive should we be about rolling up framework adapters into one product-level TanStack entity?
+2. Which rollups should be exclusive versus overlap-friendly?
+3. Should benchmark lists include only `benchmarkEligible` entities or also allow manual exceptions?
+4. Should `JavaScript Ecosystem Leaders` aim for 25, 50, or 100 entities in v1?
+5. Which watchlists and rollups should be exposed publicly on day one versus internal-only at first?
+
+## Immediate Next Steps
+
+- Convert this draft into a real `src/utils/npm-watchlists.ts` module.
+- Add real rollup definitions for ecosystem and benchmark views.
+- Fill out the tracked entity registry beyond the starter set.
+- Rebuild stale popular comparisons from the registry.
+- Draft the first larger benchmark roster separately.
diff --git a/docs/proposals/npm-watchlists-and-weekly-digests.md b/docs/proposals/npm-watchlists-and-weekly-digests.md
new file mode 100644
index 000000000..9abc6e304
--- /dev/null
+++ b/docs/proposals/npm-watchlists-and-weekly-digests.md
@@ -0,0 +1,665 @@
+# Proposal: NPM Watchlists and Weekly Digests
+
+## North Star
+
+Turn TanStack NPM Stats into a durable market map for JavaScript libraries, not just a charting tool.
+
+Users should be able to follow a set of libraries, understand who is actually gaining or losing ground inside that set, and get a concise weekly digest that surfaces meaningful movement without reacting to noisy daily swings.
+
+## Why This Matters
+
+- Raw npm download charts are useful, but they do not answer "who is winning?"
+- Raw download growth is increasingly misleading because the whole ecosystem keeps growing.
+- Users care about cohorts, rankings, trend changes, and share shifts more than isolated download counts.
+- TanStack already has fast comparison UX and historical npm data. This feature turns that into a repeatable product.
+
+## Product Outcome
+
+Add rollups and watchlists that users can explore, compare, and subscribe to by email once a week.
+
+Each digest should answer:
+
+- Which libraries moved up or down?
+- Which libraries gained or lost share?
+- Which crossovers happened?
+- Which trends look sustained instead of noisy?
+
+## Core Product Principles
+
+- `packages -> entities -> rollups -> watchlists` should be the core model.
+- Watchlists are the user-facing saved and subscribed surface.
+- Rollups are reusable editorial groupings for charts, rankings, and ecosystem views.
+- Popular comparisons are just one derived view, not the source of truth.
+- Rankings should be cohort-aware, not framed as vague "global npm rank".
+- Normalization should favor share and relative outperformance, not raw download growth.
+- Long-term rollups must work across legacy package names and package renames.
+- Weekly summaries should highlight meaningful movement, not short-term volatility.
+
+## User Stories
+
+1. As a user, I can subscribe to a curated watchlist like `Data Fetching` or `Build Tools`.
+2. As a user, I can save a custom watchlist from the current `/stats/npm` comparison.
+3. As a user, I can follow a logical library even if its npm history spans multiple package names.
+4. As a user, I can receive a weekly digest showing rank changes, share changes, and notable crossovers.
+5. As a user, I can look back across months or years and see how the watchlist evolved.
+6. As a user, I can compare larger ecosystem rollups like `TanStack` vs `Vercel` vs `Remix`.
+7. As a user, I can plot entities grouped by rollup on charts.
+
+## Product Shape
+
+### 1. Tracked entities
+
+The atomic unit should not be a single npm package. It should be a logical tracked entity.
+
+Example:
+
+```ts
+{
+ id: 'tanstack-query',
+ label: 'TanStack Query',
+ packages: ['@tanstack/react-query', 'react-query'],
+}
+```
+
+This gives us:
+
+- continuity across legacy/current package names
+- stable ranking entities
+- cleaner digest language
+- long-term rollups without losing historical identity
+
+### 2. Rollups
+
+A rollup is a reusable grouped view of tracked entities.
+
+Examples:
+
+- `tanstack-ecosystem`
+- `vercel-ecosystem`
+- `remix-ecosystem`
+- `data-fetching-ecosystem`
+- `router-ecosystem`
+
+Rollups let us:
+
+- compare larger ecosystems on charts
+- group entities visually inside one watchlist
+- create reusable market-map views without copying entity membership everywhere
+- support ecosystem-vs-ecosystem reporting in digests later
+
+### 3. Watchlists
+
+A watchlist is a named saved surface for ranking, digesting, and charting.
+
+A watchlist can contain:
+
+- entities directly
+- rollups
+- or both, depending on the UX we want
+
+Recommended watchlist types:
+
+- Curated category watchlists
+- Curated benchmark watchlists
+- TanStack-specific watchlists
+- Ecosystem watchlists
+- User-created custom watchlists
+
+### 4. Weekly digest
+
+Each watchlist can produce a weekly digest with:
+
+- current rank
+- previous rank
+- rank delta
+- share of watchlist
+- share delta
+- trailing 4-week trend
+- notable crossovers
+- link back to the live chart
+
+Future digest expansions:
+
+- rollup-vs-rollup share changes
+- entity movement inside a rollup
+- ecosystem momentum summaries
+
+## Current Model Draft
+
+This is the current preferred abstraction stack:
+
+- `package`: raw npm package history
+- `entity`: one logical library or product across one or more packages
+- `rollup`: reusable editorial grouping of entities
+- `watchlist`: a saved and subscribable surface for charts, rankings, and digests
+
+Current preferred type direction:
+
+```ts
+export type NpmTrackedEntity = {
+ id: string
+ label: string
+ shortLabel?: string
+ description?: string
+ categories: Array<
+ | 'tanstack'
+ | 'data-fetching'
+ | 'routing'
+ | 'state'
+ | 'table'
+ | 'form'
+ | 'virtualization'
+ | 'testing'
+ | 'styling'
+ | 'build'
+ | 'validation'
+ | 'docs'
+ | 'framework'
+ | 'animation'
+ | 'tooling'
+ | 'database'
+ >
+ color?: string
+ packages: Array<{
+ name: string
+ from?: string
+ to?: string
+ }>
+ lineageStrategy?: 'sum-all' | 'time-bounded'
+ benchmarkEligible?: boolean
+ popularComparisonEligible?: boolean
+ hidden?: boolean
+}
+
+export type NpmRollup = {
+ id: string
+ title: string
+ description?: string
+ kind: 'ecosystem' | 'category' | 'benchmark' | 'editorial'
+ entityIds: string[]
+ membershipMode?: 'exclusive' | 'overlap'
+ color?: string
+ public?: boolean
+}
+
+export type NpmWatchlist = {
+ id: string
+ title: string
+ description?: string
+ kind: 'curated-category' | 'curated-benchmark' | 'curated-tanstack'
+ entityIds?: string[]
+ rollupIds?: string[]
+ featured?: boolean
+ public?: boolean
+ popularComparison?: boolean
+ benchmark?: boolean
+}
+```
+
+Important modeling notes:
+
+- categories belong on entities as `categories: string[]`, not a single `category`
+- watchlists are still the primary curated product surface
+- rollups are the reusable grouping abstraction
+- popular comparisons should be derived from the registry, not hand-maintained independently
+- v1 can mostly use `lineageStrategy: 'sum-all'`
+- the model should still leave room for future time-bounded lineage
+
+## Current Decisions
+
+These are the main decisions made so far and should be preserved in any handoff.
+
+- Do not frame the feature as "global npm rank" in v1.
+- Rank within a defined cohort, watchlist, or benchmark basket.
+- Use trailing 28-day downloads for ranking.
+- Use share of watchlist as the primary normalization lens.
+- Use relative growth vs watchlist median as a secondary lens.
+- Defer anomaly detection.
+- Prefer conservative digest-oriented trend signals over loose anomaly alerts.
+- Build curated entities and watchlists separately from current `popular comparisons`.
+- Include legacy package rollups where lineage is clear.
+- Preserve compatibility with long-term and multi-year rollups.
+- Treat rollups as first-class because ecosystem-vs-ecosystem views are valuable.
+- Allow entities to belong to multiple categories.
+- Allow some rollups to overlap and some to be exclusive.
+
+## Lineage Decisions So Far
+
+These are the explicit lineage calls already discussed.
+
+- Roll up `react-query` into `@tanstack/react-query`.
+- Roll up `react-table` into `@tanstack/react-table`.
+- Roll up `react-virtual` into `@tanstack/react-virtual`.
+- Do not automatically roll `react-location` into `@tanstack/react-router` in v1.
+- TanStack Form may eventually need separate entity treatment for `@tanstack/form-core` and `@tanstack/react-form`, but one product-level entity is acceptable for v1.
+
+## Starter Registry Direction
+
+These are the concrete examples already drafted and should be treated as the current starting point, not final production data.
+
+Starter entities:
+
+- `tanstack-query`: `@tanstack/react-query` + `react-query`
+- `swr`: `swr`
+- `apollo-client`: `@apollo/client`
+- `trpc-client`: `@trpc/client`
+- `tanstack-router`: `@tanstack/react-router`
+- `react-router`: `react-router`
+- `wouter`: `wouter`
+- `tanstack-table`: `@tanstack/react-table` + `react-table`
+- `ag-grid`: `ag-grid-community` + `ag-grid-enterprise`
+- `mui-data-grid`: `@mui/x-data-grid` + `mui-datatables`
+- `tanstack-form`: `@tanstack/form-core` + `@tanstack/react-form`
+- `react-hook-form`: `react-hook-form`
+- `conform`: `@conform-to/dom`
+- `tanstack-virtual`: `@tanstack/react-virtual` + `react-virtual`
+- `react-window`: `react-window`
+- `react-virtualized`: `react-virtualized`
+- `redux`: `redux`
+- `zustand`: `zustand`
+- `jotai`: `jotai`
+- `valtio`: `valtio`
+- `vite`: `vite`
+- `webpack`: `webpack`
+- `rollup`: `rollup`
+- `esbuild`: `esbuild`
+- `rspack`: `@rspack/core`
+- `zod`: `zod`
+- `valibot`: `valibot`
+- `yup`: `yup`
+- `react`: `react`
+- `vue`: `vue`
+- `angular-core`: `@angular/core`
+- `svelte`: `svelte`
+- `solid-js`: `solid-js`
+
+Starter watchlists:
+
+- `data-fetching`
+- `routing-react`
+- `tables-data-grids`
+- `forms`
+- `virtualization`
+- `state-management`
+- `build-tools`
+- `validation`
+- `frameworks`
+- `all-tanstack`
+- `javascript-ecosystem-leaders`
+
+Starter rollups:
+
+- `tanstack-ecosystem`
+- `data-fetching-ecosystem`
+- `router-ecosystem`
+- `javascript-ecosystem-index`
+
+Future rollups already discussed:
+
+- `vercel-ecosystem`
+- `remix-ecosystem`
+- `shopify-ecosystem`
+
+## Rollup Semantics
+
+Rollups should be explicit editorial definitions, not inferred automatically from npm scopes or package naming.
+
+Two intended rollup modes:
+
+- `exclusive`: best for aggregate comparisons where double counting would distort the view
+- `overlap`: best for discovery, category views, and flexible grouped charting
+
+Examples:
+
+- `tanstack-ecosystem` should likely be `exclusive`
+- category-style rollups like `router-ecosystem` can be `overlap`
+
+## Popular Comparisons Migration
+
+The current `popular comparisons` file is useful but not a good source of truth.
+
+Migration direction:
+
+1. Build the entity, rollup, and watchlist registry.
+2. Rebuild `getPopularComparisons()` from curated watchlists and rollups flagged for chart use.
+3. Keep the existing route behavior and `packageGroup` output shape unchanged at first.
+4. Add rollup-aware chart grouping later.
+5. Remove duplicated manual comparison definitions once parity looks good.
+
+## Handoff Notes
+
+If another agent picks this up, these are the highest-value next steps already implied by the current plan.
+
+1. Convert the draft model into a real `src/utils/npm-watchlists.ts` module.
+2. Expand the entity registry beyond the starter examples.
+3. Define the first real ecosystem rollups.
+4. Decide the first public benchmark basket, especially `JavaScript Ecosystem Leaders`.
+5. Replace stale `popular comparisons` with registry-derived definitions.
+6. Design the DB schema around entities, rollups, watchlists, subscriptions, and weekly snapshots.
+
+## Registry Strategy
+
+### Entities, rollups, and watchlists should become a first-class registry
+
+Current `popular comparisons` are useful, but they are not sufficient as the long-term source of truth.
+
+Problems with using them directly:
+
+- some are out of date
+- some are sized for chart exploration, not ongoing tracking
+- some do not include legacy package rollups
+- some are too small or too editorial for ranking semantics
+
+We should create a separate curated registry for entities, rollups, and watchlists and let `popular comparisons` derive from it where useful.
+
+Suggested source file:
+
+- `src/utils/npm-watchlists.ts`
+
+### Why rollups matter
+
+Rollups are what let this feature graduate from simple package comparison into a real market map.
+
+Examples:
+
+- compare `TanStack` vs `Vercel` vs `Remix`
+- plot all router-related entities and color them by ecosystem rollup
+- compare a product rollup against its category peers
+- track how an ecosystem's aggregate share changes over time
+
+### Starter watchlist categories
+
+Curated category watchlists:
+
+- Data Fetching
+- Routing
+- Tables and Data Grids
+- Forms
+- State Management
+- Virtualization
+- Testing
+- Styling
+- Build Tools
+- Validation and Schema
+- Motion and Animation
+- Meta-frameworks
+
+Curated benchmark watchlists:
+
+- JavaScript Ecosystem Leaders
+- React Ecosystem Leaders
+- JavaScript Infra Index
+- Frontend Foundation 50
+
+TanStack watchlists:
+
+- All TanStack Libraries
+- TanStack Query Ecosystem
+- TanStack Router Ecosystem
+- TanStack Table Ecosystem
+
+Ecosystem rollups and watchlists:
+
+- TanStack Ecosystem
+- Vercel Ecosystem
+- Remix Ecosystem
+- Router Ecosystem
+- Data Fetching Ecosystem
+
+## Legacy Package Rules
+
+Legacy packages should usually roll into the same tracked entity when they represent the same product lineage.
+
+Examples:
+
+- `react-query` + `@tanstack/react-query`
+- `react-table` + `@tanstack/react-table`
+- `react-virtual` + `@tanstack/react-virtual`
+
+Do not assume every rename or adjacent product belongs in the same lineage forever. The model should allow future time-aware lineage rules if simple summing becomes misleading.
+
+V1 rule:
+
+- tracked entities use a flat array of package names and simple summed downloads
+
+Future rule if needed:
+
+- tracked entities can support time-bounded package membership
+
+## Ranking and Normalization
+
+Raw download growth is not a good primary signal because the entire ecosystem is growing.
+
+### Primary ranking metric
+
+Use trailing 28-day downloads for rank within a watchlist.
+
+Why 28-day:
+
+- smoother than daily or weekly
+- still responsive enough for weekly digests
+- less sensitive to npm reporting noise
+
+### Primary normalization metric: share of watchlist
+
+```txt
+share_of_watchlist = entity_28d_downloads / sum(all_watchlist_entity_28d_downloads)
+```
+
+This should be the main lens in digests because it makes leaders and laggards visible even when the whole cohort is growing.
+
+### Secondary normalization metric: relative growth vs cohort
+
+```txt
+relative_growth = entity_growth_rate - median_growth_rate_of_watchlist
+```
+
+This helps answer whether a library is outperforming or underperforming peers.
+
+### Optional tertiary benchmark: ecosystem index
+
+Do not use a raw sum of giant packages as the main baseline.
+
+If we add an ecosystem benchmark, it should come from a stable curated basket like `JavaScript Ecosystem Leaders` and use a median or trimmed-mean growth factor rather than raw weighted sum.
+
+### Digest metrics to show in v1
+
+- rank
+- rank delta
+- share of watchlist
+- share delta
+- trailing 4-week trend
+- crossover events
+
+## Trend Detection
+
+Avoid generic "anomaly detection" in v1.
+
+The data is too noisy and npm has known reporting weirdness. We already correct obvious outliers and zero-day anomalies in the stats pipeline.
+
+If we surface trend change signals, they should be conservative and digest-oriented.
+
+Suggested v1 notable movement rules:
+
+- rank changed by at least 1
+- share moved by a meaningful threshold
+- one entity crossed another and stayed ahead for at least one full digest period
+- growth outperformed the cohort median by a meaningful margin
+
+Possible later signals:
+
+- sustained acceleration over 4 weeks vs prior 8 to 12 weeks
+- sustained deceleration over 4 weeks vs prior 8 to 12 weeks
+- held rank breakout after 2 consecutive weeks
+
+## Long-Term Rollups
+
+This feature must support multi-year rollups.
+
+The current architecture is already favorable:
+
+- npm history is cached as year-based daily chunks
+- historical chunks are immutable
+- package groups already support rollups across multiple packages
+
+What we need to preserve:
+
+- tracked entities, not single-package rows
+- reusable rollups on top of tracked entities
+- raw historical chunks as source of truth
+- derived weekly or monthly snapshots for cheap leaderboard queries
+
+Recommended derived data:
+
+- weekly watchlist snapshots for digest generation and rank history
+- optional monthly snapshots for faster long-range reporting
+
+This keeps the system flexible:
+
+- raw chunks allow recomputation when formulas change
+- snapshots keep digests and rank-history queries cheap
+- rollups can be recalculated without changing the raw source data
+
+### Rollup views to support later
+
+- yearly rollup trend lines
+- rank history by entity within a rollup
+- ecosystem-vs-ecosystem comparisons
+- grouped charts where entities are colored or faceted by rollup
+
+## UX Entry Points
+
+### `/stats/npm`
+
+- `Save this comparison`
+- `Follow this watchlist`
+- `Subscribe to weekly digest`
+
+### Library-specific npm stats pages
+
+- `Follow this library`
+- `Add to watchlist`
+
+### Account area
+
+- My watchlists
+- Subscriptions
+- Digest frequency
+- Pause or unsubscribe
+
+## Data Model Direction
+
+Suggested tables:
+
+- `npm_tracked_entities`
+- `npm_tracked_entity_packages`
+- `npm_rollups`
+- `npm_rollup_entities`
+- `npm_watchlists`
+- `npm_watchlist_items`
+- `npm_watchlist_subscriptions`
+- `npm_watchlist_weekly_snapshots`
+- `npm_digest_sends`
+
+Notes:
+
+- tracked entities are the canonical source for rollups and labels
+- rollups reference tracked entities
+- watchlists can reference tracked entities, rollups, or both
+- weekly snapshots are required for stable digest generation and historical ranking views
+- digest send records help with idempotency and auditability
+
+## Implementation Phases
+
+### Phase 1. Curated registry
+
+- Define tracked entities, rollups, and curated watchlists in code
+- Include legacy package rollups where appropriate
+- Refresh and replace stale `popular comparisons`
+- Establish one larger benchmark watchlist like `JavaScript Ecosystem Leaders`
+
+### Phase 2. Snapshot pipeline
+
+- Compute weekly watchlist snapshots from historical npm data
+- Store rank, share, and trailing trend fields
+- Make snapshot generation idempotent
+
+### Phase 3. User-facing watchlists
+
+- Allow signed-in users to save comparisons as custom watchlists
+- Allow subscription management from account surfaces
+- Allow subscription from stats pages
+
+### Phase 4. Weekly digests
+
+- Generate digest content from weekly snapshots
+- Send through Resend
+- Include unsubscribe and pause controls
+
+### Phase 5. Trend signals and benchmark refinement
+
+- Add conservative trend-change detection
+- Add ecosystem index if the curated benchmark proves stable and useful
+
+## Suggested Implementation Order
+
+1. Build the curated tracked-entity and watchlist registry.
+2. Add reusable rollups for ecosystems and category-level groupings.
+3. Replace or derive `popular comparisons` from the new registry.
+4. Add database tables for tracked entities, rollups, watchlists, subscriptions, and weekly snapshots.
+5. Build the weekly snapshot job on top of existing historical npm chunks.
+6. Expose watchlists and rollup grouping in UI without email first.
+7. Add weekly digest generation and delivery.
+8. Add rank history and long-range watchlist views.
+9. Add conservative trend signals only after real snapshot data exists.
+
+## Success Criteria
+
+- Users can subscribe to curated watchlists and custom watchlists.
+- Users can compare major ecosystem rollups clearly.
+- Digests clearly show rank movement and share movement.
+- Rankings are stable enough to feel trustworthy week to week.
+- Legacy package history rolls up cleanly into one logical entity.
+- Multi-year watchlist history remains queryable and understandable.
+- We can explain the ranking math in plain English.
+
+## Non-Goals For V1
+
+- claiming true global npm rank across the whole registry
+- real-time alerts
+- daily digest spam
+- loose anomaly detection with low confidence
+- overfitting the system to every one-off package rename
+
+## Open Questions
+
+1. Which curated watchlists should ship first?
+2. How large should `JavaScript Ecosystem Leaders` be?
+3. Which legacy package transitions deserve permanent lineage rollups?
+4. Which rollups should be exclusive versus allowed to overlap?
+5. Should custom watchlists allow raw package groups, tracked entities, rollups, or all three?
+6. Should digests be weekly only in v1, or should monthly be supported from day one?
+7. Do we want one digest per watchlist or one combined digest across all subscriptions?
+
+## Progress
+
+- [ ] Define tracked entity model
+- [ ] Define rollup model
+- [ ] Draft curated watchlist registry
+- [ ] Draft curated ecosystem rollups
+- [ ] Audit and refresh current popular comparisons
+- [ ] Define lineage rules for legacy package rollups
+- [ ] Design DB schema
+- [ ] Build weekly snapshot job
+- [ ] Build watchlist UI surfaces
+- [ ] Build subscription management
+- [ ] Build weekly digest generation
+- [ ] Build email delivery and unsubscribe flow
+- [ ] Add rank history views
+- [ ] Evaluate trend signals after snapshot data accumulates
+
+## Notes
+
+- Existing npm stats infrastructure already gives us a strong foundation: historical daily chunks, package grouping, outlier correction, and email transport.
+- The biggest risk is product semantics, not raw implementation difficulty.
+- The feature will feel credible only if watchlists are curated well and ranking math stays easy to explain.
diff --git a/package.json b/package.json
index 2dcef0cd8..2a9acabe6 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"type": "module",
"scripts": {
"dev": "pnpm run with-env vite dev",
- "with-env": "dotenv -e .env -e .env.local",
+ "with-env": "dotenv -e .env.local",
"dev:frontend": "pnpm run with-env vite dev",
"build": "vite build",
"start": "vite start",
@@ -44,13 +44,14 @@
"@sentry/browser": "^10.47.0",
"@sentry/node": "^10.47.0",
"@sentry/tanstackstart-react": "^10.47.0",
+ "@shopify/hydrogen-react": "^2026.4.0",
"@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.2.2",
- "@tanstack/ai": "^0.10.0",
- "@tanstack/ai-anthropic": "^0.7.2",
- "@tanstack/ai-client": "^0.7.7",
- "@tanstack/ai-openai": "^0.7.3",
- "@tanstack/create": "^0.63.2",
+ "@tanstack/ai": "^0.10.2",
+ "@tanstack/ai-anthropic": "^0.7.3",
+ "@tanstack/ai-client": "^0.7.9",
+ "@tanstack/ai-openai": "^0.7.4",
+ "@tanstack/create": "^0.63.4",
"@tanstack/pacer": "^0.20.1",
"@tanstack/react-hotkeys": "^0.9.1",
"@tanstack/react-pacer": "^0.21.1",
@@ -65,7 +66,7 @@
"@uploadthing/react": "^7.3.3",
"@visx/hierarchy": "^3.12.0",
"@vitejs/plugin-react": "^6.0.1",
- "@vitejs/plugin-rsc": "^0.5.23",
+ "@vitejs/plugin-rsc": "^0.5.24",
"@webcontainer/api": "^1.6.1",
"@xstate/react": "^6.1.0",
"algoliasearch": "^5.50.0",
@@ -120,8 +121,8 @@
"@playwright/test": "^1.59.0",
"@shikijs/transformers": "^4.0.2",
"@tanstack/devtools-vite": "^0.6.0",
- "@tanstack/react-devtools": "^0.10.1",
- "@tanstack/react-query-devtools": "^5.96.2",
+ "@tanstack/react-devtools": "^0.10.2",
+ "@tanstack/react-query-devtools": "^5.99.0",
"@types/hast": "^3.0.4",
"@types/node": "^25.5.0",
"@types/pg": "^8.20.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7ecc71c1d..00d1ec4d7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -31,7 +31,7 @@ importers:
version: 5.1.5
'@netlify/vite-plugin-tanstack-start':
specifier: ^1.3.2
- version: 1.3.2(@tanstack/react-start@1.167.30(@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ version: 1.3.4(@tanstack/react-start@1.167.30(@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@observablehq/plot':
specifier: ^0.6.17
version: 0.6.17
@@ -65,6 +65,9 @@ importers:
'@sentry/tanstackstart-react':
specifier: ^10.47.0
version: 10.47.0(react@19.2.3)(rollup@4.53.3)
+ '@shopify/hydrogen-react':
+ specifier: ^2026.4.0
+ version: 2026.4.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.183.2)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@tailwindcss/typography':
specifier: ^0.5.19
version: 0.5.19(tailwindcss@4.2.2)
@@ -72,20 +75,20 @@ importers:
specifier: ^4.2.2
version: 4.2.2(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@tanstack/ai':
- specifier: ^0.10.0
- version: 0.10.0
+ specifier: ^0.10.2
+ version: 0.10.2
'@tanstack/ai-anthropic':
- specifier: ^0.7.2
- version: 0.7.2(@tanstack/ai@0.10.0)(zod@4.3.6)
+ specifier: ^0.7.3
+ version: 0.7.3(@tanstack/ai@0.10.2)(zod@4.3.6)
'@tanstack/ai-client':
- specifier: ^0.7.7
- version: 0.7.7
+ specifier: ^0.7.9
+ version: 0.7.9
'@tanstack/ai-openai':
- specifier: ^0.7.3
- version: 0.7.3(@tanstack/ai-client@0.7.7)(@tanstack/ai@0.10.0)(ws@8.20.0)(zod@4.3.6)
+ specifier: ^0.7.4
+ version: 0.7.4(@tanstack/ai-client@0.7.9)(@tanstack/ai@0.10.2)(ws@8.20.0)(zod@4.3.6)
'@tanstack/create':
- specifier: ^0.63.2
- version: 0.63.2(tslib@2.8.1)
+ specifier: ^0.63.4
+ version: 0.63.4(tslib@2.8.1)
'@tanstack/pacer':
specifier: ^0.20.1
version: 0.20.1
@@ -97,7 +100,7 @@ importers:
version: 0.21.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@tanstack/react-query':
specifier: ^5.96.2
- version: 5.96.2(react@19.2.3)
+ version: 5.99.0(react@19.2.3)
'@tanstack/react-router':
specifier: 1.168.17
version: 1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -106,10 +109,10 @@ importers:
version: 1.166.13(@tanstack/react-router@1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.168.14)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@tanstack/react-router-ssr-query':
specifier: 1.166.11
- version: 1.166.11(@tanstack/query-core@5.96.2)(@tanstack/react-query@5.96.2(react@19.2.3))(@tanstack/react-router@1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.168.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ version: 1.166.11(@tanstack/query-core@5.99.0)(@tanstack/react-query@5.99.0(react@19.2.3))(@tanstack/react-router@1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.168.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@tanstack/react-start':
specifier: 1.167.30
- version: 1.167.30(@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ version: 1.167.30(@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@tanstack/react-start-server':
specifier: 1.166.35
version: 1.166.35(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -129,8 +132,8 @@ importers:
specifier: ^6.0.1
version: 6.0.1(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@vitejs/plugin-rsc':
- specifier: ^0.5.23
- version: 0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ specifier: ^0.5.24
+ version: 0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@webcontainer/api':
specifier: ^1.6.1
version: 1.6.1
@@ -289,11 +292,11 @@ importers:
specifier: ^0.6.0
version: 0.6.0(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@tanstack/react-devtools':
- specifier: ^0.10.1
- version: 0.10.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)
+ specifier: ^0.10.2
+ version: 0.10.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)
'@tanstack/react-query-devtools':
- specifier: ^5.96.2
- version: 5.96.2(@tanstack/react-query@5.96.2(react@19.2.3))(react@19.2.3)
+ specifier: ^5.99.0
+ version: 5.99.0(@tanstack/react-query@5.99.0(react@19.2.3))(react@19.2.3)
'@types/hast':
specifier: ^3.0.4
version: 3.0.4
@@ -1234,6 +1237,12 @@ packages:
'@floating-ui/utils@0.2.11':
resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
+ '@google/model-viewer@4.2.0':
+ resolution: {integrity: sha512-RjpAI5cLs9CdvPcMRsOs8Bea/lNmGTTyaPyl16o9Fv6Qn8VSpgBMmXFr/11yb0hTrsojp2dOACEcY77R8hVUVA==}
+ engines: {node: '>=6.0.0'}
+ peerDependencies:
+ three: ^0.182.0
+
'@hono/node-server@1.19.12':
resolution: {integrity: sha512-txsUW4SQ1iilgE0l9/e9VQWmELXifEFvmdA1j6WFh/aFPj99hIntrSsq/if0UWyGVkmrRPKA1wCeP+UCr1B9Uw==}
engines: {node: '>=18.14.1'}
@@ -1552,6 +1561,12 @@ packages:
peerDependencies:
tslib: '2'
+ '@lit-labs/ssr-dom-shim@1.5.1':
+ resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==}
+
+ '@lit/reactive-element@2.1.2':
+ resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==}
+
'@mapbox/node-pre-gyp@2.0.3':
resolution: {integrity: sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg==}
engines: {node: '>=18'}
@@ -1642,16 +1657,16 @@ packages:
engines: {node: '>=18.14.0'}
hasBin: true
- '@netlify/db-dev@0.7.0':
- resolution: {integrity: sha512-xB2ciUJsWFw34DtMMmAh19qGUJy1N5mFAi6yYFFqeBlnd8StSxoUblXcqVZcQJLXm68OAxSxkfGf1qUucIDyMA==}
+ '@netlify/database-dev@0.8.0':
+ resolution: {integrity: sha512-q53dx7QgLMMN3vKRFvX/guDOPXscYaF4qtHoG0JYZorC0vcJagw6s3nV8cNob9sCjA3Tj/BNf7MnWwOSF0E1Cw==}
engines: {node: '>=20.6.1'}
'@netlify/dev-utils@4.4.3':
resolution: {integrity: sha512-VkMD8YACshR6pHgoub6nikkI+SQVdhjVvLsOK2ZSpN2wMlDHdsD8uRjESfzv/yYfq5jlsGskfx1cf1FUurWt9A==}
engines: {node: ^18.14.0 || >=20}
- '@netlify/dev@4.16.4':
- resolution: {integrity: sha512-IhyLtiEgOFCwpW/qYqCnY0LSwmw4PNgu4hJYIddLpIr/RPHAsDN+Ni3hEEW9RH8wkmvYmbc+xtxHPQZdyDUSgg==}
+ '@netlify/dev@4.17.0':
+ resolution: {integrity: sha512-DumVB+3VdIXXGWKrQVM4ouwahhtajtfC1IU8bDt472P3+zDoceai3FYrTfBq4LbWq6ojZXGqf8XWsJHO6rd/0A==}
engines: {node: '>=20.6.1'}
'@netlify/edge-bundler@14.9.19':
@@ -1669,14 +1684,18 @@ packages:
resolution: {integrity: sha512-xkVcTcpAuQKAY5GXKOjPTIct5Mz53NPHXOasggA+LTAxDDV4ohqSM8BIaXh1SgbcniHZyFhBqhc5hxZ+fFz5bQ==}
engines: {node: '>=18.0.0'}
- '@netlify/functions-dev@1.2.4':
- resolution: {integrity: sha512-Ejrb+1HL11zgVgaaMHWukH4hOXFy3FUtue8hD5rgBiLWeGp03uOlGehmbRz47FXvGBMK7Z4t7HZRZU/vpaN5+g==}
+ '@netlify/functions-dev@1.2.5':
+ resolution: {integrity: sha512-IRskgi6cexUkFtU0Da/OiiUyvyKOzxNsf16HN9iRIGGZUQ4AcyXwJPqVsquP9jHluY3Ck8bDsnxXnpOsaT4ENg==}
engines: {node: '>=20.6.1'}
'@netlify/functions@5.1.5':
resolution: {integrity: sha512-mhTl6x3TWoRwNgz8HZ9zvSR9OHB/hDEA6VinBmWY5ubgycKNCerf6XyFaFnujH2Ygx3c32yg6QOOr1v9y8euug==}
engines: {node: '>=18.0.0'}
+ '@netlify/functions@5.2.0':
+ resolution: {integrity: sha512-Pj93qeQd1tkQ5xm9gWJZmBf/1riLYqYHc0OzFukrJomrj82Ott53Rr/Q88H1ms5cF+P5QXRKWmA2JSxSybKfjA==}
+ engines: {node: '>=18.0.0'}
+
'@netlify/headers-parser@9.0.3':
resolution: {integrity: sha512-KNzC9RaKDwJVS44iTK6JxNA6LeXH0PUw0pLktWpmMVI/0FR98bvxaHcAisjHqbThAjxL9QjL1UZh0KzHCkxpNQ==}
engines: {node: '>=18.14.0'}
@@ -1725,8 +1744,8 @@ packages:
resolution: {integrity: sha512-yD20EizHJDQxajJ66Vo8RTwLwR2jMNVxufPG8MHd2AScX8jW4z0VPnnJHArq2GYPFTFZRHmiAhDrXr5m8zof6w==}
engines: {node: ^18.14.0 || >=20}
- '@netlify/vite-plugin-tanstack-start@1.3.2':
- resolution: {integrity: sha512-Dg3CfK7O+P52sX+iQVLTQNH6+7DfhBK76el8TYAiQLfdc7j5tJgWwXyhMtrBpaylGOdqbYwZfVFBI+e8asDsPg==}
+ '@netlify/vite-plugin-tanstack-start@1.3.4':
+ resolution: {integrity: sha512-MjYTiVTkD2J1dPMU6eKAMWPZvfOJZm5aM7065YWQVOJHidsKvSYg5fuI4h1vYZmQVUJwOhJFG+6rv4F9S3ZZWQ==}
engines: {node: ^22.12.0 || >=24.0.0}
peerDependencies:
'@tanstack/react-start': '>=1.132.0'
@@ -1738,8 +1757,8 @@ packages:
'@tanstack/solid-start':
optional: true
- '@netlify/vite-plugin@2.11.2':
- resolution: {integrity: sha512-R5p/qWdUsbg2QBwCLcJuCwBPYog3VH6yezXc18rI2I+OKrdg+kzv35ZE2QkvC1junLITqbaIKYx8xYykkohQkw==}
+ '@netlify/vite-plugin@2.11.4':
+ resolution: {integrity: sha512-Q1hbuL6f4hghao17Dk3dGIE20oBzvxACdCxox2FKYHR0gypcq7aJW+uoueTkcZuB1ZE7K5xSAQjmKRjOiaCV1g==}
engines: {node: ^20.6.1 || >=22}
peerDependencies:
vite: ^5 || ^6 || ^7 || ^8
@@ -2925,8 +2944,8 @@ packages:
'@rolldown/pluginutils@1.0.0-rc.12':
resolution: {integrity: sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==}
- '@rolldown/pluginutils@1.0.0-rc.13':
- resolution: {integrity: sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==}
+ '@rolldown/pluginutils@1.0.0-rc.15':
+ resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==}
'@rolldown/pluginutils@1.0.0-rc.7':
resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==}
@@ -3247,6 +3266,13 @@ packages:
'@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+ '@shopify/hydrogen-react@2026.4.0':
+ resolution: {integrity: sha512-RXtMkkZAJFv43BcNR2CNIkVbUqT28nU9uzJ05lewkX9yq2C7Vmf5AC2jLov+tevMYFqTPOQRiZYuxtym4UnKSA==}
+ peerDependencies:
+ react: ^18.3.1 || ~19.0.3 || ~19.1.4 || ^19.2.3
+ react-dom: ^18.3.1 || ~19.0.3 || ~19.1.4 || ^19.2.3
+ vite: ^5.1.0 || ^6.2.1
+
'@sindresorhus/merge-streams@4.0.0':
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
engines: {node: '>=18'}
@@ -3400,33 +3426,33 @@ packages:
peerDependencies:
vite: ^5.2.0 || ^6 || ^7 || ^8
- '@tanstack/ai-anthropic@0.7.2':
- resolution: {integrity: sha512-ZV01BPuplBOhnnzPpFqoPBWLQNGFSBPkIUaE23NqGrjzyKfeWed4mkTl/Q5cg2rF1VDTS8iOYXWME206kHuiPA==}
+ '@tanstack/ai-anthropic@0.7.3':
+ resolution: {integrity: sha512-toWuZSghJDo+eCNyjYJmumeX7prAOjiOfb1sPFQiJ81IExFUU731IejFUzM5evXuoUrXhNI1elPVOC3IYUlwHg==}
peerDependencies:
- '@tanstack/ai': ^0.10.0
+ '@tanstack/ai': ^0.10.1
zod: ^4.0.0
- '@tanstack/ai-client@0.7.7':
- resolution: {integrity: sha512-Z4BcVgtYMaeSp46UcRzKWvG2SYC3M0VW2jYaWGKRrTouQ71+3C0DREZr8MYZr1gAkCCcQqqWPejKkYdJ7+cLSQ==}
+ '@tanstack/ai-client@0.7.9':
+ resolution: {integrity: sha512-bzB/G08q4fQ4e8EwnesDrZWDVNxggVN4gOG+Twtlzxze18i46BFH0t5PjlFLL6WWCG4VGoRj+ocZ22ebrz+KUA==}
- '@tanstack/ai-event-client@0.2.0':
- resolution: {integrity: sha512-1O7PbBlSo0gCrv4/bmOvnemZ6Cvf+kZmHqug19JEz8Bj4/anup3GkwvKBk8XzEvPIB+vQb4GL9TLN4Tfo6ZCkA==}
+ '@tanstack/ai-event-client@0.2.2':
+ resolution: {integrity: sha512-Dcv2eeVyTDXbv7IPFTl7o1Vy12V06pjSnQLPoHvydYkJGkdD+vvmUFrmtGQiBq/FgW6GT7pPpVPyTW2DJVOEeA==}
peerDependencies:
- '@tanstack/ai': 0.10.0
+ '@tanstack/ai': 0.10.2
- '@tanstack/ai-openai@0.7.3':
- resolution: {integrity: sha512-xdxTR7E/BzeQcFte/chDA//2WpZQqDQF4op1TgKNoaTqffW9+JMlSubaZbMkawtJoImVCGjZoPVkUfb8aRldNA==}
+ '@tanstack/ai-openai@0.7.4':
+ resolution: {integrity: sha512-AYPLvrnWbtqj185MtTT9Mo5GWbZQOwQwtfgZCxAslctxv0nL0lQInPEQAkwcMFle+qbadJB8BhJqTnRBAsW+Tg==}
peerDependencies:
- '@tanstack/ai': ^0.10.0
- '@tanstack/ai-client': ^0.7.7
+ '@tanstack/ai': ^0.10.1
+ '@tanstack/ai-client': ^0.7.8
zod: ^4.0.0
- '@tanstack/ai@0.10.0':
- resolution: {integrity: sha512-b1GDenJs2udQfjFMnAWZ6WX9RLg04O9wC85V4cSD8phuVMJscs+Qp0UkNj7FTc+V1ggqf4Pz1jLFfqjLO2z3mg==}
+ '@tanstack/ai@0.10.2':
+ resolution: {integrity: sha512-uy9swoOXgDltFZcaKc9YkRD22fndK0NhJAtOs1vCaugSYOjgOsfT0jnkZ9kswVn+OPXQxiXKQ9PSNKIoKKSP8g==}
engines: {node: '>=18'}
- '@tanstack/create@0.63.2':
- resolution: {integrity: sha512-DDVQhO3Cv9Wulz2h8I17JDO0YkRltg0M54Jn8g3SAwK5oiMX4FcY7xeomlS87B6p3yJJFuv4KaNTpQfNnAbYWg==}
+ '@tanstack/create@0.63.4':
+ resolution: {integrity: sha512-LpCU+WrCXKJniyz2OIHmesqEsTQFRTcB0A8+1yiN7Idj8sUjFoTV1YYJJLzrlGUwAGM42IZMOmWt1EgBlPaNRw==}
'@tanstack/devtools-client@0.0.6':
resolution: {integrity: sha512-f85ZJXJnDIFOoykG/BFIixuAevJovCvJF391LPs6YjBAPhGYC50NWlx1y4iF/UmK5/cCMx+/JqI5SBOz7FanQQ==}
@@ -3454,8 +3480,8 @@ packages:
peerDependencies:
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
- '@tanstack/devtools@0.11.1':
- resolution: {integrity: sha512-g3nHgVP76kT9190d6O32AjANoEnujLEB+51PDtBzlah8hvKeEygK53cunN+HXhjlfhM4PoOCi8/B96cdJVSnLg==}
+ '@tanstack/devtools@0.11.2':
+ resolution: {integrity: sha512-K8+tsBx+ptTLqqd4dOF10B6laj1g+XYImqYZL9n0jBINGaT+sOf17PKV9pbBt8kdbZeIGsHaJ5OZWCyZoHqN4A==}
engines: {node: '>=18'}
hasBin: true
peerDependencies:
@@ -3473,14 +3499,14 @@ packages:
resolution: {integrity: sha512-ZNQ1bIL6eUXVKdic0tiImvBVkWrg/IoSK6VIacTrO3d3HAGnd70qFJNJagR/YOJIOw4EKGWnodwpYZkN1pWuVQ==}
engines: {node: '>=18'}
- '@tanstack/query-core@5.96.2':
- resolution: {integrity: sha512-hzI6cTVh4KNRk8UtoIBS7Lv9g6BnJPXvBKsvYH1aGWvv0347jT3BnSvztOE+kD76XGvZnRC/t6qdW1CaIfwCeA==}
+ '@tanstack/query-core@5.99.0':
+ resolution: {integrity: sha512-3Jv3WQG0BCcH7G+7lf/bP8QyBfJOXeY+T08Rin3GZ1bshvwlbPt7NrDHMEzGdKIOmOzvIQmxjk28YEQX60k7pQ==}
- '@tanstack/query-devtools@5.96.2':
- resolution: {integrity: sha512-vBTB1Qhbm3nHSbEUtQwks/EdcAtFfEapr1WyBW4w2ExYKuXVi3jIxUIHf5MlSltiHuL7zNyUuanqT/7sI2sb6g==}
+ '@tanstack/query-devtools@5.99.0':
+ resolution: {integrity: sha512-m4ufXaJ8FjWXw7xDtyzE/6fkZAyQFg9WrbMrUpt8ZecRJx58jiFOZ2lxZMphZdIpAnIeto/S8stbwLKLusyckQ==}
- '@tanstack/react-devtools@0.10.1':
- resolution: {integrity: sha512-cvcd0EqN7Q2LYatQXxFhOkEa9RUQXZlhXnM1mwuibxmyRX+CMyohUZcgjodtIfgh+RT0Pmvt49liTdZby5ovZw==}
+ '@tanstack/react-devtools@0.10.2':
+ resolution: {integrity: sha512-1BmZyxOrI5SqmRJ5MgkYZNNdnlLsJxQRI2YgorrAvcF2MxK6x5RcuStvD8+YlXoMw3JtNukPxoITirKAnKYDQA==}
engines: {node: '>=18'}
peerDependencies:
'@types/react': '>=16.8'
@@ -3502,14 +3528,14 @@ packages:
react: '>=16.8'
react-dom: '>=16.8'
- '@tanstack/react-query-devtools@5.96.2':
- resolution: {integrity: sha512-nTFKLGuTOFvmFRvcyZ3ArWC/DnMNPoBh6h/2yD6rsf7TCTJCQt+oUWOp2uKPTIuEPtF/vN9Kw5tl5mD1Kbposw==}
+ '@tanstack/react-query-devtools@5.99.0':
+ resolution: {integrity: sha512-CqqX7LCU9yOfCY/vBURSx2YSD83ryfX+QkfkaKionTfg1s2Hdm572Ro99gW3QPoJjzvsj1HM4pnN4nbDy3MXKA==}
peerDependencies:
- '@tanstack/react-query': ^5.96.2
+ '@tanstack/react-query': ^5.99.0
react: ^18 || ^19
- '@tanstack/react-query@5.96.2':
- resolution: {integrity: sha512-sYyzzJT4G0g02azzJ8o55VFFV31XvFpdUpG+unxS0vSaYsJnSPKGoI6WdPwUucJL1wpgGfwfmntNX/Ub1uOViA==}
+ '@tanstack/react-query@5.99.0':
+ resolution: {integrity: sha512-OY2bCqPemT1LlqJ8Y2CUau4KELnIhhG9Ol3ZndPbdnB095pRbPo1cHuXTndg8iIwtoHTgwZjyaDnQ0xD0mYwAw==}
peerDependencies:
react: ^18 || ^19
@@ -3827,8 +3853,8 @@ packages:
'@types/mysql@2.15.27':
resolution: {integrity: sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==}
- '@types/node@22.19.15':
- resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==}
+ '@types/node@22.19.17':
+ resolution: {integrity: sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==}
'@types/node@25.5.0':
resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==}
@@ -3987,8 +4013,8 @@ packages:
babel-plugin-react-compiler:
optional: true
- '@vitejs/plugin-rsc@0.5.23':
- resolution: {integrity: sha512-CV6kWPE4E241qDStwK3ErYjuZqW1i1xun3/P1wsm94RJoActLTrQsGzGsf75ioeVxEK0roPqLGhcV2WlSlPePQ==}
+ '@vitejs/plugin-rsc@0.5.24':
+ resolution: {integrity: sha512-FQ7o1Zf1GUB8L5qlIuV2mvIv/KahG2qUYW2gMpxyIN3zF7voDsfvA/t8w/TLjYC0T6p3JwMnK3N+YzMGf/m75A==}
peerDependencies:
react: '*'
react-dom: '*'
@@ -4039,6 +4065,9 @@ packages:
resolution: {integrity: sha512-kMwLlxUbduttIgaPdSkmEarFpP+mSY8FEm+QWMBRJwxOHWkri+cxd8KZHO9EMrB9vgUuz+5WEaCawaL5wGVoXg==}
engines: {node: '>=18.0.0'}
+ '@xstate/fsm@2.0.0':
+ resolution: {integrity: sha512-p/zcvBMoU2ap5byMefLkR+AM+Eh99CU/SDEQeccgKlmFNOMDwphaRGqdk+emvel/SaGZ7Rf9sDvzAplLzLdEVQ==}
+
'@xstate/react@6.1.0':
resolution: {integrity: sha512-ep9F0jGTI63B/jE8GHdMpUqtuz7yRebNaKv8EMUaiSi29NOglywc2X2YSOV/ygbIK+LtmgZ0q9anoEA2iBSEOw==}
peerDependencies:
@@ -4161,6 +4190,9 @@ packages:
resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
engines: {node: '>=4'}
+ ast-v8-to-istanbul@0.3.12:
+ resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==}
+
async-function@1.0.0:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
@@ -4531,8 +4563,8 @@ packages:
cookie-es@1.2.2:
resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==}
- cookie-es@2.0.0:
- resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==}
+ cookie-es@2.0.1:
+ resolution: {integrity: sha512-aVf4A4hI2w70LnF7GG+7xDQUkliwiXWXFvTjkip4+b64ygDQ2sJPRSKFDHbxn8o0xu9QzPkMuuiWIXyFSE2slA==}
cookie-es@3.1.1:
resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==}
@@ -5513,6 +5545,10 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ graphql@16.13.2:
+ resolution: {integrity: sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig==}
+ engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
+
gray-matter@4.0.3:
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
engines: {node: '>=6.0'}
@@ -5997,6 +6033,9 @@ packages:
js-image-generator@1.0.4:
resolution: {integrity: sha512-ckb7kyVojGAnArouVR+5lBIuwU1fcrn7E/YYSd0FK7oIngAkMmRvHASLro9Zt5SQdWToaI66NybG+OGxPw/HlQ==}
+ js-tokens@10.0.0:
+ resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -6189,6 +6228,15 @@ packages:
resolution: {integrity: sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg==}
hasBin: true
+ lit-element@4.2.2:
+ resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==}
+
+ lit-html@3.3.2:
+ resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==}
+
+ lit@3.3.2:
+ resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==}
+
load-json-file@4.0.0:
resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==}
engines: {node: '>=4'}
@@ -7193,6 +7241,10 @@ packages:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
+ regexparam@2.0.2:
+ resolution: {integrity: sha512-A1PeDEYMrkLrfyOwv2jwihXbo9qxdGD3atBYQA9JJgreAx8/7rC6IUkWOw2NQlOxLp2wL0ifQbh1HuidDfYA6w==}
+ engines: {node: '>=8'}
+
rehype-autolink-headings@7.1.0:
resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==}
@@ -7277,6 +7329,11 @@ packages:
engines: {node: '>= 0.4'}
hasBin: true
+ resolve@1.22.12:
+ resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
resolve@2.0.0-next.6:
resolution: {integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==}
engines: {node: '>= 0.4'}
@@ -7389,14 +7446,14 @@ packages:
resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==}
engines: {node: '>=20.0.0'}
- seroval-plugins@1.5.1:
- resolution: {integrity: sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw==}
+ seroval-plugins@1.5.2:
+ resolution: {integrity: sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==}
engines: {node: '>=10'}
peerDependencies:
seroval: ^1.0
- seroval@1.5.1:
- resolution: {integrity: sha512-OwrZRZAfhHww0WEnKHDY8OM0U/Qs8OTfIDWhUD4BLpNJUfXK4cGmjiagGze086m+mhI+V2nD0gfbHEnJjb9STA==}
+ seroval@1.5.2:
+ resolution: {integrity: sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==}
engines: {node: '>=10'}
serve-static@2.2.1:
@@ -8201,6 +8258,10 @@ packages:
resolution: {integrity: sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==}
engines: {node: '>= 12.0.0'}
+ worktop@0.7.3:
+ resolution: {integrity: sha512-WBHP1hk8pLP7ahAw13fugDWcO0SUAOiCD6DHT/bfLWoCIA/PL9u7GKdudT2nGZ8EGR1APbGCAI6ZzKG1+X+PnQ==}
+ engines: {node: '>=12'}
+
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -8992,6 +9053,12 @@ snapshots:
'@floating-ui/utils@0.2.11': {}
+ '@google/model-viewer@4.2.0(three@0.183.2)':
+ dependencies:
+ '@monogrid/gainmap-js': 3.4.0(three@0.183.2)
+ lit: 3.3.2
+ three: 0.183.2
+
'@hono/node-server@1.19.12(hono@4.12.9)':
dependencies:
hono: 4.12.9
@@ -9262,6 +9329,12 @@ snapshots:
'@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1)
tslib: 2.8.1
+ '@lit-labs/ssr-dom-shim@1.5.1': {}
+
+ '@lit/reactive-element@2.1.2':
+ dependencies:
+ '@lit-labs/ssr-dom-shim': 1.5.1
+
'@mapbox/node-pre-gyp@2.0.3':
dependencies:
consola: 3.4.2
@@ -9335,7 +9408,7 @@ snapshots:
'@neondatabase/serverless@1.0.2':
dependencies:
- '@types/node': 22.19.15
+ '@types/node': 22.19.17
'@types/pg': 8.20.0
optional: true
@@ -9392,7 +9465,7 @@ snapshots:
yargs: 17.7.2
zod: 4.3.6
- '@netlify/db-dev@0.7.0':
+ '@netlify/database-dev@0.8.0':
dependencies:
'@electric-sql/pglite': 0.3.16
pg-gateway: 0.3.0-beta.4
@@ -9415,15 +9488,15 @@ snapshots:
uuid: 13.0.0
write-file-atomic: 5.0.1
- '@netlify/dev@4.16.4(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))':
+ '@netlify/dev@4.17.0(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))':
dependencies:
'@netlify/ai': 0.4.1
'@netlify/blobs': 10.7.4
'@netlify/config': 24.4.4
- '@netlify/db-dev': 0.7.0
+ '@netlify/database-dev': 0.8.0
'@netlify/dev-utils': 4.4.3
'@netlify/edge-functions-dev': 1.0.16
- '@netlify/functions-dev': 1.2.4(rollup@4.53.3)
+ '@netlify/functions-dev': 1.2.5(rollup@4.53.3)
'@netlify/headers': 2.1.8
'@netlify/images': 1.3.7(@netlify/blobs@10.7.4)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))
'@netlify/redirects': 3.1.10
@@ -9496,11 +9569,11 @@ snapshots:
dependencies:
'@netlify/types': 2.6.0
- '@netlify/functions-dev@1.2.4(rollup@4.53.3)':
+ '@netlify/functions-dev@1.2.5(rollup@4.53.3)':
dependencies:
'@netlify/blobs': 10.7.4
'@netlify/dev-utils': 4.4.3
- '@netlify/functions': 5.1.5
+ '@netlify/functions': 5.2.0
'@netlify/zip-it-and-ship-it': 14.5.3(rollup@4.53.3)
cron-parser: 4.9.0
decache: 4.6.2
@@ -9523,6 +9596,10 @@ snapshots:
dependencies:
'@netlify/types': 2.6.0
+ '@netlify/functions@5.2.0':
+ dependencies:
+ '@netlify/types': 2.6.0
+
'@netlify/headers-parser@9.0.3':
dependencies:
'@iarna/toml': 2.2.5
@@ -9608,12 +9685,12 @@ snapshots:
'@netlify/types@2.6.0': {}
- '@netlify/vite-plugin-tanstack-start@1.3.2(@tanstack/react-start@1.167.30(@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
+ '@netlify/vite-plugin-tanstack-start@1.3.4(@tanstack/react-start@1.167.30(@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
- '@netlify/vite-plugin': 2.11.2(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ '@netlify/vite-plugin': 2.11.4(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)
optionalDependencies:
- '@tanstack/react-start': 1.167.30(@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ '@tanstack/react-start': 1.167.30(@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -9641,9 +9718,9 @@ snapshots:
- supports-color
- uploadthing
- '@netlify/vite-plugin@2.11.2(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
+ '@netlify/vite-plugin@2.11.4(babel-plugin-macros@3.1.0)(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
- '@netlify/dev': 4.16.4(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))
+ '@netlify/dev': 4.17.0(rollup@4.53.3)(uploadthing@7.7.4(express@5.2.1)(h3@1.15.10)(tailwindcss@4.2.2))
'@netlify/dev-utils': 4.4.3
dedent: 1.7.2(babel-plugin-macros@3.1.0)
vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)
@@ -9783,7 +9860,7 @@ snapshots:
'@opentelemetry/api-logs@0.203.0':
dependencies:
- '@opentelemetry/api': 1.9.0
+ '@opentelemetry/api': 1.9.1
'@opentelemetry/api-logs@0.207.0':
dependencies:
@@ -10747,7 +10824,7 @@ snapshots:
'@rolldown/pluginutils@1.0.0-rc.12': {}
- '@rolldown/pluginutils@1.0.0-rc.13': {}
+ '@rolldown/pluginutils@1.0.0-rc.15': {}
'@rolldown/pluginutils@1.0.0-rc.7': {}
@@ -11063,6 +11140,20 @@ snapshots:
'@shikijs/vscode-textmate@10.0.2': {}
+ '@shopify/hydrogen-react@2026.4.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(three@0.183.2)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
+ dependencies:
+ '@google/model-viewer': 4.2.0(three@0.183.2)
+ '@xstate/fsm': 2.0.0
+ ast-v8-to-istanbul: 0.3.12
+ graphql: 16.13.2
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ type-fest: 4.41.0
+ vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)
+ worktop: 0.7.3
+ transitivePeerDependencies:
+ - three
+
'@sindresorhus/merge-streams@4.0.0': {}
'@so-ric/colorspace@1.1.6':
@@ -11191,37 +11282,37 @@ snapshots:
tailwindcss: 4.2.2
vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)
- '@tanstack/ai-anthropic@0.7.2(@tanstack/ai@0.10.0)(zod@4.3.6)':
+ '@tanstack/ai-anthropic@0.7.3(@tanstack/ai@0.10.2)(zod@4.3.6)':
dependencies:
'@anthropic-ai/sdk': 0.71.2(zod@4.3.6)
- '@tanstack/ai': 0.10.0
+ '@tanstack/ai': 0.10.2
zod: 4.3.6
- '@tanstack/ai-client@0.7.7':
+ '@tanstack/ai-client@0.7.9':
dependencies:
- '@tanstack/ai': 0.10.0
- '@tanstack/ai-event-client': 0.2.0(@tanstack/ai@0.10.0)
+ '@tanstack/ai': 0.10.2
+ '@tanstack/ai-event-client': 0.2.2(@tanstack/ai@0.10.2)
- '@tanstack/ai-event-client@0.2.0(@tanstack/ai@0.10.0)':
+ '@tanstack/ai-event-client@0.2.2(@tanstack/ai@0.10.2)':
dependencies:
- '@tanstack/ai': 0.10.0
+ '@tanstack/ai': 0.10.2
'@tanstack/devtools-event-client': 0.4.3
- '@tanstack/ai-openai@0.7.3(@tanstack/ai-client@0.7.7)(@tanstack/ai@0.10.0)(ws@8.20.0)(zod@4.3.6)':
+ '@tanstack/ai-openai@0.7.4(@tanstack/ai-client@0.7.9)(@tanstack/ai@0.10.2)(ws@8.20.0)(zod@4.3.6)':
dependencies:
- '@tanstack/ai': 0.10.0
- '@tanstack/ai-client': 0.7.7
+ '@tanstack/ai': 0.10.2
+ '@tanstack/ai-client': 0.7.9
openai: 6.33.0(ws@8.20.0)(zod@4.3.6)
zod: 4.3.6
transitivePeerDependencies:
- ws
- '@tanstack/ai@0.10.0':
+ '@tanstack/ai@0.10.2':
dependencies:
- '@tanstack/ai-event-client': 0.2.0(@tanstack/ai@0.10.0)
+ '@tanstack/ai-event-client': 0.2.2(@tanstack/ai@0.10.2)
partial-json: 0.1.7
- '@tanstack/create@0.63.2(tslib@2.8.1)':
+ '@tanstack/create@0.63.4(tslib@2.8.1)':
dependencies:
ejs: 3.1.10
execa: 9.6.1
@@ -11274,7 +11365,7 @@ snapshots:
- supports-color
- utf-8-validate
- '@tanstack/devtools@0.11.1(csstype@3.2.3)(solid-js@1.9.12)':
+ '@tanstack/devtools@0.11.2(csstype@3.2.3)(solid-js@1.9.12)':
dependencies:
'@solid-primitives/event-listener': 2.4.5(solid-js@1.9.12)
'@solid-primitives/keyboard': 1.3.5(solid-js@1.9.12)
@@ -11301,13 +11392,13 @@ snapshots:
'@tanstack/devtools-event-client': 0.4.3
'@tanstack/store': 0.9.3
- '@tanstack/query-core@5.96.2': {}
+ '@tanstack/query-core@5.99.0': {}
- '@tanstack/query-devtools@5.96.2': {}
+ '@tanstack/query-devtools@5.99.0': {}
- '@tanstack/react-devtools@0.10.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)':
+ '@tanstack/react-devtools@0.10.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)':
dependencies:
- '@tanstack/devtools': 0.11.1(csstype@3.2.3)(solid-js@1.9.12)
+ '@tanstack/devtools': 0.11.2(csstype@3.2.3)(solid-js@1.9.12)
'@types/react': 19.2.14
'@types/react-dom': 19.2.3(@types/react@19.2.14)
react: 19.2.3
@@ -11332,15 +11423,15 @@ snapshots:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
- '@tanstack/react-query-devtools@5.96.2(@tanstack/react-query@5.96.2(react@19.2.3))(react@19.2.3)':
+ '@tanstack/react-query-devtools@5.99.0(@tanstack/react-query@5.99.0(react@19.2.3))(react@19.2.3)':
dependencies:
- '@tanstack/query-devtools': 5.96.2
- '@tanstack/react-query': 5.96.2(react@19.2.3)
+ '@tanstack/query-devtools': 5.99.0
+ '@tanstack/react-query': 5.99.0(react@19.2.3)
react: 19.2.3
- '@tanstack/react-query@5.96.2(react@19.2.3)':
+ '@tanstack/react-query@5.99.0(react@19.2.3)':
dependencies:
- '@tanstack/query-core': 5.96.2
+ '@tanstack/query-core': 5.99.0
react: 19.2.3
'@tanstack/react-router-devtools@1.166.13(@tanstack/react-router@1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.168.14)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
@@ -11354,12 +11445,12 @@ snapshots:
transitivePeerDependencies:
- csstype
- '@tanstack/react-router-ssr-query@1.166.11(@tanstack/query-core@5.96.2)(@tanstack/react-query@5.96.2(react@19.2.3))(@tanstack/react-router@1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.168.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ '@tanstack/react-router-ssr-query@1.166.11(@tanstack/query-core@5.99.0)(@tanstack/react-query@5.99.0(react@19.2.3))(@tanstack/react-router@1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.168.14)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
- '@tanstack/query-core': 5.96.2
- '@tanstack/react-query': 5.96.2(react@19.2.3)
+ '@tanstack/query-core': 5.99.0
+ '@tanstack/react-query': 5.99.0(react@19.2.3)
'@tanstack/react-router': 1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@tanstack/router-ssr-query-core': 1.167.1(@tanstack/query-core@5.96.2)(@tanstack/router-core@1.168.14)
+ '@tanstack/router-ssr-query-core': 1.167.1(@tanstack/query-core@5.99.0)(@tanstack/router-core@1.168.14)
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
transitivePeerDependencies:
@@ -11382,7 +11473,7 @@ snapshots:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
- '@tanstack/react-start-rsc@0.0.10(@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
+ '@tanstack/react-start-rsc@0.0.10(@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
'@tanstack/react-router': 1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@tanstack/react-start-server': 1.166.35(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -11397,7 +11488,7 @@ snapshots:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
optionalDependencies:
- '@vitejs/plugin-rsc': 0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ '@vitejs/plugin-rsc': 0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
transitivePeerDependencies:
- '@rsbuild/core'
- crossws
@@ -11418,11 +11509,11 @@ snapshots:
transitivePeerDependencies:
- crossws
- '@tanstack/react-start@1.167.30(@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
+ '@tanstack/react-start@1.167.30(@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
'@tanstack/react-router': 1.168.17(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@tanstack/react-start-client': 1.166.34(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@tanstack/react-start-rsc': 0.0.10(@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ '@tanstack/react-start-rsc': 0.0.10(@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
'@tanstack/react-start-server': 1.166.35(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@tanstack/router-utils': 1.161.6
'@tanstack/start-client-core': 1.167.15
@@ -11433,7 +11524,7 @@ snapshots:
react-dom: 19.2.3(react@19.2.3)
vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)
optionalDependencies:
- '@vitejs/plugin-rsc': 0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
+ '@vitejs/plugin-rsc': 0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))
transitivePeerDependencies:
- '@rsbuild/core'
- crossws
@@ -11457,16 +11548,16 @@ snapshots:
'@tanstack/router-core@1.168.13':
dependencies:
'@tanstack/history': 1.161.6
- cookie-es: 2.0.0
- seroval: 1.5.1
- seroval-plugins: 1.5.1(seroval@1.5.1)
+ cookie-es: 2.0.1
+ seroval: 1.5.2
+ seroval-plugins: 1.5.2(seroval@1.5.2)
'@tanstack/router-core@1.168.14':
dependencies:
'@tanstack/history': 1.161.6
cookie-es: 3.1.1
- seroval: 1.5.1
- seroval-plugins: 1.5.1(seroval@1.5.1)
+ seroval: 1.5.2
+ seroval-plugins: 1.5.2(seroval@1.5.2)
'@tanstack/router-devtools-core@1.167.3(@tanstack/router-core@1.168.14)(csstype@3.2.3)':
dependencies:
@@ -11510,9 +11601,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@tanstack/router-ssr-query-core@1.167.1(@tanstack/query-core@5.96.2)(@tanstack/router-core@1.168.14)':
+ '@tanstack/router-ssr-query-core@1.167.1(@tanstack/query-core@5.99.0)(@tanstack/router-core@1.168.14)':
dependencies:
- '@tanstack/query-core': 5.96.2
+ '@tanstack/query-core': 5.99.0
'@tanstack/router-core': 1.168.14
'@tanstack/router-utils@1.161.6':
@@ -11534,7 +11625,7 @@ snapshots:
'@tanstack/router-core': 1.168.13
'@tanstack/start-fn-stubs': 1.161.6
'@tanstack/start-storage-context': 1.166.27
- seroval: 1.5.1
+ seroval: 1.5.2
'@tanstack/start-fn-stubs@1.161.6': {}
@@ -11554,7 +11645,7 @@ snapshots:
exsolve: 1.0.8
pathe: 2.0.3
picomatch: 4.0.4
- seroval: 1.5.1
+ seroval: 1.5.2
source-map: 0.7.6
srvx: 0.11.15
tinyglobby: 0.2.15
@@ -11578,7 +11669,7 @@ snapshots:
'@tanstack/start-client-core': 1.167.15
'@tanstack/start-storage-context': 1.166.27
h3-v2: h3@2.0.1-rc.16
- seroval: 1.5.1
+ seroval: 1.5.2
transitivePeerDependencies:
- crossws
@@ -11756,7 +11847,7 @@ snapshots:
dependencies:
'@types/node': 25.5.0
- '@types/node@22.19.15':
+ '@types/node@22.19.17':
dependencies:
undici-types: 6.21.0
optional: true
@@ -11828,8 +11919,7 @@ snapshots:
'@types/triple-beam@1.3.5': {}
- '@types/trusted-types@2.0.7':
- optional: true
+ '@types/trusted-types@2.0.7': {}
'@types/unist@2.0.11': {}
@@ -11947,9 +12037,9 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-rc.7
vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3)
- '@vitejs/plugin-rsc@0.5.23(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
+ '@vitejs/plugin-rsc@0.5.24(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.3))':
dependencies:
- '@rolldown/pluginutils': 1.0.0-rc.13
+ '@rolldown/pluginutils': 1.0.0-rc.15
es-module-lexer: 2.0.0
estree-walker: 3.0.3
magic-string: 0.30.21
@@ -12026,6 +12116,8 @@ snapshots:
'@whatwg-node/promise-helpers': 1.3.2
tslib: 2.8.1
+ '@xstate/fsm@2.0.0': {}
+
'@xstate/react@6.1.0(@types/react@19.2.14)(react@19.2.3)(xstate@5.30.0)':
dependencies:
react: 19.2.3
@@ -12177,6 +12269,12 @@ snapshots:
dependencies:
tslib: 2.8.1
+ ast-v8-to-istanbul@0.3.12:
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.31
+ estree-walker: 3.0.3
+ js-tokens: 10.0.0
+
async-function@1.0.0: {}
async-sema@3.1.1: {}
@@ -12202,7 +12300,7 @@ snapshots:
dependencies:
'@babel/runtime': 7.29.2
cosmiconfig: 7.1.0
- resolve: 1.22.11
+ resolve: 1.22.12
optional: true
bail@2.0.2: {}
@@ -12547,7 +12645,7 @@ snapshots:
cookie-es@1.2.2: {}
- cookie-es@2.0.0: {}
+ cookie-es@2.0.1: {}
cookie-es@3.1.1: {}
@@ -13633,6 +13731,8 @@ snapshots:
graceful-fs@4.2.11: {}
+ graphql@16.13.2: {}
+
gray-matter@4.0.3:
dependencies:
js-yaml: 3.14.2
@@ -14202,6 +14302,8 @@ snapshots:
dependencies:
jpeg-js: 0.4.4
+ js-tokens@10.0.0: {}
+
js-tokens@4.0.0: {}
js-tokens@9.0.1: {}
@@ -14387,6 +14489,22 @@ snapshots:
untun: 0.1.3
uqr: 0.1.2
+ lit-element@4.2.2:
+ dependencies:
+ '@lit-labs/ssr-dom-shim': 1.5.1
+ '@lit/reactive-element': 2.1.2
+ lit-html: 3.3.2
+
+ lit-html@3.3.2:
+ dependencies:
+ '@types/trusted-types': 2.0.7
+
+ lit@3.3.2:
+ dependencies:
+ '@lit/reactive-element': 2.1.2
+ lit-element: 4.2.2
+ lit-html: 3.3.2
+
load-json-file@4.0.0:
dependencies:
graceful-fs: 4.2.11
@@ -15659,6 +15777,8 @@ snapshots:
gopd: 1.2.0
set-function-name: 2.0.2
+ regexparam@2.0.2: {}
+
rehype-autolink-headings@7.1.0:
dependencies:
'@types/hast': 3.0.4
@@ -15752,7 +15872,7 @@ snapshots:
dependencies:
debug: 4.4.3
module-details-from-path: 1.0.4
- resolve: 1.22.11
+ resolve: 1.22.12
transitivePeerDependencies:
- supports-color
@@ -15783,6 +15903,13 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ resolve@1.22.12:
+ dependencies:
+ es-errors: 1.3.0
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
resolve@2.0.0-next.6:
dependencies:
es-errors: 1.3.0
@@ -15946,11 +16073,11 @@ snapshots:
serialize-javascript@7.0.5: {}
- seroval-plugins@1.5.1(seroval@1.5.1):
+ seroval-plugins@1.5.2(seroval@1.5.2):
dependencies:
- seroval: 1.5.1
+ seroval: 1.5.2
- seroval@1.5.1: {}
+ seroval@1.5.2: {}
serve-static@2.2.1:
dependencies:
@@ -16072,8 +16199,8 @@ snapshots:
solid-js@1.9.12:
dependencies:
csstype: 3.2.3
- seroval: 1.5.1
- seroval-plugins: 1.5.1(seroval@1.5.1)
+ seroval: 1.5.2
+ seroval-plugins: 1.5.2(seroval@1.5.2)
source-map-explorer@2.5.3:
dependencies:
@@ -16771,6 +16898,10 @@ snapshots:
triple-beam: 1.4.1
winston-transport: 4.9.0
+ worktop@0.7.3:
+ dependencies:
+ regexparam: 2.0.2
+
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx
index fdcb3da25..d0f8a9c2d 100644
--- a/src/components/Navbar.tsx
+++ b/src/components/Navbar.tsx
@@ -8,6 +8,7 @@ const LazyNavbarAuthControls = React.lazy(() =>
default: m.NavbarAuthControls,
})),
)
+import { NavbarCartButton } from './NavbarCartButton'
import { Link, useLocation, useMatches } from '@tanstack/react-router'
import { NetlifyImage } from './NetlifyImage'
import {
@@ -303,6 +304,7 @@ export function Navbar({ children }: { children: React.ReactNode }) {
You are currently reading {version} docs. Redirect to{' '} @@ -40,7 +40,7 @@ export function RedirectVersionBanner(props: {