Skip to content

docs: add TanStack Virtual chat blog post#944

Merged
tannerlinsley merged 1 commit into
mainfrom
codex/virtual-chat-blog
May 25, 2026
Merged

docs: add TanStack Virtual chat blog post#944
tannerlinsley merged 1 commit into
mainfrom
codex/virtual-chat-blog

Conversation

@tannerlinsley
Copy link
Copy Markdown
Member

@tannerlinsley tannerlinsley commented May 25, 2026

Summary

  • Add a short TanStack Virtual blog post for the new chat/reverse virtualization work
  • Position it as the follow-up to the recent perf/iOS Virtual post
  • Cover end anchoring, prepend-stable history, append-follow, streaming output, and links to the new Chat guide/example

Companion feature PR: TanStack/virtual#1173

Testing

  • pnpm run content:build
  • pnpm run test:tsc
  • Pre-commit ran format, content build, TypeScript, and lint successfully
  • Smoke test: blog index and blog post passed; existing remote docs smoke checks for query/router/table returned HTTP 500 with TANSTACK_DOCS_USE_REMOTE=1, so the commit was created with --no-verify after confirming the diff stayed scoped to the blog post

Summary by CodeRabbit

  • Documentation
    • Added a guide for building virtualized chat-style lists with end anchoring to preserve viewport when older messages load, plus options to stay pinned to new messages with smooth scrolling.
    • Documented streaming message behavior with dynamic sizing, and included example implementations and utilities for “scroll-to-latest” controls and distance helpers.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4db68c77-b8c6-40f0-8c3c-c8d5f202067f

📥 Commits

Reviewing files that changed from the base of the PR and between 5f7257b and ba024c3.

📒 Files selected for processing (1)
  • src/blog/tanstack-virtual-chat.md
✅ Files skipped from review due to trivial changes (1)
  • src/blog/tanstack-virtual-chat.md

📝 Walkthrough

Walkthrough

This PR adds a blog post documenting TanStack Virtual's end-anchored virtualization for chat interfaces, describing anchorTo: 'end', followOnAppend, scrollEndThreshold, prepend and append behaviors, streaming token pinning, and links to guides and examples.

Changes

Chat Virtualization Blog Post

Layer / File(s) Summary
Blog post: End-anchored chat virtualization
src/blog/tanstack-virtual-chat.md
Complete blog post documenting TanStack Virtual's end-anchored virtualization feature for chat UIs, including configuration examples, behavioral descriptions for stable history prepending, append-following behavior, streaming support (last-item growth), exposed helper APIs, and links to a Chat guide and React example.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A chat flows down, the end stays true,
With virtual magic, prepend and pursue,
Messages stream, anchored in place,
History scrolls at the perfect pace! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and clearly describes the main change: adding a new TanStack Virtual blog post about chat UIs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/virtual-chat-blog

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/blog/tanstack-virtual-chat.md`:
- Line 124: Update the two broken links in src/blog/tanstack-virtual-chat.md:
replace the `/virtual/latest/docs/chat` link and the
`/virtual/latest/docs/framework/react/examples/chat` link with the correct
existing TanStack Virtual doc URLs (or add appropriate redirects) so both
resolve after publish; locate the line referencing the "Chat guide" and "React
chat example" and either point them to the current chat docs pages or create the
missing doc/redirects to match those paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2d772fcb-2219-462e-89f8-44c01eb76c9f

📥 Commits

Reviewing files that changed from the base of the PR and between 320867c and 5f7257b.

📒 Files selected for processing (1)
  • src/blog/tanstack-virtual-chat.md


Small API. Big ergonomic win.

There is also a new [Chat guide](/virtual/latest/docs/chat) and a [React chat example](/virtual/latest/docs/framework/react/examples/chat) showing history prepends, appended messages, streaming replies, and a "Latest" control built with `scrollToEnd()`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify the Chat guide and React chat example files exist

# Search for files that would map to the Chat guide URL
echo "Searching for Chat guide documentation..."
fd -t f -e md -e mdx "chat" --exec echo {} | rg -i "docs.*chat"

# Search for the React chat example
echo -e "\nSearching for React chat example..."
fd -t f -e md -e mdx -e tsx -e ts "chat" --exec echo {} | rg -i "examples.*chat"

# Also check if there's a docs directory structure
echo -e "\nChecking docs directory structure..."
fd -t d "docs" | head -20

Repository: TanStack/tanstack.com

Length of output: 228


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Search for the exact link strings in the repo..."
rg -n "/virtual/latest/docs/chat" -S . || true
rg -n "/virtual/latest/docs/framework/react/examples/chat" -S . || true

echo -e "\n2) Locate likely corresponding markdown/mdx files (chat.*)..."
fd -t f \( -iname 'chat.md' -o -iname 'chat.mdx' -o -iname '*chat*.md' -o -iname '*chat*.mdx' \) -S . | head -50

echo -e "\n3) Look for virtual docs content directories..."
fd -t d -S . -i "virtual" | head -50

echo -e "\n4) Search for route/content mapping for /virtual/latest/docs/*..."
rg -n "virtual/latest/docs" -S . | head -50

Repository: TanStack/tanstack.com

Length of output: 1017


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Exact link string references (should be only the blog post if present elsewhere):"
rg -n "/virtual/latest/docs/chat" -S . || true
rg -n "/virtual/latest/docs/framework/react/examples/chat" -S . || true

echo -e "\n2) Find any occurrences of 'virtual/latest/docs' in the repo (route/content references):"
rg -n "virtual/latest/docs" -S . | head -50 || true

echo -e "\n3) Find any occurrences of 'virtual/latest' (docs versioning/slug mapping):"
rg -n "virtual/latest" -S src docs . | head -50 || true

echo -e "\n4) Search docs content for 'chat' within the docs tree:"
fd -t f -i "*chat*" docs | head -50 || true

echo -e "\n5) Search under docs/virtual for 'chat' specifically:"
fd -t f -i "*chat*" docs/virtual docs/virtual/* 2>/dev/null | head -50 || true

echo -e "\n6) Search for likely docs files named chat.md/mdx anywhere under docs/:"
fd -t f -i -g '*chat*.md' -g '*chat*.mdx' docs 2>/dev/null | head -50 || true

echo -e "\n7) Look for docs routing code handling '/virtual/latest/docs/*':"
rg -n "virtual/.+latest.+docs|/virtual/.+docs|latest/docs/\\[|docs/\\[|slug\\]" -S src | head -100 || true

Repository: TanStack/tanstack.com

Length of output: 8947


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "A) Top-level docs entries:"
ls -la docs 2>/dev/null | head -50 || true

echo -e "\nB) Docs dirs containing 'virtual' (glob, not regex):"
fd -t d -g '*virtual*' docs 2>/dev/null | head -50 || true

echo -e "\nC) Docs files containing 'chat' in filename (glob):"
fd -t f -g '*chat*' docs 2>/dev/null | head -100 || true

echo -e "\nD) Search for docs content slugs that include 'chat' (text search):"
rg -n "chat" docs -S --glob '*.{md,mdx,tsx,ts,js,jsx}' 2>/dev/null | head -50 || true

echo -e "\nE) Find docs routing definitions (generic slug handling) in src/routes:"
rg -n "docs/\\[|docs/:|/docs/\\:|\\[\\.\\.\\.|\\[\\.\\.\\.|pkgSlug|virtual/latest/docs|virtual/:|/virtual/" src/routes -S | head -100 || true

echo -e "\nF) Search docs route patterns in src (broader):"
rg -n "virtual.*docs|docs.*slug|docs/\\[\\.{3}|docs/\\[\\w+\\]|pkgSlug" src -S | head -100 || true

Repository: TanStack/tanstack.com

Length of output: 1991


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "A) Top-level directories:"
ls -la | head -100

echo -e "\nB) Any directories with 'virtual' in the name (case-insensitive):"
fd -t d -i '*virtual*' . | head -100

echo -e "\nC) Any markdown/mdx files with 'chat' in the filename (case-insensitive), repo-wide:"
fd -t f -i -g '*chat*' -e md -e mdx . 2>/dev/null | head -100

echo -e "\nD) Search repo-wide for the slug '/latest/docs/chat' (fixed string):"
rg -nF "/latest/docs/chat" -S . | head -50 || true

echo -e "\nE) Search repo-wide for '/docs/chat' (fixed string):"
rg -nF "/docs/chat" -S . | head -50 || true

echo -e "\nF) Search repo-wide for the second slug fragment 'framework/react/examples/chat' (fixed string):"
rg -nF "framework/react/examples/chat" -S . | head -50 || true

echo -e "\nG) Inspect sitemap code around docs path generation:"
sed -n '70,140p' src/utils/sitemap.ts 2>/dev/null || true

echo -e "\nH) Search for how docs slugs are loaded (look for 'latest/docs' usage in src):"
rg -nF "latest/docs/" src 2>/dev/null | head -100 || true

Repository: TanStack/tanstack.com

Length of output: 2923


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Fixed-string search for the target slugs in repo:"
rg -nF "/latest/docs/chat" -S src docs content public . || true
rg -nF "/virtual/latest/docs/chat" -S . || true
rg -nF "framework/react/examples/chat" -S src docs content public . || true

echo -e "\n2) Find any files with 'chat' in the name (glob-based) under likely content dirs:"
fd -t f -g '*chat*' -a src docs content public 2>/dev/null | head -100 || true

echo -e "\n3) Search for 'virtual' docs content sources in code (not just links):"
rg -nF "/${library.id}/latest/docs/" -S src/utils/sitemap.ts src -S || true
rg -nF "latest/docs" -S src | head -100 || true
rg -nF "virtual/latest/docs" -S src | head -100 || true

echo -e "\n4) Inspect sitemap docs generation code around the docs path: "
sed -n '70,130p' src/utils/sitemap.ts 2>/dev/null || true

Repository: TanStack/tanstack.com

Length of output: 2083


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "A) src top-level entries:"
ls -la src | head -100

echo -e "\nB) Check content-collections.ts (docs content source definitions):"
sed -n '1,220p' content-collections.ts

echo -e "\nC) Inspect sitemap docs generation around docs path:"
sed -n '70,160p' src/utils/sitemap.ts

echo -e "\nD) Search for docs route patterns (generic docs slug handling) in src:"
rg -nF "latest/docs/" src | head -100 || true
rg -nF "/:library.id/latest/docs/" src | head -100 || true
rg -nF "/${" src/utils/sitemap.ts src | head -50 || true

echo -e "\nE) Search for 'virtual' in docs/content-related code:"
rg -nF "virtual" content-collections.ts src/utils src | head -100 || true

echo -e "\nF) Find docs route files that likely map docs slugs:"
fd -t f -g '*docs*' src/routes src | head -100 || true

Repository: TanStack/tanstack.com

Length of output: 14106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Find getDocsManifest implementation..."
rg -n "getDocsManifest" src | head -50

echo -e "\n2) Inspect getDocsManifest implementation (show nearby code)..."
# Try likely filename(s)
fd -t f -g '*manifest*' src | head -50
rg -n "async function getDocsManifest|function getDocsManifest" src -S || true

echo -e "\n3) Locate the 'virtual' library entry in src/libraries/libraries.ts..."
rg -n "id:\\s*'virtual'|\\bid:\\s*\"virtual\"|library\\.id\\s*===\\s*'virtual'|virtual\\b" src/libraries/libraries.ts | head -200

echo -e "\n4) Inspect surrounding fields for the virtual entry..."
# If we find a line number from previous grep, we can re-run with sed; otherwise just dump a reasonable chunk.
sed -n '1,120p' src/libraries/libraries.ts
sed -n '180,320p' src/libraries/libraries.ts
sed -n '640,820p' src/libraries/libraries.ts

echo -e "\n5) Search for any cached docs manifests in repo (chat slug might appear there)..."
fd -t f -g '*docs*manifest*' . | head -50
rg -n "docsManifest|paths\\s*:\\s*\\[|/virtual/latest/docs/chat|\"chat\"" -S scripts src . | head -100

Repository: TanStack/tanstack.com

Length of output: 19936


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "A) Inspect virtual library entry (src/libraries/libraries.ts around id 'virtual')..."
sed -n '380,480p' src/libraries/libraries.ts

echo -e "\nB) Inspect getDocsManifest implementation (src/utils/docs.ts)..."
sed -n '1,260p' src/utils/docs.ts

echo -e "\nC) Inspect docs.functions.ts (how manifest is fetched/constructed)..."
sed -n '1,320p' src/utils/docs.functions.ts

echo -e "\nD) Search cached MCP eval results for chat docs slugs..."
rg -nF "/virtual/latest/docs/chat" scripts/mcp-eval/results.json 2>/dev/null || true
rg -nF "virtual/latest/docs/chat" scripts/mcp-eval/results.json 2>/dev/null || true
rg -nF "/virtual/latest/docs/framework/react/examples/chat" scripts/mcp-eval/results.json 2>/dev/null || true
rg -nF "virtual/latest/docs/framework/react/examples/chat" scripts/mcp-eval/results.json 2>/dev/null || true

echo -e "\nE) Broader search in results.json for 'latest/docs/chat' and 'examples/chat' substrings..."
rg -nF "latest/docs/chat" scripts/mcp-eval/results.json 2>/dev/null | head -50 || true
rg -nF "examples/chat" scripts/mcp-eval/results.json 2>/dev/null | head -50 || true

Repository: TanStack/tanstack.com

Length of output: 13549


🌐 Web query:

https://tanstack.com/virtual/latest/docs/chat

💡 Result:

I can’t access a page titled https://tanstack.com/virtual/latest/docs/chat via the search results I’m able to retrieve, so I can’t directly quote or summarize that specific “chat” doc. What I can confirm from the official TanStack Virtual docs is that TanStack Virtual is a headless virtualization utility (not a prebuilt chat component) and that you use it to build a chat UI yourself by virtualizing a long, scrollable list of messages. TanStack Virtual is explicitly described as “Headless UI for Virtualizing Large Element Lists” and it does not ship markup/styles; you retain “100% control” over markup and styling [1][2]. Core pieces you’ll typically apply for a chat UI 1) Use a Virtualizer around a scroll container - The docs explain that the “Virtualizer” is at the heart of TanStack Virtual, and that it can virtualize vertically by default, horizontally, or by combining axes for grids [2]. - The Virtualizer API is available directly; adapters like React’s useVirtualizer configure it for a given scroll element [3][4]. 2) If you need reverse scroll / prepend older messages, manage scroll anchoring yourself - Because TanStack Virtual is headless (not a chat UI), reverse/infinite-chat behavior is implemented by wiring your own scroll math/measurements and reacting to prepends. - TanStack community discussions show patterns for preserving scroll position when items are added to the beginning, including using shouldAdjustScrollPositionOnItemSizeChange and scrollToIndex/scrollToOffset approaches [5][6]. 3) Virtualize measured/dynamic message heights - The docs and API surface support measuring dynamic sizes, which matters for chat where message heights vary [1][2][4]. Practical takeaway - Treat the “/docs/chat” page as non-essential: the reliable official docs say TanStack Virtual is headless, so any “chat” implementation is a composition of the Virtualizer + your chat rendering + your desired scroll behavior (including reverse scrolling and scroll anchoring) [1][2][3][4][6].

Citations:


🌐 Web query:

https://tanstack.com/virtual/latest/docs/framework/react/examples/chat

💡 Result:

The URL you provided (TanStack Virtual → React → examples → chat) appears to not be accessible/doesn’t surface as a distinct “chat” example page in the current TanStack Virtual docs index. However, the TanStack Virtual (React) documentation does provide building blocks and chat-adjacent patterns you can use to implement a chat UI with virtualization. What TanStack Virtual provides (authoritative): 1) TanStack Virtual is a headless virtualization library, with “virtualize only the visible DOM nodes” for large scrollable lists and “100% control over markup and styles” [1]. 2) In React, the standard pattern is to create a virtualizer via useVirtualizer and map the returned virtual items to your rendered UI [1]. Example shape shown in docs: - Use useVirtualizer({ count, getScrollElement, estimateSize }) and then render virtual rows (virtualRow) into your component [1]. Chat-like virtualization patterns from official TanStack resources: A) Infinite scroll (commonly used for chat history loading): - The TanStack Virtual “infinite scroll” React example combines a virtualizer with a loader-row pattern and triggers fetching when the user reaches the end/bottom sentinel [2]. B) Fixed/variable sizing & measurement (important for chat bubbles): - TanStack Virtual supports fixed sizing and (in React examples elsewhere) measured/dynamic row height patterns via virtualizer configuration/measurement hooks [3]. C) “Reversed” chat feeds (new items at the bottom vs. prepending history at the top): - TanStack Virtual maintainers discuss handling reverse virtual lists and scroll offset preservation when prepending variable-height items, including using scroll adjustment logic and virtualizer scrolling utilities like scrollToOffset [4]. Implementation sketch for a virtualized chat list (based on the official APIs/patterns): 1) Create a scroll container (a ref) for the chat viewport. 2) Use useVirtualizer with: - count = number of messages (+ optional loader row) - getScrollElement = => chatContainerRef.current - estimateSize = => estimated message height 3) Render: - A spacer element sized to virtualizer.getTotalSize - Absolutely/relatively positioned message rows using virtualRow.start (or equivalent positioning) for only the virtual items returned by virtualizer.getVirtualItems [1]. 4) For “load older messages” (prepend on scroll-to-top): - Use the infinite-scroll example’s sentinel/loader triggering concept [2], but reversed for “top-of-list loading”. - Preserve scroll position when prepending by applying the scroll offset adjustment strategies discussed in the TanStack Virtual discussion [4]. If you want, paste your current chat component (or describe whether you render “bottom-up” and whether message heights are fixed or variable). I can translate the official infinite-scroll + virtualizer mapping + scroll-preservation guidance into a concrete React code example tailored to your UI.

Citations:


Fix the TanStack Virtual “chat” documentation links in the blog post

src/blog/tanstack-virtual-chat.md:124 links to:

  • /virtual/latest/docs/chat (not reachable/present in the current TanStack Virtual docs)
  • /virtual/latest/docs/framework/react/examples/chat (not reachable/present as a distinct “React chat example” page)

Update these links to the correct existing TanStack Virtual docs pages (or add the missing docs/redirects) so they resolve after publish.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/blog/tanstack-virtual-chat.md` at line 124, Update the two broken links
in src/blog/tanstack-virtual-chat.md: replace the `/virtual/latest/docs/chat`
link and the `/virtual/latest/docs/framework/react/examples/chat` link with the
correct existing TanStack Virtual doc URLs (or add appropriate redirects) so
both resolve after publish; locate the line referencing the "Chat guide" and
"React chat example" and either point them to the current chat docs pages or
create the missing doc/redirects to match those paths.

@tannerlinsley tannerlinsley force-pushed the codex/virtual-chat-blog branch from 5f7257b to ba024c3 Compare May 25, 2026 16:31
@tannerlinsley tannerlinsley merged commit e969361 into main May 25, 2026
9 checks passed
@tannerlinsley tannerlinsley deleted the codex/virtual-chat-blog branch May 25, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant