Skip to content

Commit a35e425

Browse files
committed
Merge remote-tracking branch 'origin/main' into docs/frontmatter-description-keywords
# Conflicts: # src/routes/$libraryId/$version.docs.$.tsx # src/routes/$libraryId/$version.docs.framework.$framework.$.tsx # src/utils/docs.functions.ts
2 parents fc2ec40 + c40f7b3 commit a35e425

200 files changed

Lines changed: 9612 additions & 4454 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/analytics.md

Lines changed: 375 additions & 0 deletions
Large diffs are not rendered by default.

.agents/index.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ TanStack.com marketing site built with TanStack Start.
88
- Run `pnpm test` before commits or after significant code changes, not after every tiny edit
99
- Smoke tests live outside the default `pnpm test` path and are reserved for commit-hook validation
1010
- Don't run builds after every change. This is a visual site; assume changes work unless reported otherwise.
11-
- **Typesafety is paramount.** Never cast types; fix at source instead. See [typescript.md](.agents/typescript.md).
11+
- **Typesafety is paramount.** Never cast types; fix at source instead. See [typescript.md](./typescript.md).
1212

1313
## Topic Guides
1414

15-
- [TypeScript Conventions](.agents/typescript.md): Type inference, casting rules, generic naming
16-
- [TanStack Patterns](.agents/tanstack-patterns.md): Loaders, server functions, environment shaking
17-
- [UI Style Guide](.agents/ui-style.md): Visual design principles for 2026
18-
- [Workflow](.agents/workflow.md): Build commands, debugging, Playwright
15+
- [TypeScript Conventions](./typescript.md): Type inference, casting rules, generic naming
16+
- [TanStack Patterns](./tanstack-patterns.md): Loaders, server functions, environment shaking
17+
- [UI Style Guide](./ui-style.md): Visual design principles for 2026
18+
- [Workflow](./workflow.md): Build commands, debugging, Playwright
19+
- [Analytics](./analytics.md): GA4 event taxonomy, funnel definition, custom dimensions

.claude/launch.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"version": "0.0.1",
3+
"configurations": [
4+
{
5+
"name": "web",
6+
"runtimeExecutable": "pnpm",
7+
"runtimeArgs": ["dev"],
8+
"port": 3000
9+
},
10+
{
11+
"name": "db-studio",
12+
"runtimeExecutable": "pnpm",
13+
"runtimeArgs": ["db:studio"],
14+
"port": 4983
15+
}
16+
]
17+
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ dist
3131

3232
test-results
3333
.claude/CLAUDE.md
34+
.claude/worktrees
3435
.eslintcache
3536
.tsbuildinfo
3637
src/routeTree.gen.ts
38+
.og-preview/

.oxlintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
".tanstack-start",
2020
".netlify",
2121
"public",
22-
"convex/.temp"
22+
"convex/.temp",
23+
".claude"
2324
],
2425
"rules": {
2526
"no-array-constructor": "error",

README.md

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
# Welcome to TanStack.com!
1+
<div align="center">
22

3-
This site is built with TanStack Start and TanStack Router.
3+
# TanStack.com
44

5-
- [TanStack Router Docs](https://tanstack.com/router)
5+
The home of the TanStack ecosystem. Built with [TanStack Router](https://tanstack.com/router) and deployed automagically with [Netlify](https://netlify.com/).
66

7-
It's deployed automagically with Netlify!
7+
<a href="https://twitter.com/tan_stack"><img src="https://img.shields.io/twitter/follow/tan_stack.svg?style=social" alt="Follow @TanStack"/></a>
88

9-
- [Netlify](https://netlify.com/)
9+
### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)
10+
11+
</div>
1012

1113
## Development
1214

15+
### Quick Start
16+
1317
From your terminal:
1418

1519
```sh
@@ -19,76 +23,66 @@ pnpm dev
1923

2024
This starts your app in development mode, rebuilding assets on file changes.
2125

22-
## Authentication in Development
26+
### Local Setup
2327

24-
The dev server uses the production database and real OAuth, so dev and production behave identically. To authenticate your local session, run:
28+
The documentation for all TanStack projects (except `React Charts`) is hosted on [tanstack.com](https://tanstack.com). In production, doc pages are fetched from GitHub. In development, they're read from your local file system.
2529

26-
```sh
27-
pnpm auth:login
28-
```
30+
Pre-commit hooks run smoke tests against these docs, so you'll need sibling repos cloned for commits to pass.
2931

30-
This opens `tanstack.com` in your browser. Sign in with GitHub or Google, and the resulting session token is saved to `.env.local` as `DEV_SESSION_TOKEN`. Restart the dev server and you will be signed in automatically.
31-
32-
To authenticate against a locally running server instead:
32+
Create a `tanstack` parent directory and clone this repo alongside the projects:
3333

3434
```sh
35-
pnpm auth:login --url http://localhost:3000
35+
mkdir tanstack && cd tanstack
36+
git clone git@github.com:TanStack/tanstack.com.git
37+
git clone git@github.com:TanStack/query.git
38+
git clone git@github.com:TanStack/router.git
39+
git clone git@github.com:TanStack/table.git
3640
```
3741

38-
> [!NOTE]
39-
> The token is a real signed session cookie tied to your production account. It expires in 30 days. Re-run `pnpm auth:login` to refresh it.
40-
41-
> [!NOTE]
42-
> If you are using an AI agent (Claude, Cursor, etc.) to help develop, run `pnpm auth:login` once before starting your session so the agent can interact with authenticated features on your behalf.
43-
44-
## Editing and previewing the docs of TanStack projects locally
45-
46-
The documentations for all TanStack projects except for `React Charts` are hosted on [https://tanstack.com](https://tanstack.com), powered by this TanStack Router app.
47-
In production, the markdown doc pages are fetched from the GitHub repos of the projects, but in development they are read from the local file system.
48-
49-
Follow these steps if you want to edit the doc pages of a project (in these steps we'll assume it's [`TanStack/form`](https://github.com/tanstack/form)) and preview them locally :
50-
51-
1. Create a new directory called `tanstack`.
42+
Your directory structure should look like this:
5243

53-
```sh
54-
mkdir tanstack
44+
```
45+
tanstack/
46+
├── tanstack.com/
47+
├── query/
48+
├── router/
49+
└── table/
5550
```
5651

57-
2. Enter the directory and clone this repo and the repo of the project there.
52+
> [!WARNING]
53+
> Directory names must match repo names exactly (e.g., `query` not `tanstack-query`). The app finds docs by looking for sibling directories by name.
5854
59-
```sh
60-
cd tanstack
61-
git clone git@github.com:TanStack/tanstack.com.git
62-
git clone git@github.com:TanStack/form.git
63-
```
55+
### Editing Docs
56+
57+
To edit docs for a project, make changes in its `docs/` folder (e.g., `../form/docs/`) and visit http://localhost:3000/form/latest/docs/overview to preview.
6458

6559
> [!NOTE]
66-
> Your `tanstack` directory should look like this:
67-
>
68-
> ```
69-
> tanstack/
70-
> |
71-
> +-- form/
72-
> |
73-
> +-- tanstack.com/
74-
> ```
60+
> Updated pages need to be manually reloaded in the browser.
7561
7662
> [!WARNING]
77-
> Make sure the name of the directory in your local file system matches the name of the project's repo. For example, `tanstack/form` must be cloned into `form` (this is the default) instead of `some-other-name`, because that way, the doc pages won't be found.
63+
> Update the project's `docs/config.json` if you add a new doc page!
7864
79-
3. Enter the `tanstack/tanstack.com` directory, install the dependencies and run the app in dev mode:
65+
## Get Involved
8066

81-
```sh
82-
cd tanstack.com
83-
pnpm i
84-
# The app will run on https://localhost:3000 by default
85-
pnpm dev
86-
```
67+
- We welcome issues and pull requests!
68+
- Participate in [GitHub Discussions](https://github.com/TanStack/tanstack.com/discussions)
69+
- Chat with the community on [Discord](https://discord.com/invite/WrRKjPJ)
8770

88-
4. Now you can visit http://localhost:3000/form/latest/docs/overview in the browser and see the changes you make in `tanstack/form/docs`.
71+
## Explore the TanStack Ecosystem
8972

90-
> [!NOTE]
91-
> The updated pages need to be manually reloaded in the browser.
73+
- <a href="https://github.com/tanstack/config"><b>TanStack Config</b></a> – Tooling for JS/TS packages
74+
- <a href="https://github.com/tanstack/db"><b>TanStack DB</b></a> – Reactive sync client store
75+
- <a href="https://github.com/tanstack/devtools"><b>TanStack DevTools</b></a> – Unified devtools panel
76+
- <a href="https://github.com/tanstack/form"><b>TanStack Form</b></a> – Type‑safe form state
77+
- <a href="https://github.com/tanstack/pacer"><b>TanStack Pacer</b></a> – Debouncing, throttling, batching
78+
- <a href="https://github.com/tanstack/query"><b>TanStack Query</b></a> – Async state & caching
79+
- <a href="https://github.com/tanstack/ranger"><b>TanStack Ranger</b></a> – Range & slider primitives
80+
- <a href="https://github.com/tanstack/router"><b>TanStack Router</b></a> – Type‑safe routing, caching & URL state
81+
- <a href="https://github.com/tanstack/router"><b>TanStack Start</b></a> – Full‑stack SSR & streaming
82+
- <a href="https://github.com/tanstack/store"><b>TanStack Store</b></a> – Reactive data store
83+
- <a href="https://github.com/tanstack/table"><b>TanStack Table</b></a> – Headless datagrids
84+
- <a href="https://github.com/tanstack/virtual"><b>TanStack Virtual</b></a> – Virtualized rendering
9285

93-
> [!WARNING]
94-
> You will need to update the `docs/config.json` file (in the project's repo) if you add a new doc page!
86+
… and more at <a href="https://tanstack.com"><b>TanStack.com »</b></a>
87+
88+
<!-- Use the force, Luke -->

content-collections.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
import { defineCollection, defineConfig } from '@content-collections/core'
2+
import { libraryIds } from '~/libraries/libraries'
23
import { normalizeRedirectFrom } from '~/utils/redirects'
34
import { z } from 'zod'
45

6+
const libraryIdSet = new Set<string>(libraryIds)
7+
const libraryListSchema = z.string().refine(
8+
(value) => {
9+
const libraries = value
10+
.split(',')
11+
.map((library) => library.trim())
12+
.filter(Boolean)
13+
14+
return (
15+
libraries.length > 0 &&
16+
libraries.every((library) => libraryIdSet.has(library))
17+
)
18+
},
19+
{
20+
message: `Expected comma-separated library ids: ${libraryIds.join(', ')}`,
21+
},
22+
)
23+
524
const posts = defineCollection({
625
name: 'posts',
726
directory: './src/blog',
@@ -12,6 +31,7 @@ const posts = defineCollection({
1231
draft: z.boolean().optional(),
1332
excerpt: z.string(),
1433
authors: z.string().array(),
34+
library: libraryListSchema.optional(),
1535
content: z.string(),
1636
redirect_from: z.string().array().optional(),
1737
}),

docs-info.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ Fenced code blocks are supported with language identifiers for syntax highlighti
5151
export function App() {
5252
return <div>Hello</div>
5353
}
54-
;``
5554
```
5655
````
5756

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Lighthouse: @tanstack/dom-vite shim vs. real React
2+
3+
**Date:** 2026-04-20
4+
**tanstack.com commit at time of measurement:** `fb806bb` (shim build with `@tanstack/dom-vite@0.1.0-alpha.5`, pulling `@tanstack/react-dom@0.1.0-alpha.4` — includes the RSC deferred-hydration adoption fix landed the same day).
5+
**React baseline build:** same source tree with `tanstackDom()` plugin removed from `vite.config.ts` and `serverVariantAliases` dropped — i.e. stock `react@19.2.3` / `react-dom@19.2.3`.
6+
7+
## TL;DR
8+
9+
- **Performance score: parity** (±2 across pages / form factors, within run-to-run noise).
10+
- **FCP: consistent shim win** everywhere — ~4% on home, ~11–17% on docs / blog. Smaller main-thread parse cost lets first paint land sooner.
11+
- **LCP: shim regresses on RSC-heavy pages, desktop** — the LCP element on docs / blog pages lives in the Flight-streamed subtree, and the shim's `use(pendingPromise)` + deferred-resume adds latency vs. React's battle-tested RSC client. Mobile is mostly parity (network-bound anyway).
12+
- **TBT / CLS: effectively zero on both** after the same-day RSC hydration fix — no duplicate DOM, no layout shift from appending.
13+
- **Bundle (raw JS): −4.7%** on tanstack.com (-980 KB of 21 MB total client JS). Modest because router / store / app code dominates; shim only replaces React's share.
14+
15+
## Methodology
16+
17+
1. `pnpm build` for each variant.
18+
2. `PORT=4000 pnpm start:prod` to serve from `dist/server/server.js` on `http://localhost:4000`.
19+
3. **5 trials × 3 URLs × 2 form factors = 30 Lighthouse runs per variant** using `npx lighthouse` v13 with `--only-categories=performance` and headless Chrome.
20+
4. Mobile runs use Lighthouse's default emulation (slow 4G + 4× CPU slowdown). Desktop uses `--preset=desktop` (no throttling).
21+
5. Medians reported below.
22+
23+
## Medians
24+
25+
### Performance score
26+
27+
| URL | form | React | Shim | Δ |
28+
| --------------------------------------------------- | :-----: | ----: | ---: | --: |
29+
| `/` | desktop | 99 | 99 | 0 |
30+
| `/` | mobile | 87 | 88 | +1 |
31+
| `/query/latest/docs/framework/react/guides/queries` | desktop | 96 | 96 | 0 |
32+
| `/query/latest/docs/framework/react/guides/queries` | mobile | 64 | 66 | +2 |
33+
| `/blog/react-server-components` | desktop | 98 | 96 | −2 |
34+
| `/blog/react-server-components` | mobile | 70 | 71 | +1 |
35+
36+
### Web Vitals
37+
38+
| URL | form | FCP (R → S) | LCP (R → S) | TBT (R → S) | CLS (R → S) | TTI (R → S) |
39+
| ------------------------------- | :-----: | :------------------: | :------------------: | :----------------: | :---------: | :-----------: |
40+
| `/` | desktop | 0.61s → 0.59s (−4%) | 0.84s → 0.91s (+8%) | 0ms → 0ms | 0 → 0 | 0.84s → 0.92s |
41+
| `/` | mobile | 2.34s → 2.31s | 3.71s → 3.60s (−3%) | 19ms → 20ms | 0 → 0 | 5.54s → 5.55s |
42+
| `/query/.../queries` | desktop | 1.05s → 0.92s (−13%) | 1.05s → 1.24s (+18%) | 0ms → 0ms | 0 → 0 | 1.05s → 1.24s |
43+
| `/query/.../queries` | mobile | 4.66s → 4.13s (−11%) | 6.62s → 6.39s (−3%) | 17ms → 19ms | 0 → 0 | 8.36s → 8.41s |
44+
| `/blog/react-server-components` | desktop | 0.90s → 0.74s (−17%) | 0.90s → 1.29s (+43%) | 0ms → 0ms | 0 → 0 | 0.90s → 1.29s |
45+
| `/blog/react-server-components` | mobile | 3.73s → 3.21s (−14%) | 5.32s → 6.23s (+17%) | 34ms → 21ms (−37%) | 0 → 0 | 6.24s → 6.57s |
46+
47+
### Bundle size (uncompressed total client JS)
48+
49+
| Build | Total client JS | Notes |
50+
| ---------- | --------------: | ---------------------------------------------------------------------------------------------------- |
51+
| Real React | 21,052 KB | Dedicated `react-*.js` chunk = 176 KB (`manualChunks` splits `node_modules/react{,-dom}/`) |
52+
| Shim | 20,072 KB | No dedicated react chunk; shim code inlines into `app-shell` (+16 KB there). Net **−980 KB (−4.7%)** |
53+
54+
## Caveats
55+
56+
- **Lab data only.** Chrome origin-level CWV (CrUX) needs ~28 days of real traffic before aggregates stabilize. Since the shim only went live on `2026-04-20`, field data won't be comparable for a month.
57+
- **`pnpm start:prod` serves from Node locally — no CDN.** Absolute TTFB numbers are dev-machine noise (5ms–1s range depending on cold-cache loader work); anchor on client-side metrics.
58+
- **Per-page LCP percentages can look dramatic when the absolute value is small.** Blog desktop LCP `0.90s → 1.29s` is +390 ms — real, but a sub-second LCP regression in both states is still a Core Web Vitals "Good" rating (<2.5s).
59+
- **Single-node prod server — no edge, no warm cache.** Mobile Lighthouse runs with 4× CPU throttling are inherently high-variance.
60+
61+
## Reproduce
62+
63+
```bash
64+
# React baseline
65+
# 1) temporarily remove tanstackDom() plugin + serverVariantAliases in vite.config.ts
66+
pnpm build
67+
PORT=4000 pnpm start:prod &
68+
# run 5 trials × 3 URLs × 2 form factors, save JSON to ./react/
69+
70+
# Shim
71+
# 2) restore tanstackDom() plugin + serverVariantAliases
72+
pnpm build
73+
PORT=4000 pnpm start:prod &
74+
# re-run, save JSON to ./shim/
75+
76+
# Aggregate medians + delta (parse JSON, compute median of numericValues per audit key)
77+
```
78+
79+
See the shim side for the runner + aggregator scripts used (`/tmp/lh-compare/run.sh`, `/tmp/lh-compare/aggregate.mjs` at measurement time).
80+
81+
## Related shim work shipped with this comparison
82+
83+
- `@tanstack/react-dom@0.1.0-alpha.4`: `renderFunction`'s deferred-hydration branch now mirrors `renderLazy`'s ancestor-Suspense guard (`_awaitingLazyHydration`). Fixes duplicate-markup on RSC pages. Regression test: `tests/rsc-hydration-adopt.test.tsx`.
84+
- `@tanstack/react-dom-server@0.1.0-alpha.4`: shell-chunk batching in `streamHtml` (reduces Node stream overhead ~3–4% on SSR bench).
85+
- `@tanstack/dom-vite@0.1.0-alpha.5`: dep bump to pick up react-dom@alpha.4.

netlify.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ publish = "dist/client"
77

88
[functions]
99
directory = "netlify/functions"
10+
included_files = [
11+
"public/fonts/Inter-Regular.ttf",
12+
"public/fonts/Inter-ExtraBold.ttf",
13+
"public/images/logos/splash-dark.png",
14+
]
1015

1116
[[headers]]
1217
for = "/*"
@@ -35,3 +40,18 @@ for = "/builder/*"
3540
[headers.values]
3641
Cross-Origin-Opener-Policy = "same-origin"
3742
Cross-Origin-Embedder-Policy = "require-corp"
43+
44+
# Reverse-proxy Google Analytics through our own origin so requests are
45+
# first-party (escapes hostname-based ad blockers, longer-lived cookies,
46+
# cleaner CSP). gtag.js is told to use this prefix as its transport_url.
47+
[[redirects]]
48+
from = "/_a/gtag.js"
49+
to = "https://www.googletagmanager.com/gtag/js?id=G-JMT1Z50SPS"
50+
status = 200
51+
force = true
52+
53+
[[redirects]]
54+
from = "/_a/g/collect"
55+
to = "https://www.google-analytics.com/g/collect"
56+
status = 200
57+
force = true

0 commit comments

Comments
 (0)