`)}
+ `,
+ )}
+
+
+ `
+ }
+}
+```
+
+## Page Parameters
+
+`initialPageParam` is required. `getNextPageParam` decides whether another page exists and what value should be passed as `pageParam` to the next query function call.
+
+```ts
+createInfiniteQueryController(this, {
+ queryKey: ['projects'],
+ queryFn: ({ pageParam }) => fetchProjectsPage(pageParam),
+ initialPageParam: 1,
+ getNextPageParam: (lastPage) =>
+ lastPage.hasMore ? lastPage.page + 1 : undefined,
+})
+```
+
+Returning `undefined` or `null` means there is no next page.
+
+## Avoid Overlapping Fetches
+
+There is one ongoing fetch for an infinite query cache entry. If you call `fetchNextPage` while a background refetch is running, you can overwrite data. Disable the button or check `!query.isFetching` before loading more:
+
+```ts
+if (query.hasNextPage && !query.isFetching) {
+ this.projects.fetchNextPage()
+}
+```
+
+## Paginated Alternative
+
+If your UI shows one page at a time, a normal query with a page in the key can be a better fit. The [Pagination example](../examples/pagination) uses `createQueryController`, `placeholderData: keepPreviousData`, prefetching, and mutations to demonstrate that pattern.
diff --git a/docs/framework/lit/guides/mutations.md b/docs/framework/lit/guides/mutations.md
new file mode 100644
index 00000000000..8e5c3fdfa42
--- /dev/null
+++ b/docs/framework/lit/guides/mutations.md
@@ -0,0 +1,166 @@
+---
+id: mutations
+title: Mutations
+---
+
+Unlike queries, mutations are used to create, update, delete, or otherwise perform server side effects. In Lit, use [`createMutationController`](../reference/functions/createMutationController.md).
+
+```ts
+import { LitElement, html } from 'lit'
+import {
+ QueryClient,
+ QueryClientProvider,
+ createMutationController,
+ createQueryController,
+} from '@tanstack/lit-query'
+
+const queryClient = new QueryClient()
+
+class AppQueryProvider extends QueryClientProvider {
+ constructor() {
+ super()
+ this.client = queryClient
+ }
+}
+
+customElements.define('app-query-provider', AppQueryProvider)
+
+class TodosView extends LitElement {
+ private readonly todos = createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+ })
+
+ private readonly addTodo = createMutationController(this, {
+ mutationFn: createTodo,
+ onSuccess: async () => {
+ await queryClient.invalidateQueries({ queryKey: ['todos'] })
+ },
+ })
+
+ render() {
+ const query = this.todos()
+ const mutation = this.addTodo()
+ const todos = query.data ?? []
+
+ return html`
+ ${mutation.isError ? html`
${mutation.error.message}
` : null}
+ ${mutation.isSuccess ? html`
Todo added
` : null}
+
+
+
+
+ ${todos.map((todo) => html`
${todo.title}
`)}
+
+ `
+ }
+}
+
+customElements.define('todos-view', TodosView)
+```
+
+Render the element under the provider so the controllers can resolve the same `QueryClient` from Lit context:
+
+```html
+
+
+
+```
+
+## Mutation States
+
+A mutation can be in one of these primary states:
+
+- `isIdle` or `status === 'idle'`: no mutation has run or it has been reset
+- `isPending` or `status === 'pending'`: the mutation is running
+- `isError` or `status === 'error'`: the mutation failed and `error` is available
+- `isSuccess` or `status === 'success'`: the mutation finished and `data` is available
+
+## Variables
+
+Pass variables to the mutation function by calling `mutate`:
+
+```ts
+this.addTodo.mutate({
+ title: this.nextTitle,
+})
+```
+
+`mutate` throws synchronously if the controller cannot resolve a `QueryClient`, such as when the element is not under a connected `QueryClientProvider` and no explicit client was passed. `mutateAsync` reports the same setup problem as a rejected promise.
+
+Use `mutateAsync` when you want a promise:
+
+```ts
+try {
+ const created = await this.addTodo.mutateAsync({ title: this.nextTitle })
+ this.nextTitle = created.title
+} catch (error) {
+ this.errorMessage = String(error)
+}
+```
+
+## Resetting Mutation State
+
+The accessor includes `reset`:
+
+```ts
+html`
+ ${mutation.isError
+ ? html``
+ : null}
+`
+```
+
+## Side Effects
+
+Mutation options support `onMutate`, `onError`, `onSuccess`, and `onSettled`. The pagination example passes an explicit `queryClient` to the controller and uses the same in-scope client for optimistic updates and rollback:
+
+```ts
+private readonly favoriteMutation = createMutationController(
+ this,
+ {
+ mutationKey: ['toggle-project-favorite'],
+ mutationFn: async (input) => {
+ const response = await toggleProjectFavoriteOnServer(input)
+ return response.project
+ },
+ onMutate: async (variables) => {
+ await queryClient.cancelQueries({ queryKey: ['projects'] })
+ const snapshots = queryClient.getQueriesData({
+ queryKey: ['projects'],
+ })
+
+ for (const [key, existing] of snapshots) {
+ if (!existing) continue
+
+ queryClient.setQueryData(key, {
+ ...existing,
+ projects: existing.projects.map((project) =>
+ project.id === variables.id
+ ? { ...project, isFavorite: variables.isFavorite }
+ : project,
+ ),
+ })
+ }
+
+ return { snapshots }
+ },
+ onError: (_error, _variables, context) => {
+ for (const [key, snapshot] of context?.snapshots ?? []) {
+ queryClient.setQueryData(key, snapshot)
+ }
+ },
+ onSettled: async () => {
+ await queryClient.invalidateQueries({ queryKey: ['projects'] })
+ },
+ },
+ queryClient,
+)
+```
+
+For the exact runnable flow, see the [Pagination example](../examples/pagination).
diff --git a/docs/framework/lit/guides/parallel-queries.md b/docs/framework/lit/guides/parallel-queries.md
new file mode 100644
index 00000000000..2d9bf967f7b
--- /dev/null
+++ b/docs/framework/lit/guides/parallel-queries.md
@@ -0,0 +1,134 @@
+---
+id: parallel-queries
+title: Parallel Queries
+---
+
+Parallel queries are queries that run at the same time so the UI does not wait for one request before starting the next.
+
+## Manual Parallel Queries
+
+When the number of queries is fixed, create multiple query controllers on the same host. They will all subscribe when the host connects.
+
+```ts
+import { LitElement, html } from 'lit'
+import { createQueryController } from '@tanstack/lit-query'
+
+class DashboardView extends LitElement {
+ private readonly users = createQueryController(this, {
+ queryKey: ['users'],
+ queryFn: fetchUsers,
+ })
+
+ private readonly teams = createQueryController(this, {
+ queryKey: ['teams'],
+ queryFn: fetchTeams,
+ })
+
+ private readonly projects = createQueryController(this, {
+ queryKey: ['projects'],
+ queryFn: fetchProjects,
+ })
+
+ render() {
+ const users = this.users()
+ const teams = this.teams()
+ const projects = this.projects()
+
+ if (users.isPending || teams.isPending || projects.isPending) {
+ return html`Loading...`
+ }
+
+ if (users.isError || teams.isError || projects.isError) {
+ return html`Unable to load dashboard`
+ }
+
+ return html`
+
+ `
+ }
+}
+```
+
+Each controller receives the same `ReactiveControllerHost`. If no explicit `QueryClient` is passed, each controller resolves the nearest connected `QueryClientProvider`.
+
+## Dynamic Parallel Queries
+
+When the number of queries changes with host state, use [`createQueriesController`](../reference/functions/createQueriesController.md). It accepts a `queries` array and returns an accessor for the array of query results.
+
+Use an options getter when the query list depends on reactive host fields:
+
+```ts
+import { LitElement, html } from 'lit'
+import { createQueriesController } from '@tanstack/lit-query'
+
+class UsersDetails extends LitElement {
+ static properties = {
+ userIds: { attribute: false },
+ }
+
+ userIds: Array = []
+
+ private readonly users = createQueriesController(this, () => ({
+ queries: this.userIds.map((id) => ({
+ queryKey: ['user', id],
+ queryFn: () => fetchUserById(id),
+ })),
+ }))
+
+ render() {
+ const userQueries = this.users()
+
+ return html`
+
+ ${userQueries.map((query, index) => {
+ if (query.isPending) return html`
Loading...
`
+ if (query.isError) return html`
Error loading user
`
+
+ return html`
${this.userIds[index]}: ${query.data.name}
`
+ })}
+
+ `
+ }
+}
+```
+
+The order of the results matches the order of the input queries.
+
+## Combining Results
+
+Use `combine` when a component wants one derived value instead of an array of query results:
+
+```ts
+private readonly dashboard = createQueriesController(this, {
+ queries: [
+ { queryKey: ['stats'], queryFn: fetchStats },
+ { queryKey: ['projects'], queryFn: fetchProjects },
+ ],
+ combine: ([stats, projects]) => ({
+ activeUsers: stats.data?.activeUsers ?? 0,
+ projects: projects.data ?? [],
+ isPending: stats.isPending || projects.isPending,
+ isError: stats.isError || projects.isError,
+ }),
+})
+```
+
+```ts
+render() {
+ const dashboard = this.dashboard()
+
+ if (dashboard.isPending) return html`Loading...`
+ if (dashboard.isError) return html`Unable to load dashboard`
+
+ return html`
+
Total projects: ${dashboard.projects.length}
+
Active users: ${dashboard.activeUsers}
+ `
+}
+```
+
+Having the same query key more than once in the `queries` array can cause those entries to share cached data. Deduplicate repeated keys first if each rendered row needs independent query state.
diff --git a/docs/framework/lit/guides/queries.md b/docs/framework/lit/guides/queries.md
new file mode 100644
index 00000000000..592cdcfd029
--- /dev/null
+++ b/docs/framework/lit/guides/queries.md
@@ -0,0 +1,141 @@
+---
+id: queries
+title: Queries
+---
+
+New to Lit Query? Start with [Installation](../installation.md) and [Quick Start](../quick-start.md) before wiring query controllers into your elements.
+
+## Query Basics
+
+A query is a declarative dependency on an asynchronous source of data tied to a unique key. Use queries for reading server state. If a function creates, updates, or deletes server data, use a [mutation](./mutations.md) instead.
+
+In Lit, subscribe to a query with [`createQueryController`](../reference/functions/createQueryController.md):
+
+```ts
+import { LitElement, html } from 'lit'
+import { createQueryController } from '@tanstack/lit-query'
+
+class TodosView extends LitElement {
+ private readonly todos = createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+ })
+
+ render() {
+ const query = this.todos()
+
+ if (query.isPending) return html`Loading...`
+ if (query.isError) return html`Error: ${query.error.message}`
+
+ return html`
+
+ ${query.data.map((todo) => html`
${todo.title}
`)}
+
+ `
+ }
+}
+```
+
+The controller needs:
+
+- A `ReactiveControllerHost`, usually `this` inside a `LitElement`
+- A unique `queryKey`
+- A `queryFn` that returns a promise and throws on errors
+
+The returned accessor exposes the current `QueryObserverResult`. Call it in `render`, or read `.current`:
+
+```ts
+const query = this.todos()
+const sameQuery = this.todos.current
+```
+
+## Query States
+
+A query can be in one primary state at a time:
+
+- `isPending` or `status === 'pending'`: no data is available yet
+- `isError` or `status === 'error'`: the query failed and `error` is available
+- `isSuccess` or `status === 'success'`: data is available
+
+The result also includes `isFetching`, which can be true during the initial load or a background refetch.
+
+```ts
+render() {
+ const query = this.todos()
+
+ if (query.status === 'pending') {
+ return html`Loading...`
+ }
+
+ if (query.status === 'error') {
+ return html`Error: ${query.error.message}`
+ }
+
+ return html``
+}
+```
+
+TypeScript will narrow `query.data` after you check `pending` and `error` before reading it.
+
+## Fetch Status
+
+The `status` field describes whether data is available. The `fetchStatus` field describes what the query function is doing:
+
+- `fetchStatus === 'fetching'`: the query is currently fetching.
+- `fetchStatus === 'paused'`: the query wanted to fetch, but fetching is paused.
+- `fetchStatus === 'idle'`: the query is not fetching.
+
+These states are intentionally separate. Background refetching and stale-while-revalidate behavior can produce combinations like:
+
+- A successful query with cached data can have `status === 'success'` and `fetchStatus === 'fetching'` while a background refetch is running.
+- A query with no data can have `status === 'pending'` and `fetchStatus === 'paused'` if fetching cannot start yet.
+
+Use `status` when deciding whether data can be rendered, and use `fetchStatus` or `isFetching` when deciding whether to show a network activity indicator:
+
+```ts
+render() {
+ const query = this.todos()
+
+ if (query.isPending) return html`Loading...`
+ if (query.isError) return html`Error: ${query.error.message}`
+
+ return html`
+ ${query.fetchStatus === 'fetching'
+ ? html`Refreshing...`
+ : null}
+
+ `
+}
+```
+
+## Reactive Query Options
+
+Use an options getter when the query key or query function depends on host state:
+
+```ts
+class UserTodos extends LitElement {
+ static properties = {
+ userId: { type: String },
+ }
+
+ userId = ''
+
+ private readonly todos = createQueryController(this, () => ({
+ queryKey: ['todos', this.userId],
+ queryFn: () => fetchTodos(this.userId),
+ enabled: this.userId.length > 0,
+ }))
+}
+```
+
+The query key is used for caching, refetching, and sharing data between controllers.
+
+## Refetching
+
+The accessor includes `refetch`:
+
+```ts
+html``
+```
+
+For multiple queries that should run at the same time, see [Parallel Queries](./parallel-queries.md).
diff --git a/docs/framework/lit/guides/query-functions.md b/docs/framework/lit/guides/query-functions.md
new file mode 100644
index 00000000000..74845737e82
--- /dev/null
+++ b/docs/framework/lit/guides/query-functions.md
@@ -0,0 +1,81 @@
+---
+id: query-functions
+title: Query Functions
+---
+
+A query function can be any function that returns a promise. The promise should resolve data or throw an error.
+
+```ts
+createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+})
+
+createQueryController(this, () => ({
+ queryKey: ['todo', this.todoId],
+ queryFn: () => fetchTodo(this.todoId),
+}))
+```
+
+## Handling Errors
+
+TanStack Query needs failed query functions to throw or return a rejected promise. Some clients do that automatically. The browser `fetch` API does not, so check `response.ok` yourself:
+
+```ts
+async function fetchTodos(): Promise {
+ const response = await fetch('/api/todos')
+
+ if (!response.ok) {
+ throw new Error('Failed to fetch todos')
+ }
+
+ return response.json() as Promise
+}
+```
+
+The thrown error is available on the query result:
+
+```ts
+const query = this.todos()
+
+if (query.isError) {
+ return html`Error: ${query.error.message}`
+}
+```
+
+## Query Function Context
+
+TanStack Query passes a context object to every query function. It includes:
+
+- `queryKey`: the current query key
+- `client`: the `QueryClient`
+- `signal`: an `AbortSignal` for cancellation
+- `meta`: optional query metadata
+
+```ts
+createQueryController(this, {
+ queryKey: ['todos', { status: 'open' }],
+ queryFn: async ({ queryKey, signal }) => {
+ const [, filters] = queryKey
+ const response = await fetch(`/api/todos?status=${filters.status}`, {
+ signal,
+ })
+ if (!response.ok) throw new Error('Failed to fetch todos')
+ return response.json() as Promise
+ },
+})
+```
+
+Infinite query functions also receive `pageParam`:
+
+```ts
+createInfiniteQueryController(this, {
+ queryKey: ['projects'],
+ queryFn: ({ pageParam }) => fetchProjectsPage(pageParam),
+ initialPageParam: 1,
+ getNextPageParam: (lastPage) =>
+ lastPage.hasMore ? lastPage.page + 1 : undefined,
+})
+```
+
+See [Infinite Queries](./infinite-queries.md) for the controller-specific behavior.
diff --git a/docs/framework/lit/guides/query-invalidation.md b/docs/framework/lit/guides/query-invalidation.md
new file mode 100644
index 00000000000..0227469ad41
--- /dev/null
+++ b/docs/framework/lit/guides/query-invalidation.md
@@ -0,0 +1,83 @@
+---
+id: query-invalidation
+title: Query Invalidation
+---
+
+Waiting for queries to become stale is not always enough. After a mutation succeeds, you often know that related cached data is out of date. Use `queryClient.invalidateQueries` to mark matching queries stale and refetch active observers.
+
+```ts
+queryClient.invalidateQueries()
+
+queryClient.invalidateQueries({
+ queryKey: ['todos'],
+})
+```
+
+When a query is invalidated:
+
+- It is marked stale, overriding any `staleTime`
+- If a matching query is active in a controller, it can refetch in the background
+
+## Invalidation from Mutations
+
+```ts
+private readonly addTodo = createMutationController(this, {
+ mutationFn: addTodo,
+ onSuccess: async () => {
+ await queryClient.invalidateQueries({ queryKey: ['todos'] })
+ },
+})
+```
+
+Use this pattern when the mutation result tells you related cached data is stale. The [Pagination example](../examples/pagination) shows invalidation after project mutations.
+
+## Query Matching
+
+Match a group of queries by prefix:
+
+```ts
+queryClient.invalidateQueries({ queryKey: ['projects'] })
+```
+
+Both of these query keys match:
+
+```ts
+const projectsListKey = ['projects']
+const projectsPageKey = ['projects', 1, 250, false]
+```
+
+Use a more specific key when only one slice should be invalidated:
+
+```ts
+queryClient.invalidateQueries({
+ queryKey: ['projects', this.page],
+})
+```
+
+Use `exact: true` to match only the exact key:
+
+```ts
+queryClient.invalidateQueries({
+ queryKey: ['projects'],
+ exact: true,
+})
+```
+
+## Manual Cache Updates
+
+Invalidation is usually simpler than normalized cache updates. When you do need immediate UI updates, combine targeted cache writes with invalidation:
+
+```ts
+queryClient.setQueryData(['todos'], (existing) => {
+ if (!existing) return existing
+
+ return {
+ ...existing,
+ items: [...existing.items, createdTodo],
+ }
+})
+
+await queryClient.invalidateQueries({ queryKey: ['todos'] })
+```
+
+For rollback with optimistic updates, see the mutation guide and the [Pagination example](../examples/pagination).
diff --git a/docs/framework/lit/guides/query-keys.md b/docs/framework/lit/guides/query-keys.md
new file mode 100644
index 00000000000..8a532e93e7e
--- /dev/null
+++ b/docs/framework/lit/guides/query-keys.md
@@ -0,0 +1,85 @@
+---
+id: query-keys
+title: Query Keys
+---
+
+TanStack Query manages caching by query key. Query keys must be arrays at the top level, and they should uniquely describe the data returned by the query function.
+
+## Simple Keys
+
+Use simple keys for list resources or non-hierarchical data:
+
+```ts
+createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+})
+
+createQueryController(this, {
+ queryKey: ['settings'],
+ queryFn: fetchSettings,
+})
+```
+
+## Keys with Variables
+
+Include variables when they change what the query fetches:
+
+```ts
+createQueryController(this, () => ({
+ queryKey: ['todo', this.todoId],
+ queryFn: () => fetchTodo(this.todoId),
+}))
+
+createQueryController(this, () => ({
+ queryKey: ['projects', { page: this.page, filter: this.filter }],
+ queryFn: () => fetchProjects({ page: this.page, filter: this.filter }),
+}))
+```
+
+The pagination example uses a key shaped like this:
+
+```ts
+type ProjectsQueryKey = readonly ['projects', number, number, boolean]
+
+function projectsQueryKey(
+ page: number,
+ delayMs: number,
+ forceError: boolean,
+): ProjectsQueryKey {
+ return ['projects', page, delayMs, forceError] as const
+}
+```
+
+## Deterministic Hashing
+
+Object key order does not matter inside a query key:
+
+```ts
+const keyA = ['todos', { status, page }]
+const keyB = ['todos', { page, status }]
+```
+
+Array item order does matter:
+
+```ts
+const keyA = ['todos', status, page]
+const keyB = ['todos', page, status]
+```
+
+## Query Keys as Dependencies
+
+If your query function reads a reactive host property, include that value in the query key:
+
+```ts
+class UserTodos extends LitElement {
+ userId = ''
+
+ private readonly todos = createQueryController(this, () => ({
+ queryKey: ['todos', this.userId],
+ queryFn: () => fetchTodos(this.userId),
+ }))
+}
+```
+
+This lets Lit Query cache each user's todos separately and refetch when the host state changes.
diff --git a/docs/framework/lit/guides/reactive-controllers-vs-hooks.md b/docs/framework/lit/guides/reactive-controllers-vs-hooks.md
new file mode 100644
index 00000000000..0cb0530ed0b
--- /dev/null
+++ b/docs/framework/lit/guides/reactive-controllers-vs-hooks.md
@@ -0,0 +1,111 @@
+---
+id: reactive-controllers-vs-hooks
+title: Reactive Controllers vs Hooks
+---
+
+React Query examples use hooks. Lit Query uses reactive controllers.
+
+The job is similar: subscribe a component to a `QueryClient`, read the latest result, and update the component when the cache changes. The integration point is different because Lit components use the `ReactiveControllerHost` interface instead of React's render and hook system.
+
+## Mapping the Concepts
+
+| React Query | Lit Query |
+| --------------------------- | ---------------------------------------------- |
+| `useQuery(options)` | `createQueryController(this, options)` |
+| `useQueries(options)` | `createQueriesController(this, options)` |
+| `useMutation(options)` | `createMutationController(this, options)` |
+| `useInfiniteQuery(options)` | `createInfiniteQueryController(this, options)` |
+| `useIsFetching(options)` | `useIsFetching(this, options)` |
+| `useIsMutating(options)` | `useIsMutating(this, options)` |
+| `useMutationState(options)` | `useMutationState(this, options)` |
+| Hook result object | Callable result accessor |
+| React context provider | `QueryClientProvider` custom element |
+| Component render rerun | `host.requestUpdate()` |
+
+## Host-Bound APIs
+
+Lit APIs that subscribe a component to query or mutation state receive a `host` as the first argument:
+
+```ts
+class TodosView extends LitElement {
+ private readonly todos = createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+ })
+}
+```
+
+`this` is valid because `LitElement` implements `ReactiveControllerHost`. The controller attaches to the host, subscribes when the host connects, requests updates when the query result changes, and unsubscribes when the host disconnects.
+
+The host-bound APIs are [`createQueryController`](../reference/functions/createQueryController.md), [`createQueriesController`](../reference/functions/createQueriesController.md), [`createInfiniteQueryController`](../reference/functions/createInfiniteQueryController.md), [`createMutationController`](../reference/functions/createMutationController.md), [`useIsFetching`](../reference/functions/useIsFetching.md), [`useIsMutating`](../reference/functions/useIsMutating.md), and [`useMutationState`](../reference/functions/useMutationState.md).
+
+[`useQueryClient`](../reference/functions/useQueryClient.md) is different. It is not a reactive controller, does not accept a host, does not subscribe, and throws synchronously if no single default client is available. Use it only for imperative code that runs while exactly one `QueryClientProvider` is connected. Inside host-bound APIs, prefer the provider context or pass an explicit `QueryClient`.
+
+## Reading Results
+
+Lit Query controller creators return a callable accessor with a `current` property:
+
+```ts
+const query = this.todos()
+const sameQuery = this.todos.current
+```
+
+Render methods normally call the accessor:
+
+```ts
+render() {
+ const query = this.todos()
+
+ if (query.isPending) return html`Loading...`
+ if (query.isError) return html`Error: ${query.error.message}`
+
+ return html``
+}
+```
+
+## Reactive Options
+
+If query options depend on host state, pass a function. Lit Query re-reads function accessors during host updates:
+
+```ts
+class ProjectView extends LitElement {
+ static properties = {
+ projectId: { type: Number },
+ }
+
+ projectId = 1
+
+ private readonly project = createQueryController(this, () => ({
+ queryKey: ['project', this.projectId],
+ queryFn: () => fetchProject(this.projectId),
+ }))
+}
+```
+
+If options are static, pass an object. If you mutate a static options object yourself, call the controller helper that causes the observer to see the new options, such as `refetch`, or prefer a function accessor for reactive state.
+
+## Provider Context
+
+Host-bound APIs can receive an explicit `QueryClient`, but most apps render under [`QueryClientProvider`](../reference/classes/QueryClientProvider.md). The provider uses Lit context to deliver the client to descendant controllers.
+
+```ts
+customElements.define('query-client-provider', QueryClientProvider)
+```
+
+```ts
+html`
+
+
+
+`
+```
+
+Custom element registration is always the application's responsibility.
+
+`QueryClientProvider` also registers its client in a process-local fallback store for [`useQueryClient`](../reference/functions/useQueryClient.md) and [`resolveQueryClient`](../reference/functions/resolveQueryClient.md). That fallback is intentionally conservative:
+
+- If no provider is connected, `useQueryClient()` throws.
+- If exactly one distinct client is connected, `useQueryClient()` returns it.
+- If multiple distinct clients are connected in the same JavaScript context, `useQueryClient()` and `resolveQueryClient()` throw because the fallback would be ambiguous.
+
+Multiple roots, micro-frontends, test suites with shared modules, and nested apps should avoid relying on the process-local fallback. Render host-bound controllers under the right provider, pass an explicit `QueryClient` to the controller, or cleanly disconnect providers between tests.
diff --git a/docs/framework/lit/guides/ssr.md b/docs/framework/lit/guides/ssr.md
new file mode 100644
index 00000000000..0c6cce2e476
--- /dev/null
+++ b/docs/framework/lit/guides/ssr.md
@@ -0,0 +1,145 @@
+---
+id: ssr
+title: Server Rendering & Hydration
+---
+
+Lit Query can be used with server rendering by combining Lit SSR with TanStack Query Core hydration APIs re-exported from `@tanstack/lit-query`.
+
+The runnable source for this guide is the [SSR example](../examples/ssr).
+
+## Flow
+
+Server rendering has three phases:
+
+1. Create a per-request `QueryClient`.
+2. Prefetch queries on the server and render Lit HTML with that client.
+3. Dehydrate the cache into the HTML, then hydrate a browser `QueryClient` before the client app renders.
+
+Never share one server `QueryClient` between users or requests.
+
+## Server Prefetch and Render
+
+```ts
+import { render } from '@lit-labs/ssr'
+import { collectResult } from '@lit-labs/ssr/lib/render-result.js'
+import { html } from 'lit'
+import { QueryClient, dehydrate } from '@tanstack/lit-query'
+import { createDataQueryOptions } from './api.js'
+import './app.js'
+
+async function renderPage() {
+ const apiBaseUrl = 'https://example.com'
+ const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ staleTime: 30_000,
+ },
+ },
+ })
+
+ await queryClient.prefetchQuery(createDataQueryOptions(apiBaseUrl))
+
+ const appHtml = await collectResult(
+ render(
+ html``,
+ ),
+ )
+
+ const dehydratedState = dehydrate(queryClient)
+
+ return { appHtml, dehydratedState }
+}
+```
+
+The server passes the same client into the Lit element with a property binding. This lets `createQueryController` read the prefetched cache during server render. If your query function calls `fetch` during SSR, pass an absolute API origin instead of relying on a browser-relative URL.
+
+## Client Hydration
+
+```ts
+import '@lit-labs/ssr-client/lit-element-hydrate-support.js'
+import { QueryClient, hydrate, type DehydratedState } from '@tanstack/lit-query'
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ staleTime: 30_000,
+ },
+ },
+})
+
+const dehydratedState = JSON.parse(
+ document.getElementById('__QUERY_STATE__')?.textContent ?? 'null',
+) as DehydratedState
+
+queryClient.mount()
+hydrate(queryClient, dehydratedState)
+
+const appElement = document.querySelector('ssr-app') as
+ | (HTMLElement & { queryClient?: QueryClient })
+ | null
+
+if (!appElement) {
+ throw new Error('Expected the SSR app element to exist before hydration.')
+}
+
+appElement.queryClient = queryClient
+await import('./app.js')
+```
+
+Unmount the client when the page is unloaded if you mounted it manually:
+
+```ts
+window.addEventListener(
+ 'pagehide',
+ () => {
+ queryClient.unmount()
+ },
+ { once: true },
+)
+```
+
+## Component Pattern
+
+The SSR example creates its controller only after a `queryClient` property is available:
+
+```ts
+import { LitElement } from 'lit'
+import {
+ createQueryController,
+ type QueryClient,
+ type QueryResultAccessor,
+} from '@tanstack/lit-query'
+import { createDataQueryOptions, type DataResponse } from './api.js'
+
+class SsrApp extends LitElement {
+ static properties = {
+ apiBaseUrl: { attribute: 'api-base-url' },
+ queryClient: { attribute: false },
+ }
+
+ apiBaseUrl = ''
+ queryClient?: QueryClient
+ private dataQuery?: QueryResultAccessor
+
+ protected override willUpdate(): void {
+ if (!this.dataQuery && this.queryClient) {
+ this.dataQuery = createQueryController(
+ this,
+ createDataQueryOptions(this.apiBaseUrl),
+ this.queryClient,
+ )
+ }
+ }
+}
+```
+
+This explicit-client pattern is useful for SSR because the client is created by the renderer rather than discovered from a connected DOM provider.
+
+## Serialization
+
+Embed dehydrated state as JSON in the HTML and escape characters that can break out of a script tag. The example server uses a small serializer before replacing `__QUERY_STATE_JSON__` in the built HTML template.
+
+Lit Query re-exports `dehydrate` and `hydrate` from TanStack Query Core. Use `dehydrate(queryClient)` after server prefetching to capture the cache state. In the browser, parse that state, create a fresh `QueryClient`, call `hydrate(queryClient, dehydratedState)`, assign the client to the server-rendered element, and only then import the Lit component so it upgrades with the prefetched cache available.
diff --git a/docs/framework/lit/installation.md b/docs/framework/lit/installation.md
new file mode 100644
index 00000000000..dacbadb9e58
--- /dev/null
+++ b/docs/framework/lit/installation.md
@@ -0,0 +1,109 @@
+---
+id: installation
+title: Installation
+---
+
+> IMPORTANT: The Lit adapter is currently experimental and v0.1. Pin exact versions if you need extra release stability while the API is early.
+
+Install Lit Query with Lit and TanStack Query Core:
+
+```bash
+npm i @tanstack/lit-query @tanstack/query-core lit
+```
+
+or
+
+```bash
+pnpm add @tanstack/lit-query @tanstack/query-core lit
+```
+
+or
+
+```bash
+yarn add @tanstack/lit-query @tanstack/query-core lit
+```
+
+or
+
+```bash
+bun add @tanstack/lit-query @tanstack/query-core lit
+```
+
+`@tanstack/query-core` is a peer dependency of `@tanstack/lit-query`. Even though the Lit docs import user-facing APIs from `@tanstack/lit-query`, your app should install `@tanstack/query-core` explicitly.
+
+## Requirements
+
+Lit Query is intended for Lit 2.8 and newer, including Lit 3. It uses Lit reactive controllers and Lit context, so query consumers should be `ReactiveControllerHost` instances such as `LitElement`.
+
+TanStack Query is optimized for modern browsers:
+
+```txt
+Chrome >= 91
+Firefox >= 90
+Edge >= 91
+Safari >= 15
+iOS >= 15
+Opera >= 77
+```
+
+## Provider Setup
+
+Create a `QueryClient`, provide it with `QueryClientProvider`, and register your custom element. The package exports the provider class but does not call `customElements.define` for you.
+
+### Subclass Pattern
+
+```ts
+import { QueryClient, QueryClientProvider } from '@tanstack/lit-query'
+
+const queryClient = new QueryClient()
+
+class AppQueryProvider extends QueryClientProvider {
+ constructor() {
+ super()
+ this.client = queryClient
+ }
+}
+
+customElements.define('app-query-provider', AppQueryProvider)
+```
+
+```html
+
+
+
+```
+
+### Direct Provider Element
+
+You can register the provider class directly and bind its `client` property from a Lit template. The dot is important: `.client=${queryClient}` is a property binding, not an HTML attribute.
+
+```ts
+import { LitElement, html } from 'lit'
+import { QueryClient, QueryClientProvider } from '@tanstack/lit-query'
+
+const queryClient = new QueryClient()
+
+customElements.define('query-client-provider', QueryClientProvider)
+
+class AppRoot extends LitElement {
+ render() {
+ return html`
+
+
+
+ `
+ }
+}
+```
+
+If a connected provider has no `client`, it throws. See the generated [`QueryClientProvider` reference](./reference/classes/QueryClientProvider.md) for the full contract.
+
+## Render Roots
+
+The snippets in these docs use Lit's default shadow DOM. Lit Query controllers and `QueryClientProvider` work with shadow DOM and light DOM because they use the host lifecycle and Lit context, not global selectors.
+
+Some runnable examples override `createRenderRoot()` and return `this` so their demo markup stays in light DOM for shared page styles and test selectors. That override is not required for Lit Query. Use light DOM only when your app has a separate reason to expose a component's internal markup to global CSS, tests, or non-shadow-DOM integration code.
+
+## Devtools Status
+
+Lit Devtools are not available yet. This is a current adapter limitation, not an installation step.
diff --git a/docs/framework/lit/overview.md b/docs/framework/lit/overview.md
new file mode 100644
index 00000000000..354848d6231
--- /dev/null
+++ b/docs/framework/lit/overview.md
@@ -0,0 +1,93 @@
+---
+id: overview
+title: Overview
+---
+
+> IMPORTANT: The `@tanstack/lit-query` package is currently experimental and v0.1. Expect the Lit adapter API and docs to keep evolving. If you use it in production while it is early, pin the package to a patch version and upgrade deliberately.
+
+The `@tanstack/lit-query` package is the Lit adapter for TanStack Query. It gives Lit applications reactive controller APIs for fetching, caching, synchronizing, and updating server state.
+
+TanStack Query manages server state: data that is owned by a remote system, fetched asynchronously, shared across screens, and potentially changed by someone else at any time. It handles caching, request deduplication, stale data, background refetching, mutations, invalidation, pagination, and garbage collection.
+
+Lit Query exposes those features through [Lit reactive controllers](https://lit.dev/docs/composition/controllers/). A Lit reactive controller is attached to a `ReactiveControllerHost`, usually a `LitElement`. Lit Query controllers subscribe to the `QueryClient`, request host updates when results change, and are cleaned up with the host lifecycle.
+
+## Core APIs
+
+Most Lit applications use these APIs:
+
+- [`QueryClientProvider`](./reference/classes/QueryClientProvider.md) to provide a `QueryClient` through Lit context
+- [`createQueryController`](./reference/functions/createQueryController.md) for queries
+- [`createQueriesController`](./reference/functions/createQueriesController.md) for dynamic parallel queries
+- [`createMutationController`](./reference/functions/createMutationController.md) for mutations
+- [`createInfiniteQueryController`](./reference/functions/createInfiniteQueryController.md) for infinite queries
+- [`useIsFetching`](./reference/functions/useIsFetching.md), [`useIsMutating`](./reference/functions/useIsMutating.md), and [`useMutationState`](./reference/functions/useMutationState.md) for cache state indicators
+
+The adapter also re-exports TanStack Query Core APIs from `@tanstack/lit-query`, so examples in the Lit docs use `@tanstack/lit-query` as the user-facing import path.
+
+## A First Query
+
+```ts
+import { LitElement, html } from 'lit'
+import {
+ QueryClient,
+ QueryClientProvider,
+ createQueryController,
+} from '@tanstack/lit-query'
+
+const queryClient = new QueryClient()
+
+class AppQueryProvider extends QueryClientProvider {
+ constructor() {
+ super()
+ this.client = queryClient
+ }
+}
+
+customElements.define('app-query-provider', AppQueryProvider)
+
+class RepoStats extends LitElement {
+ private readonly repo = createQueryController(this, {
+ queryKey: ['repoData'],
+ queryFn: async () => {
+ const response = await fetch(
+ 'https://api.github.com/repos/TanStack/query',
+ )
+ if (!response.ok) throw new Error('Failed to fetch repo data')
+ return response.json() as Promise<{
+ name: string
+ description: string
+ stargazers_count: number
+ }>
+ },
+ })
+
+ render() {
+ const query = this.repo()
+
+ if (query.isPending) return html`Loading...`
+ if (query.isError) return html`Error: ${query.error.message}`
+
+ return html`
+
${query.data.name}
+
${query.data.description}
+ ${query.data.stargazers_count} stars
+ `
+ }
+}
+
+customElements.define('repo-stats', RepoStats)
+```
+
+Render the provider above your query consumers:
+
+```html
+
+
+
+```
+
+## Status Notes
+
+Lit Devtools are not available yet. Use the cache APIs and the generated API reference while the adapter matures.
+
+Start with [Installation](./installation.md), then [Quick Start](./quick-start.md), and use the [Reactive Controllers vs Hooks](./guides/reactive-controllers-vs-hooks.md) guide if you are coming from React Query.
diff --git a/docs/framework/lit/quick-start.md b/docs/framework/lit/quick-start.md
new file mode 100644
index 00000000000..69bff6c8f11
--- /dev/null
+++ b/docs/framework/lit/quick-start.md
@@ -0,0 +1,83 @@
+---
+id: quick-start
+title: Quick Start
+---
+
+This snippet shows the three core Lit Query concepts:
+
+- [Queries](./guides/queries.md)
+- [Mutations](./guides/mutations.md)
+- [Query Invalidation](./guides/query-invalidation.md)
+
+For complete runnable examples, see [Basic](./examples/basic), [Pagination](./examples/pagination), and [SSR](./examples/ssr).
+
+```ts
+import { LitElement, html } from 'lit'
+import {
+ QueryClient,
+ QueryClientProvider,
+ createMutationController,
+ createQueryController,
+} from '@tanstack/lit-query'
+import { addTodo, getTodos } from './api'
+
+const queryClient = new QueryClient()
+
+class AppQueryProvider extends QueryClientProvider {
+ constructor() {
+ super()
+ this.client = queryClient
+ }
+}
+
+customElements.define('app-query-provider', AppQueryProvider)
+
+class TodosView extends LitElement {
+ private readonly todos = createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: getTodos,
+ })
+
+ private readonly createTodo = createMutationController(this, {
+ mutationFn: addTodo,
+ onSuccess: async () => {
+ await queryClient.invalidateQueries({ queryKey: ['todos'] })
+ },
+ })
+
+ render() {
+ const query = this.todos()
+ const mutation = this.createTodo()
+
+ if (query.isPending) return html`Loading...`
+ if (query.isError) return html`Error: ${query.error.message}`
+
+ return html`
+
+ ${query.data.map((todo) => html`
${todo.title}
`)}
+
+
+
+ `
+ }
+}
+
+customElements.define('todos-view', TodosView)
+```
+
+Mount the provider around your component:
+
+```html
+
+
+
+```
+
+The controllers are created with `this` because a `LitElement` is a `ReactiveControllerHost`. Lit Query uses the host lifecycle to subscribe, request updates, and clean up when the element disconnects.
+
+Continue with [Reactive Controllers vs Hooks](./guides/reactive-controllers-vs-hooks.md) if you know React Query, or go straight to [Queries](./guides/queries.md).
diff --git a/docs/framework/lit/reference/classes/QueryClientProvider.md b/docs/framework/lit/reference/classes/QueryClientProvider.md
new file mode 100644
index 00000000000..df14c2769bb
--- /dev/null
+++ b/docs/framework/lit/reference/classes/QueryClientProvider.md
@@ -0,0 +1,98 @@
+---
+id: QueryClientProvider
+title: QueryClientProvider
+---
+
+# Class: QueryClientProvider
+
+Defined in: [packages/lit-query/src/QueryClientProvider.ts:64](https://github.com/TanStack/query/blob/main/packages/lit-query/src/QueryClientProvider.ts#L64)
+
+Lit element that provides a `QueryClient` to descendant Lit Query
+controllers through Lit context.
+
+The `client` is a property, not an attribute. When rendering this element in
+a Lit template, bind it with property binding: `.client=${queryClient}`.
+The provider throws if it connects without a client, or if an already
+connected provider has its client cleared.
+
+This class is not registered as a custom element by the package. Applications
+must register either a subclass or the class itself with
+`customElements.define`.
+
+## Examples
+
+```ts
+import { html, LitElement } from 'lit'
+import { QueryClient, QueryClientProvider } from '@tanstack/lit-query'
+
+const queryClient = new QueryClient()
+
+class AppQueryProvider extends QueryClientProvider {
+ constructor() {
+ super()
+ this.client = queryClient
+ }
+}
+
+customElements.define('app-query-provider', AppQueryProvider)
+
+class AppRoot extends LitElement {
+ render() {
+ return html``
+ }
+}
+```
+
+```ts
+import { html } from 'lit'
+import { QueryClient, QueryClientProvider } from '@tanstack/lit-query'
+
+const queryClient = new QueryClient()
+
+customElements.define('query-client-provider', QueryClientProvider)
+
+const view = html`
+
+
+
+`
+```
+
+## Extends
+
+- `LitElement`
+
+## Constructors
+
+### Constructor
+
+```ts
+new QueryClientProvider(): QueryClientProvider;
+```
+
+Defined in: [packages/lit-query/src/QueryClientProvider.ts:82](https://github.com/TanStack/query/blob/main/packages/lit-query/src/QueryClientProvider.ts#L82)
+
+#### Returns
+
+`QueryClientProvider`
+
+#### Overrides
+
+```ts
+LitElement.constructor
+```
+
+## Properties
+
+### client
+
+```ts
+client: QueryClient;
+```
+
+Defined in: [packages/lit-query/src/QueryClientProvider.ts:76](https://github.com/TanStack/query/blob/main/packages/lit-query/src/QueryClientProvider.ts#L76)
+
+The `QueryClient` provided to descendant controllers and global fallback
+helpers while this provider is connected.
+
+Bind this as a property in Lit templates with `.client=${queryClient}`.
diff --git a/docs/framework/lit/reference/functions/createInfiniteQueryController.md b/docs/framework/lit/reference/functions/createInfiniteQueryController.md
new file mode 100644
index 00000000000..63bccc835af
--- /dev/null
+++ b/docs/framework/lit/reference/functions/createInfiniteQueryController.md
@@ -0,0 +1,104 @@
+---
+id: createInfiniteQueryController
+title: createInfiniteQueryController
+---
+
+# Function: createInfiniteQueryController()
+
+```ts
+function createInfiniteQueryController(
+ host,
+ options,
+queryClient?): InfiniteQueryResultAccessor;
+```
+
+Defined in: [packages/lit-query/src/createInfiniteQueryController.ts:364](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createInfiniteQueryController.ts#L364)
+
+Creates a Lit reactive controller that subscribes the host to an infinite
+query.
+
+The returned accessor is callable and also exposes `current`, `refetch`,
+`fetchNextPage`, `fetchPreviousPage`, and `destroy`. When `options` is a
+function, it is re-read during host updates so query keys and options can
+follow reactive host state.
+
+If `queryClient` is omitted, the controller resolves the client from the
+nearest connected `QueryClientProvider`.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `Error`
+
+### TData
+
+`TData` = `InfiniteData`\<`TQueryFnData`, `unknown`\>
+
+### TQueryKey
+
+`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
+
+### TPageParam
+
+`TPageParam` = `unknown`
+
+## Parameters
+
+### host
+
+`ReactiveControllerHost`
+
+The Lit reactive controller host that owns the infinite query
+subscription.
+
+### options
+
+[`Accessor`](../type-aliases/Accessor.md)\<[`CreateInfiniteQueryOptions`](../type-aliases/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>\>
+
+Infinite query observer options, or a getter that returns
+options.
+
+### queryClient?
+
+`QueryClient`
+
+Optional explicit query client. Provide this for
+controllers that should not resolve a client from Lit context.
+
+## Returns
+
+[`InfiniteQueryResultAccessor`](../type-aliases/InfiniteQueryResultAccessor.md)\<`TData`, `TError`\>
+
+An accessor for the latest infinite query result with page helper
+methods.
+
+## Example
+
+```ts
+import { LitElement, html } from 'lit'
+import { createInfiniteQueryController } from '@tanstack/lit-query'
+
+class ProjectsView extends LitElement {
+ private readonly projects = createInfiniteQueryController(this, {
+ queryKey: ['projects'],
+ queryFn: ({ pageParam }) => fetchProjects(pageParam),
+ initialPageParam: 0,
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
+ })
+
+ render() {
+ const query = this.projects()
+
+ return html`
+
+ `
+ }
+}
+```
diff --git a/docs/framework/lit/reference/functions/createMutationController.md b/docs/framework/lit/reference/functions/createMutationController.md
new file mode 100644
index 00000000000..3c870e06fe2
--- /dev/null
+++ b/docs/framework/lit/reference/functions/createMutationController.md
@@ -0,0 +1,96 @@
+---
+id: createMutationController
+title: createMutationController
+---
+
+# Function: createMutationController()
+
+```ts
+function createMutationController(
+ host,
+ options,
+queryClient?): MutationResultAccessor;
+```
+
+Defined in: [packages/lit-query/src/createMutationController.ts:338](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createMutationController.ts#L338)
+
+Creates a Lit reactive controller that subscribes the host to a mutation.
+
+The returned accessor is callable and also exposes `current`, `mutate`,
+`mutateAsync`, `reset`, and `destroy`. When `options` is a function, it is
+re-read during host updates so mutation options can follow reactive host
+state.
+
+If `queryClient` is omitted, the controller resolves the client from the
+nearest connected `QueryClientProvider`.
+
+## Type Parameters
+
+### TData
+
+`TData` = `unknown`
+
+### TError
+
+`TError` = `Error`
+
+### TVariables
+
+`TVariables` = `void`
+
+### TOnMutateResult
+
+`TOnMutateResult` = `unknown`
+
+## Parameters
+
+### host
+
+`ReactiveControllerHost`
+
+The Lit reactive controller host that owns the mutation
+subscription.
+
+### options
+
+[`Accessor`](../type-aliases/Accessor.md)\<[`CreateMutationOptions`](../type-aliases/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>\>
+
+Mutation observer options, or a getter that returns options.
+
+### queryClient?
+
+`QueryClient`
+
+Optional explicit query client. Provide this for
+controllers that should not resolve a client from Lit context.
+
+## Returns
+
+[`MutationResultAccessor`](../type-aliases/MutationResultAccessor.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>
+
+An accessor for the latest mutation result with mutation helper
+methods.
+
+## Example
+
+```ts
+import { LitElement, html } from 'lit'
+import { createMutationController } from '@tanstack/lit-query'
+
+class AddTodoForm extends LitElement {
+ private readonly addTodo = createMutationController(this, {
+ mutationFn: (title: string) =>
+ fetch('/api/todos', { method: 'POST', body: JSON.stringify({ title }) }),
+ })
+
+ render() {
+ const mutation = this.addTodo()
+
+ return html`
+
+ `
+ }
+}
+```
diff --git a/docs/framework/lit/reference/functions/createQueriesController.md b/docs/framework/lit/reference/functions/createQueriesController.md
new file mode 100644
index 00000000000..db5e74399cb
--- /dev/null
+++ b/docs/framework/lit/reference/functions/createQueriesController.md
@@ -0,0 +1,90 @@
+---
+id: createQueriesController
+title: createQueriesController
+---
+
+# Function: createQueriesController()
+
+```ts
+function createQueriesController(
+ host,
+ options,
+queryClient?): QueriesResultAccessor;
+```
+
+Defined in: [packages/lit-query/src/createQueriesController.ts:615](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueriesController.ts#L615)
+
+Creates a Lit reactive controller that subscribes the host to multiple
+queries.
+
+The returned accessor is callable and also exposes `current` and `destroy`.
+When `options` or `options.queries` is a function, it is re-read during host
+updates so the query list can follow reactive host state.
+
+If `queryClient` is omitted, the controller resolves the client from the
+nearest connected `QueryClientProvider`.
+
+## Type Parameters
+
+### TQueryOptions
+
+`TQueryOptions` *extends* `any`[]
+
+### TCombinedResult
+
+`TCombinedResult` = `CreateQueriesResults`\<`TQueryOptions`\>
+
+## Parameters
+
+### host
+
+`ReactiveControllerHost`
+
+The Lit reactive controller host that owns the queries
+subscription.
+
+### options
+
+[`Accessor`](../type-aliases/Accessor.md)\<[`CreateQueriesControllerOptions`](../type-aliases/CreateQueriesControllerOptions.md)\<`TQueryOptions`, `TCombinedResult`\>\>
+
+Queries controller options, or a getter that returns options.
+
+### queryClient?
+
+`QueryClient`
+
+Optional explicit query client. Provide this for
+controllers that should not resolve a client from Lit context.
+
+## Returns
+
+[`QueriesResultAccessor`](../type-aliases/QueriesResultAccessor.md)\<`TCombinedResult`\>
+
+An accessor for the latest query results, or the value returned by
+`combine`.
+
+## Example
+
+```ts
+import { LitElement, html } from 'lit'
+import { createQueriesController } from '@tanstack/lit-query'
+
+class DashboardView extends LitElement {
+ private readonly dashboard = createQueriesController(this, {
+ queries: [
+ { queryKey: ['stats'], queryFn: fetchStats },
+ { queryKey: ['projects'], queryFn: fetchProjects },
+ ],
+ combine: ([stats, projects]) => ({
+ stats: stats.data,
+ projects: projects.data ?? [],
+ isPending: stats.isPending || projects.isPending,
+ }),
+ })
+
+ render() {
+ const dashboard = this.dashboard()
+ return html`
Projects: ${dashboard.projects.length}
`
+ }
+}
+```
diff --git a/docs/framework/lit/reference/functions/createQueryController.md b/docs/framework/lit/reference/functions/createQueryController.md
new file mode 100644
index 00000000000..11e52770bbd
--- /dev/null
+++ b/docs/framework/lit/reference/functions/createQueryController.md
@@ -0,0 +1,97 @@
+---
+id: createQueryController
+title: createQueryController
+---
+
+# Function: createQueryController()
+
+```ts
+function createQueryController(
+ host,
+ options,
+queryClient?): QueryResultAccessor;
+```
+
+Defined in: [packages/lit-query/src/createQueryController.ts:319](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueryController.ts#L319)
+
+Creates a Lit reactive controller that subscribes the host to a single query.
+
+The returned accessor is callable and also exposes `current`, `refetch`,
+`suspense`, and `destroy`. When `options` is a function, it is re-read during
+host updates so query keys and options can follow reactive host state.
+
+If `queryClient` is omitted, the controller resolves the client from the
+nearest connected `QueryClientProvider`.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `Error`
+
+### TData
+
+`TData` = `TQueryFnData`
+
+### TQueryData
+
+`TQueryData` = `TQueryFnData`
+
+### TQueryKey
+
+`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
+
+## Parameters
+
+### host
+
+`ReactiveControllerHost`
+
+The Lit reactive controller host that owns the query
+subscription.
+
+### options
+
+[`Accessor`](../type-aliases/Accessor.md)\<[`CreateQueryOptions`](../type-aliases/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryData`, `TQueryKey`\>\>
+
+Query observer options, or a getter that returns options.
+
+### queryClient?
+
+`QueryClient`
+
+Optional explicit query client. Provide this for
+controllers that should not resolve a client from Lit context.
+
+## Returns
+
+[`QueryResultAccessor`](../type-aliases/QueryResultAccessor.md)\<`TData`, `TError`\>
+
+An accessor for the latest query result with query helper methods.
+
+## Example
+
+```ts
+import { LitElement, html } from 'lit'
+import { createQueryController } from '@tanstack/lit-query'
+
+class TodosView extends LitElement {
+ private readonly todos = createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: async () => fetch('/api/todos').then((r) => r.json()),
+ })
+
+ render() {
+ const query = this.todos()
+
+ if (query.isPending) return html`Loading...`
+ if (query.isError) return html`Error`
+
+ return html`
${query.data.map((todo) => html`
${todo.title}
`)}
`
+ }
+}
+```
diff --git a/docs/framework/lit/reference/functions/getDefaultQueryClient.md b/docs/framework/lit/reference/functions/getDefaultQueryClient.md
new file mode 100644
index 00000000000..4c9ff19db48
--- /dev/null
+++ b/docs/framework/lit/reference/functions/getDefaultQueryClient.md
@@ -0,0 +1,22 @@
+---
+id: getDefaultQueryClient
+title: getDefaultQueryClient
+---
+
+# Function: getDefaultQueryClient()
+
+```ts
+function getDefaultQueryClient(): QueryClient | undefined;
+```
+
+Defined in: [packages/lit-query/src/context.ts:72](https://github.com/TanStack/query/blob/main/packages/lit-query/src/context.ts#L72)
+
+Returns the registered default `QueryClient`, if exactly one default client is
+available.
+
+## Returns
+
+`QueryClient` \| `undefined`
+
+The default query client, or `undefined` when there is no registered
+client or more than one registered client.
diff --git a/docs/framework/lit/reference/functions/infiniteQueryOptions.md b/docs/framework/lit/reference/functions/infiniteQueryOptions.md
new file mode 100644
index 00000000000..3ac26702f12
--- /dev/null
+++ b/docs/framework/lit/reference/functions/infiniteQueryOptions.md
@@ -0,0 +1,63 @@
+---
+id: infiniteQueryOptions
+title: infiniteQueryOptions
+---
+
+# Function: infiniteQueryOptions()
+
+```ts
+function infiniteQueryOptions(options): InfiniteQueryObserverOptions;
+```
+
+Defined in: [packages/lit-query/src/infiniteQueryOptions.ts:26](https://github.com/TanStack/query/blob/main/packages/lit-query/src/infiniteQueryOptions.ts#L26)
+
+Preserves and types infinite query options for reuse across Lit Query APIs.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `Error`
+
+### TData
+
+`TData` = `InfiniteData`\<`TQueryFnData`, `unknown`\>
+
+### TQueryKey
+
+`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
+
+### TPageParam
+
+`TPageParam` = `unknown`
+
+## Parameters
+
+### options
+
+`InfiniteQueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
+
+Infinite query options to preserve.
+
+## Returns
+
+`InfiniteQueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
+
+The same options object.
+
+## Example
+
+```ts
+import { infiniteQueryOptions } from '@tanstack/lit-query'
+
+const projectsOptions = infiniteQueryOptions({
+ queryKey: ['projects'],
+ queryFn: ({ pageParam }) => fetchProjects(pageParam),
+ initialPageParam: 0,
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
+})
+```
diff --git a/docs/framework/lit/reference/functions/mutationOptions.md b/docs/framework/lit/reference/functions/mutationOptions.md
new file mode 100644
index 00000000000..966fb849098
--- /dev/null
+++ b/docs/framework/lit/reference/functions/mutationOptions.md
@@ -0,0 +1,57 @@
+---
+id: mutationOptions
+title: mutationOptions
+---
+
+# Function: mutationOptions()
+
+```ts
+function mutationOptions(options): MutationObserverOptions;
+```
+
+Defined in: [packages/lit-query/src/mutationOptions.ts:22](https://github.com/TanStack/query/blob/main/packages/lit-query/src/mutationOptions.ts#L22)
+
+Preserves and types mutation options for reuse across Lit Query APIs.
+
+## Type Parameters
+
+### TData
+
+`TData` = `unknown`
+
+### TError
+
+`TError` = `Error`
+
+### TVariables
+
+`TVariables` = `void`
+
+### TOnMutateResult
+
+`TOnMutateResult` = `unknown`
+
+## Parameters
+
+### options
+
+`MutationObserverOptions`\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>
+
+Mutation options to preserve.
+
+## Returns
+
+`MutationObserverOptions`\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>
+
+The same options object.
+
+## Example
+
+```ts
+import { mutationOptions } from '@tanstack/lit-query'
+
+const addTodoOptions = mutationOptions({
+ mutationKey: ['add-todo'],
+ mutationFn: (title: string) => addTodo(title),
+})
+```
diff --git a/docs/framework/lit/reference/functions/queryOptions.md b/docs/framework/lit/reference/functions/queryOptions.md
new file mode 100644
index 00000000000..2c43233ca26
--- /dev/null
+++ b/docs/framework/lit/reference/functions/queryOptions.md
@@ -0,0 +1,147 @@
+---
+id: queryOptions
+title: queryOptions
+---
+
+# Function: queryOptions()
+
+## Call Signature
+
+```ts
+function queryOptions(options): Omit, "queryFn"> & object & object;
+```
+
+Defined in: [packages/lit-query/src/queryOptions.ts:94](https://github.com/TanStack/query/blob/main/packages/lit-query/src/queryOptions.ts#L94)
+
+Brands query options so the `queryKey` carries the query function data and
+error types across TanStack Query APIs.
+
+### Type Parameters
+
+#### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+#### TError
+
+`TError` = `Error`
+
+#### TData
+
+`TData` = `TQueryFnData`
+
+#### TQueryKey
+
+`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
+
+### Parameters
+
+#### options
+
+[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
+
+Query options to preserve and brand.
+
+### Returns
+
+`Omit`\<`QueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`, `never`\>, `"queryFn"`\> & `object` & `object`
+
+The same options object with a typed `queryKey`.
+
+### Example
+
+```ts
+import { queryOptions } from '@tanstack/lit-query'
+
+const todosOptions = queryOptions({
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+ initialData: [],
+})
+```
+
+## Call Signature
+
+```ts
+function queryOptions(options): OmitKeyof, "queryFn"> & object & object;
+```
+
+Defined in: [packages/lit-query/src/queryOptions.ts:112](https://github.com/TanStack/query/blob/main/packages/lit-query/src/queryOptions.ts#L112)
+
+Brands query options so the `queryKey` carries the query function data and
+error types across TanStack Query APIs.
+
+### Type Parameters
+
+#### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+#### TError
+
+`TError` = `Error`
+
+#### TData
+
+`TData` = `TQueryFnData`
+
+#### TQueryKey
+
+`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
+
+### Parameters
+
+#### options
+
+[`UnusedSkipTokenOptions`](../type-aliases/UnusedSkipTokenOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
+
+Query options to preserve and brand.
+
+### Returns
+
+`OmitKeyof`\<`QueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`, `never`\>, `"queryFn"`\> & `object` & `object`
+
+The same options object with a typed `queryKey`.
+
+## Call Signature
+
+```ts
+function queryOptions(options): QueryObserverOptions & object & object;
+```
+
+Defined in: [packages/lit-query/src/queryOptions.ts:130](https://github.com/TanStack/query/blob/main/packages/lit-query/src/queryOptions.ts#L130)
+
+Brands query options so the `queryKey` carries the query function data and
+error types across TanStack Query APIs.
+
+### Type Parameters
+
+#### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+#### TError
+
+`TError` = `Error`
+
+#### TData
+
+`TData` = `TQueryFnData`
+
+#### TQueryKey
+
+`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
+
+### Parameters
+
+#### options
+
+[`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
+
+Query options to preserve and brand.
+
+### Returns
+
+`QueryObserverOptions`\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`, `never`\> & `object` & `object`
+
+The same options object with a typed `queryKey`.
diff --git a/docs/framework/lit/reference/functions/registerDefaultQueryClient.md b/docs/framework/lit/reference/functions/registerDefaultQueryClient.md
new file mode 100644
index 00000000000..d3174f600ca
--- /dev/null
+++ b/docs/framework/lit/reference/functions/registerDefaultQueryClient.md
@@ -0,0 +1,30 @@
+---
+id: registerDefaultQueryClient
+title: registerDefaultQueryClient
+---
+
+# Function: registerDefaultQueryClient()
+
+```ts
+function registerDefaultQueryClient(client): void;
+```
+
+Defined in: [packages/lit-query/src/context.ts:32](https://github.com/TanStack/query/blob/main/packages/lit-query/src/context.ts#L32)
+
+Registers a `QueryClient` as a process-local fallback for APIs that resolve a
+client without an explicit argument.
+
+`QueryClientProvider` calls this automatically while it is connected. Prefer
+passing an explicit client or rendering under a provider when possible.
+
+## Parameters
+
+### client
+
+`QueryClient`
+
+The query client to register as the current default.
+
+## Returns
+
+`void`
diff --git a/docs/framework/lit/reference/functions/resolveQueryClient.md b/docs/framework/lit/reference/functions/resolveQueryClient.md
new file mode 100644
index 00000000000..cfb0ba226ac
--- /dev/null
+++ b/docs/framework/lit/reference/functions/resolveQueryClient.md
@@ -0,0 +1,29 @@
+---
+id: resolveQueryClient
+title: resolveQueryClient
+---
+
+# Function: resolveQueryClient()
+
+```ts
+function resolveQueryClient(explicit?): QueryClient;
+```
+
+Defined in: [packages/lit-query/src/context.ts:118](https://github.com/TanStack/query/blob/main/packages/lit-query/src/context.ts#L118)
+
+Resolves an explicit `QueryClient` or falls back to `useQueryClient`.
+
+## Parameters
+
+### explicit?
+
+`QueryClient`
+
+Optional client supplied by the caller.
+
+## Returns
+
+`QueryClient`
+
+The explicit client when provided, otherwise the current default
+client.
diff --git a/docs/framework/lit/reference/functions/unregisterDefaultQueryClient.md b/docs/framework/lit/reference/functions/unregisterDefaultQueryClient.md
new file mode 100644
index 00000000000..8c82f497c35
--- /dev/null
+++ b/docs/framework/lit/reference/functions/unregisterDefaultQueryClient.md
@@ -0,0 +1,29 @@
+---
+id: unregisterDefaultQueryClient
+title: unregisterDefaultQueryClient
+---
+
+# Function: unregisterDefaultQueryClient()
+
+```ts
+function unregisterDefaultQueryClient(client): void;
+```
+
+Defined in: [packages/lit-query/src/context.ts:45](https://github.com/TanStack/query/blob/main/packages/lit-query/src/context.ts#L45)
+
+Unregisters a client previously registered with
+`registerDefaultQueryClient`.
+
+`QueryClientProvider` calls this automatically when it disconnects.
+
+## Parameters
+
+### client
+
+`QueryClient`
+
+The query client registration to release.
+
+## Returns
+
+`void`
diff --git a/docs/framework/lit/reference/functions/useIsFetching.md b/docs/framework/lit/reference/functions/useIsFetching.md
new file mode 100644
index 00000000000..6cfd72bb4e5
--- /dev/null
+++ b/docs/framework/lit/reference/functions/useIsFetching.md
@@ -0,0 +1,67 @@
+---
+id: useIsFetching
+title: useIsFetching
+---
+
+# Function: useIsFetching()
+
+```ts
+function useIsFetching(
+ host,
+ filters,
+ queryClient?): IsFetchingAccessor;
+```
+
+Defined in: [packages/lit-query/src/useIsFetching.ts:147](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useIsFetching.ts#L147)
+
+Creates a Lit reactive controller that tracks how many matching queries are
+currently fetching.
+
+When `filters` is a function, it is re-read during host updates so the count
+can follow reactive host state. If `queryClient` is omitted, the controller
+resolves the client from the nearest connected `QueryClientProvider`.
+
+## Parameters
+
+### host
+
+`ReactiveControllerHost`
+
+The Lit reactive controller host that owns the cache
+subscription.
+
+### filters
+
+[`Accessor`](../type-aliases/Accessor.md)\<`QueryFilters`\\> = `{}`
+
+Query filters, or a getter that returns query filters.
+
+### queryClient?
+
+`QueryClient`
+
+Optional explicit query client. Provide this for
+controllers that should not resolve a client from Lit context.
+
+## Returns
+
+[`IsFetchingAccessor`](../type-aliases/IsFetchingAccessor.md)
+
+An accessor for the current number of matching fetching queries.
+
+## Example
+
+```ts
+import { LitElement, html } from 'lit'
+import { useIsFetching } from '@tanstack/lit-query'
+
+class TodosStatus extends LitElement {
+ private readonly todosFetching = useIsFetching(this, {
+ queryKey: ['todos'],
+ })
+
+ render() {
+ return html`${this.todosFetching()} active todo fetches`
+ }
+}
+```
diff --git a/docs/framework/lit/reference/functions/useIsMutating.md b/docs/framework/lit/reference/functions/useIsMutating.md
new file mode 100644
index 00000000000..1991ee25266
--- /dev/null
+++ b/docs/framework/lit/reference/functions/useIsMutating.md
@@ -0,0 +1,67 @@
+---
+id: useIsMutating
+title: useIsMutating
+---
+
+# Function: useIsMutating()
+
+```ts
+function useIsMutating(
+ host,
+ filters,
+ queryClient?): IsMutatingAccessor;
+```
+
+Defined in: [packages/lit-query/src/useIsMutating.ts:147](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useIsMutating.ts#L147)
+
+Creates a Lit reactive controller that tracks how many matching mutations are
+currently pending.
+
+When `filters` is a function, it is re-read during host updates so the count
+can follow reactive host state. If `queryClient` is omitted, the controller
+resolves the client from the nearest connected `QueryClientProvider`.
+
+## Parameters
+
+### host
+
+`ReactiveControllerHost`
+
+The Lit reactive controller host that owns the cache
+subscription.
+
+### filters
+
+[`Accessor`](../type-aliases/Accessor.md)\<`MutationFilters`\<`unknown`, `Error`, `unknown`, `unknown`\>\> = `{}`
+
+Mutation filters, or a getter that returns mutation filters.
+
+### queryClient?
+
+`QueryClient`
+
+Optional explicit query client. Provide this for
+controllers that should not resolve a client from Lit context.
+
+## Returns
+
+[`IsMutatingAccessor`](../type-aliases/IsMutatingAccessor.md)
+
+An accessor for the current number of matching pending mutations.
+
+## Example
+
+```ts
+import { LitElement, html } from 'lit'
+import { useIsMutating } from '@tanstack/lit-query'
+
+class MutationStatus extends LitElement {
+ private readonly savesPending = useIsMutating(this, {
+ mutationKey: ['save-project'],
+ })
+
+ render() {
+ return html`${this.savesPending()} saves pending`
+ }
+}
+```
diff --git a/docs/framework/lit/reference/functions/useMutationState.md b/docs/framework/lit/reference/functions/useMutationState.md
new file mode 100644
index 00000000000..f12f55d38b2
--- /dev/null
+++ b/docs/framework/lit/reference/functions/useMutationState.md
@@ -0,0 +1,75 @@
+---
+id: useMutationState
+title: useMutationState
+---
+
+# Function: useMutationState()
+
+```ts
+function useMutationState(
+ host,
+ options,
+queryClient?): MutationStateAccessor;
+```
+
+Defined in: [packages/lit-query/src/useMutationState.ts:187](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useMutationState.ts#L187)
+
+Creates a Lit reactive controller that selects state from matching mutations
+in the mutation cache.
+
+When `options.filters` is a function, it is re-read during host updates so
+the selection can follow reactive host state. If `queryClient` is omitted,
+the controller resolves the client from the nearest connected
+`QueryClientProvider`.
+
+## Type Parameters
+
+### TResult
+
+`TResult` = `MutationState`\<`unknown`, `unknown`, `unknown`, `unknown`\>
+
+## Parameters
+
+### host
+
+`ReactiveControllerHost`
+
+The Lit reactive controller host that owns the mutation cache
+subscription.
+
+### options
+
+[`MutationStateOptions`](../type-aliases/MutationStateOptions.md)\<`TResult`\> = `{}`
+
+Mutation state filters and optional selector.
+
+### queryClient?
+
+`QueryClient`
+
+Optional explicit query client. Provide this for
+controllers that should not resolve a client from Lit context.
+
+## Returns
+
+[`MutationStateAccessor`](../type-aliases/MutationStateAccessor.md)\<`TResult`\>
+
+An accessor for the selected mutation state array.
+
+## Example
+
+```ts
+import { LitElement, html } from 'lit'
+import { useMutationState } from '@tanstack/lit-query'
+
+class PendingUploads extends LitElement {
+ private readonly uploads = useMutationState(this, {
+ filters: { mutationKey: ['upload'], status: 'pending' },
+ select: (mutation) => mutation.state.variables as File,
+ })
+
+ render() {
+ return html`${this.uploads().length} uploads pending`
+ }
+}
+```
diff --git a/docs/framework/lit/reference/functions/useQueryClient.md b/docs/framework/lit/reference/functions/useQueryClient.md
new file mode 100644
index 00000000000..72db893d0d5
--- /dev/null
+++ b/docs/framework/lit/reference/functions/useQueryClient.md
@@ -0,0 +1,25 @@
+---
+id: useQueryClient
+title: useQueryClient
+---
+
+# Function: useQueryClient()
+
+```ts
+function useQueryClient(): QueryClient;
+```
+
+Defined in: [packages/lit-query/src/context.ts:98](https://github.com/TanStack/query/blob/main/packages/lit-query/src/context.ts#L98)
+
+Resolves the current default `QueryClient` registered by a connected
+`QueryClientProvider`.
+
+This helper is useful outside a Lit reactive controller when a single
+provider is mounted. It throws if no client is registered or if multiple
+clients are mounted and the default would be ambiguous.
+
+## Returns
+
+`QueryClient`
+
+The single registered query client.
diff --git a/docs/framework/lit/reference/index.md b/docs/framework/lit/reference/index.md
new file mode 100644
index 00000000000..77ef5851377
--- /dev/null
+++ b/docs/framework/lit/reference/index.md
@@ -0,0 +1,59 @@
+---
+id: "@tanstack/lit-query"
+title: "@tanstack/lit-query"
+---
+
+# @tanstack/lit-query
+
+## Classes
+
+- [QueryClientProvider](classes/QueryClientProvider.md)
+
+## Type Aliases
+
+- [Accessor](type-aliases/Accessor.md)
+- [CreateInfiniteQueryOptions](type-aliases/CreateInfiniteQueryOptions.md)
+- [CreateMutationOptions](type-aliases/CreateMutationOptions.md)
+- [CreateQueriesControllerOptions](type-aliases/CreateQueriesControllerOptions.md)
+- [CreateQueriesInput](type-aliases/CreateQueriesInput.md)
+- [CreateQueryOptions](type-aliases/CreateQueryOptions.md)
+- [DefinedInitialDataOptions](type-aliases/DefinedInitialDataOptions.md)
+- [InfiniteQueryControllerOptions](type-aliases/InfiniteQueryControllerOptions.md)
+- [InfiniteQueryResultAccessor](type-aliases/InfiniteQueryResultAccessor.md)
+- [IsFetchingAccessor](type-aliases/IsFetchingAccessor.md)
+- [IsMutatingAccessor](type-aliases/IsMutatingAccessor.md)
+- [MutationControllerOptions](type-aliases/MutationControllerOptions.md)
+- [MutationControllerResult](type-aliases/MutationControllerResult.md)
+- [MutationResultAccessor](type-aliases/MutationResultAccessor.md)
+- [MutationStateAccessor](type-aliases/MutationStateAccessor.md)
+- [MutationStateOptions](type-aliases/MutationStateOptions.md)
+- [QueriesControllerOptions](type-aliases/QueriesControllerOptions.md)
+- [QueriesResultAccessor](type-aliases/QueriesResultAccessor.md)
+- [QueryControllerOptions](type-aliases/QueryControllerOptions.md)
+- [QueryControllerResult](type-aliases/QueryControllerResult.md)
+- [QueryResultAccessor](type-aliases/QueryResultAccessor.md)
+- [UndefinedInitialDataOptions](type-aliases/UndefinedInitialDataOptions.md)
+- [UnusedSkipTokenOptions](type-aliases/UnusedSkipTokenOptions.md)
+- [ValueAccessor](type-aliases/ValueAccessor.md)
+
+## Variables
+
+- [queryClientContext](variables/queryClientContext.md)
+
+## Functions
+
+- [createInfiniteQueryController](functions/createInfiniteQueryController.md)
+- [createMutationController](functions/createMutationController.md)
+- [createQueriesController](functions/createQueriesController.md)
+- [createQueryController](functions/createQueryController.md)
+- [getDefaultQueryClient](functions/getDefaultQueryClient.md)
+- [infiniteQueryOptions](functions/infiniteQueryOptions.md)
+- [mutationOptions](functions/mutationOptions.md)
+- [queryOptions](functions/queryOptions.md)
+- [registerDefaultQueryClient](functions/registerDefaultQueryClient.md)
+- [resolveQueryClient](functions/resolveQueryClient.md)
+- [unregisterDefaultQueryClient](functions/unregisterDefaultQueryClient.md)
+- [useIsFetching](functions/useIsFetching.md)
+- [useIsMutating](functions/useIsMutating.md)
+- [useMutationState](functions/useMutationState.md)
+- [useQueryClient](functions/useQueryClient.md)
diff --git a/docs/framework/lit/reference/type-aliases/Accessor.md b/docs/framework/lit/reference/type-aliases/Accessor.md
new file mode 100644
index 00000000000..95d77dee47a
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/Accessor.md
@@ -0,0 +1,30 @@
+---
+id: Accessor
+title: Accessor
+---
+
+# Type Alias: Accessor\
+
+```ts
+type Accessor = T | () => T;
+```
+
+Defined in: [packages/lit-query/src/accessor.ts:13](https://github.com/TanStack/query/blob/main/packages/lit-query/src/accessor.ts#L13)
+
+A value that can be passed directly or read from a zero-argument getter.
+
+Lit Query APIs read function accessors during host updates, so the getter can
+depend on reactive host state.
+
+## Type Parameters
+
+### T
+
+`T`
+
+## Example
+
+```ts
+const staticKey: Accessor = ['todos']
+const reactiveKey: Accessor = () => ['todos', this.userId]
+```
diff --git a/docs/framework/lit/reference/type-aliases/CreateInfiniteQueryOptions.md b/docs/framework/lit/reference/type-aliases/CreateInfiniteQueryOptions.md
new file mode 100644
index 00000000000..ba09bb1126c
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/CreateInfiniteQueryOptions.md
@@ -0,0 +1,39 @@
+---
+id: CreateInfiniteQueryOptions
+title: CreateInfiniteQueryOptions
+---
+
+# Type Alias: CreateInfiniteQueryOptions\
+
+```ts
+type CreateInfiniteQueryOptions = InfiniteQueryObserverOptions;
+```
+
+Defined in: [packages/lit-query/src/createInfiniteQueryController.ts:27](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createInfiniteQueryController.ts#L27)
+
+Options accepted by `createInfiniteQueryController`.
+
+This is the Lit adapter shape for `InfiniteQueryObserverOptions`. Pass it
+directly or through an `Accessor` when the options depend on Lit host state.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `InfiniteData`\<`TQueryFnData`\>
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
+
+### TPageParam
+
+`TPageParam` = `unknown`
diff --git a/docs/framework/lit/reference/type-aliases/CreateMutationOptions.md b/docs/framework/lit/reference/type-aliases/CreateMutationOptions.md
new file mode 100644
index 00000000000..94d611682b5
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/CreateMutationOptions.md
@@ -0,0 +1,35 @@
+---
+id: CreateMutationOptions
+title: CreateMutationOptions
+---
+
+# Type Alias: CreateMutationOptions\
+
+```ts
+type CreateMutationOptions = MutationObserverOptions;
+```
+
+Defined in: [packages/lit-query/src/createMutationController.ts:25](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createMutationController.ts#L25)
+
+Options accepted by `createMutationController`.
+
+This is the Lit adapter shape for `MutationObserverOptions`. Pass it directly
+or through an `Accessor` when the options depend on Lit host state.
+
+## Type Parameters
+
+### TData
+
+`TData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TVariables
+
+`TVariables` = `void`
+
+### TOnMutateResult
+
+`TOnMutateResult` = `unknown`
diff --git a/docs/framework/lit/reference/type-aliases/CreateQueriesControllerOptions.md b/docs/framework/lit/reference/type-aliases/CreateQueriesControllerOptions.md
new file mode 100644
index 00000000000..1f69e15b84a
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/CreateQueriesControllerOptions.md
@@ -0,0 +1,64 @@
+---
+id: CreateQueriesControllerOptions
+title: CreateQueriesControllerOptions
+---
+
+# Type Alias: CreateQueriesControllerOptions\
+
+```ts
+type CreateQueriesControllerOptions = object;
+```
+
+Defined in: [packages/lit-query/src/createQueriesController.ts:194](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueriesController.ts#L194)
+
+Options accepted by `createQueriesController`.
+
+`queries` can be a static list or a getter that returns the current list.
+`combine` can reshape the array of query results into a single value for the
+returned accessor.
+
+## Type Parameters
+
+### TQueryOptions
+
+`TQueryOptions` *extends* `any`[] = `any`[]
+
+### TCombinedResult
+
+`TCombinedResult` = `CreateQueriesResults`\<`TQueryOptions`\>
+
+## Properties
+
+### combine()?
+
+```ts
+optional combine: (result) => TCombinedResult;
+```
+
+Defined in: [packages/lit-query/src/createQueriesController.ts:208](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueriesController.ts#L208)
+
+Optional function that combines the query result array into one value.
+
+#### Parameters
+
+##### result
+
+`CreateQueriesResults`\<`TQueryOptions`\>
+
+#### Returns
+
+`TCombinedResult`
+
+***
+
+### queries
+
+```ts
+queries: Accessor<
+ | readonly [...CreateQueriesOptions]
+| readonly [...{ [K in keyof TQueryOptions]: GetCreateQueriesInput }]>;
+```
+
+Defined in: [packages/lit-query/src/createQueriesController.ts:199](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueriesController.ts#L199)
+
+Query options to observe, or a getter that returns the current options.
diff --git a/docs/framework/lit/reference/type-aliases/CreateQueriesInput.md b/docs/framework/lit/reference/type-aliases/CreateQueriesInput.md
new file mode 100644
index 00000000000..0f698f79617
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/CreateQueriesInput.md
@@ -0,0 +1,35 @@
+---
+id: CreateQueriesInput
+title: CreateQueriesInput
+---
+
+# Type Alias: CreateQueriesInput\
+
+```ts
+type CreateQueriesInput = QueryObserverOptions;
+```
+
+Defined in: [packages/lit-query/src/createQueriesController.ts:30](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueriesController.ts#L30)
+
+Options for one query inside `createQueriesController`.
+
+This mirrors `QueryObserverOptions` and is used by the tuple inference that
+maps each input query to its corresponding result.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `TQueryFnData`
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
diff --git a/docs/framework/lit/reference/type-aliases/CreateQueryOptions.md b/docs/framework/lit/reference/type-aliases/CreateQueryOptions.md
new file mode 100644
index 00000000000..a967e779ac8
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/CreateQueryOptions.md
@@ -0,0 +1,40 @@
+---
+id: CreateQueryOptions
+title: CreateQueryOptions
+---
+
+# Type Alias: CreateQueryOptions\
+
+```ts
+type CreateQueryOptions = QueryObserverOptions;
+```
+
+Defined in: [packages/lit-query/src/createQueryController.ts:27](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueryController.ts#L27)
+
+Options accepted by `createQueryController`.
+
+This is the Lit adapter shape for `QueryObserverOptions`. It can be passed
+directly to `createQueryController`, or wrapped in an `Accessor` when the
+options depend on Lit host state.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `TQueryFnData`
+
+### TQueryData
+
+`TQueryData` = `TQueryFnData`
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
diff --git a/docs/framework/lit/reference/type-aliases/DefinedInitialDataOptions.md b/docs/framework/lit/reference/type-aliases/DefinedInitialDataOptions.md
new file mode 100644
index 00000000000..b369207dbb3
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/DefinedInitialDataOptions.md
@@ -0,0 +1,48 @@
+---
+id: DefinedInitialDataOptions
+title: DefinedInitialDataOptions
+---
+
+# Type Alias: DefinedInitialDataOptions\
+
+```ts
+type DefinedInitialDataOptions = Omit, "queryFn"> & object;
+```
+
+Defined in: [packages/lit-query/src/queryOptions.ts:16](https://github.com/TanStack/query/blob/main/packages/lit-query/src/queryOptions.ts#L16)
+
+Query options with `initialData` that guarantees defined query data.
+
+## Type Declaration
+
+### initialData
+
+```ts
+initialData:
+ | NonUndefinedGuard
+| () => NonUndefinedGuard;
+```
+
+### queryFn?
+
+```ts
+optional queryFn: QueryFunction;
+```
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `TQueryFnData`
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
diff --git a/docs/framework/lit/reference/type-aliases/InfiniteQueryControllerOptions.md b/docs/framework/lit/reference/type-aliases/InfiniteQueryControllerOptions.md
new file mode 100644
index 00000000000..f2b6bbe0b58
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/InfiniteQueryControllerOptions.md
@@ -0,0 +1,36 @@
+---
+id: InfiniteQueryControllerOptions
+title: InfiniteQueryControllerOptions
+---
+
+# Type Alias: InfiniteQueryControllerOptions\
+
+```ts
+type InfiniteQueryControllerOptions = Accessor>;
+```
+
+Defined in: [packages/lit-query/src/types.ts:41](https://github.com/TanStack/query/blob/main/packages/lit-query/src/types.ts#L41)
+
+Accessor-wrapped options accepted by `createInfiniteQueryController`.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `InfiniteData`\<`TQueryFnData`\>
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
+
+### TPageParam
+
+`TPageParam` = `unknown`
diff --git a/docs/framework/lit/reference/type-aliases/InfiniteQueryResultAccessor.md b/docs/framework/lit/reference/type-aliases/InfiniteQueryResultAccessor.md
new file mode 100644
index 00000000000..a45900de25f
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/InfiniteQueryResultAccessor.md
@@ -0,0 +1,66 @@
+---
+id: InfiniteQueryResultAccessor
+title: InfiniteQueryResultAccessor
+---
+
+# Type Alias: InfiniteQueryResultAccessor\
+
+```ts
+type InfiniteQueryResultAccessor = ValueAccessor> & object;
+```
+
+Defined in: [packages/lit-query/src/createInfiniteQueryController.ts:48](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createInfiniteQueryController.ts#L48)
+
+Accessor returned by `createInfiniteQueryController`.
+
+Call the accessor or read its `current` property to get the latest infinite
+query result. The attached methods delegate to the active infinite query
+observer.
+
+## Type Declaration
+
+### destroy()
+
+```ts
+destroy: () => void;
+```
+
+Removes the controller from its Lit host and unsubscribes observers.
+
+#### Returns
+
+`void`
+
+### fetchNextPage
+
+```ts
+fetchNextPage: InfiniteQueryObserverResult["fetchNextPage"];
+```
+
+Fetches the next page for the current infinite query.
+
+### fetchPreviousPage
+
+```ts
+fetchPreviousPage: InfiniteQueryObserverResult["fetchPreviousPage"];
+```
+
+Fetches the previous page for the current infinite query.
+
+### refetch
+
+```ts
+refetch: InfiniteQueryObserverResult["refetch"];
+```
+
+Refetches the current infinite query.
+
+## Type Parameters
+
+### TData
+
+`TData`
+
+### TError
+
+`TError`
diff --git a/docs/framework/lit/reference/type-aliases/IsFetchingAccessor.md b/docs/framework/lit/reference/type-aliases/IsFetchingAccessor.md
new file mode 100644
index 00000000000..99c09c43502
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/IsFetchingAccessor.md
@@ -0,0 +1,29 @@
+---
+id: IsFetchingAccessor
+title: IsFetchingAccessor
+---
+
+# Type Alias: IsFetchingAccessor
+
+```ts
+type IsFetchingAccessor = ValueAccessor & object;
+```
+
+Defined in: [packages/lit-query/src/useIsFetching.ts:17](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useIsFetching.ts#L17)
+
+Accessor returned by `useIsFetching`.
+
+Call the accessor or read its `current` property to get the number of
+currently fetching queries that match the filters.
+
+## Type Declaration
+
+### destroy()
+
+```ts
+destroy: () => void;
+```
+
+#### Returns
+
+`void`
diff --git a/docs/framework/lit/reference/type-aliases/IsMutatingAccessor.md b/docs/framework/lit/reference/type-aliases/IsMutatingAccessor.md
new file mode 100644
index 00000000000..1f0ff1194f7
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/IsMutatingAccessor.md
@@ -0,0 +1,29 @@
+---
+id: IsMutatingAccessor
+title: IsMutatingAccessor
+---
+
+# Type Alias: IsMutatingAccessor
+
+```ts
+type IsMutatingAccessor = ValueAccessor & object;
+```
+
+Defined in: [packages/lit-query/src/useIsMutating.ts:17](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useIsMutating.ts#L17)
+
+Accessor returned by `useIsMutating`.
+
+Call the accessor or read its `current` property to get the number of
+currently pending mutations that match the filters.
+
+## Type Declaration
+
+### destroy()
+
+```ts
+destroy: () => void;
+```
+
+#### Returns
+
+`void`
diff --git a/docs/framework/lit/reference/type-aliases/MutationControllerOptions.md b/docs/framework/lit/reference/type-aliases/MutationControllerOptions.md
new file mode 100644
index 00000000000..6482d82a13a
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/MutationControllerOptions.md
@@ -0,0 +1,32 @@
+---
+id: MutationControllerOptions
+title: MutationControllerOptions
+---
+
+# Type Alias: MutationControllerOptions\
+
+```ts
+type MutationControllerOptions = Accessor>;
+```
+
+Defined in: [packages/lit-query/src/types.ts:54](https://github.com/TanStack/query/blob/main/packages/lit-query/src/types.ts#L54)
+
+Accessor-wrapped options accepted by `createMutationController`.
+
+## Type Parameters
+
+### TData
+
+`TData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TVariables
+
+`TVariables` = `void`
+
+### TOnMutateResult
+
+`TOnMutateResult` = `unknown`
diff --git a/docs/framework/lit/reference/type-aliases/MutationControllerResult.md b/docs/framework/lit/reference/type-aliases/MutationControllerResult.md
new file mode 100644
index 00000000000..8b63b098fba
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/MutationControllerResult.md
@@ -0,0 +1,32 @@
+---
+id: MutationControllerResult
+title: MutationControllerResult
+---
+
+# Type Alias: MutationControllerResult\
+
+```ts
+type MutationControllerResult = MutationObserverResult;
+```
+
+Defined in: [packages/lit-query/src/types.ts:64](https://github.com/TanStack/query/blob/main/packages/lit-query/src/types.ts#L64)
+
+Result object produced by a Lit mutation controller.
+
+## Type Parameters
+
+### TData
+
+`TData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TVariables
+
+`TVariables` = `void`
+
+### TOnMutateResult
+
+`TOnMutateResult` = `unknown`
diff --git a/docs/framework/lit/reference/type-aliases/MutationResultAccessor.md b/docs/framework/lit/reference/type-aliases/MutationResultAccessor.md
new file mode 100644
index 00000000000..6846aec42aa
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/MutationResultAccessor.md
@@ -0,0 +1,91 @@
+---
+id: MutationResultAccessor
+title: MutationResultAccessor
+---
+
+# Type Alias: MutationResultAccessor\
+
+```ts
+type MutationResultAccessor = ValueAccessor> & object;
+```
+
+Defined in: [packages/lit-query/src/createMutationController.ts:38](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createMutationController.ts#L38)
+
+Accessor returned by `createMutationController`.
+
+Call the accessor or read its `current` property to get the latest mutation
+result. The attached methods delegate to the active mutation observer.
+
+## Type Declaration
+
+### destroy()
+
+```ts
+destroy: () => void;
+```
+
+Removes the controller from its Lit host and unsubscribes observers.
+
+#### Returns
+
+`void`
+
+### mutate()
+
+```ts
+mutate: (variables, options?) => void;
+```
+
+Starts the mutation and swallows the returned promise.
+
+Throws synchronously if no `QueryClient` can be resolved.
+
+#### Parameters
+
+##### variables
+
+`TVariables`
+
+##### options?
+
+`MutateOptions`\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>
+
+#### Returns
+
+`void`
+
+### mutateAsync
+
+```ts
+mutateAsync: MutationObserverResult["mutate"];
+```
+
+Starts the mutation and returns the observer promise.
+
+Rejects if no `QueryClient` can be resolved.
+
+### reset
+
+```ts
+reset: MutationObserverResult["reset"];
+```
+
+Resets the mutation observer to its idle state.
+
+## Type Parameters
+
+### TData
+
+`TData`
+
+### TError
+
+`TError`
+
+### TVariables
+
+`TVariables`
+
+### TOnMutateResult
+
+`TOnMutateResult`
diff --git a/docs/framework/lit/reference/type-aliases/MutationStateAccessor.md b/docs/framework/lit/reference/type-aliases/MutationStateAccessor.md
new file mode 100644
index 00000000000..6c9f9298caa
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/MutationStateAccessor.md
@@ -0,0 +1,37 @@
+---
+id: MutationStateAccessor
+title: MutationStateAccessor
+---
+
+# Type Alias: MutationStateAccessor\
+
+```ts
+type MutationStateAccessor = ValueAccessor & object;
+```
+
+Defined in: [packages/lit-query/src/useMutationState.ts:32](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useMutationState.ts#L32)
+
+Accessor returned by `useMutationState`.
+
+Call the accessor or read its `current` property to get the selected state for
+matching mutations.
+
+## Type Declaration
+
+### destroy()
+
+```ts
+destroy: () => void;
+```
+
+Removes the controller from its Lit host and unsubscribes observers.
+
+#### Returns
+
+`void`
+
+## Type Parameters
+
+### TResult
+
+`TResult`
diff --git a/docs/framework/lit/reference/type-aliases/MutationStateOptions.md b/docs/framework/lit/reference/type-aliases/MutationStateOptions.md
new file mode 100644
index 00000000000..7ae3228ea66
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/MutationStateOptions.md
@@ -0,0 +1,54 @@
+---
+id: MutationStateOptions
+title: MutationStateOptions
+---
+
+# Type Alias: MutationStateOptions\
+
+```ts
+type MutationStateOptions = object;
+```
+
+Defined in: [packages/lit-query/src/useMutationState.ts:19](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useMutationState.ts#L19)
+
+Options accepted by `useMutationState`.
+
+## Type Parameters
+
+### TResult
+
+`TResult`
+
+## Properties
+
+### filters?
+
+```ts
+optional filters: Accessor;
+```
+
+Defined in: [packages/lit-query/src/useMutationState.ts:21](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useMutationState.ts#L21)
+
+Filters used to select mutations from the mutation cache.
+
+***
+
+### select()?
+
+```ts
+optional select: (mutation) => TResult;
+```
+
+Defined in: [packages/lit-query/src/useMutationState.ts:23](https://github.com/TanStack/query/blob/main/packages/lit-query/src/useMutationState.ts#L23)
+
+Maps each matching mutation to the value returned by the accessor.
+
+#### Parameters
+
+##### mutation
+
+`Mutation`
+
+#### Returns
+
+`TResult`
diff --git a/docs/framework/lit/reference/type-aliases/QueriesControllerOptions.md b/docs/framework/lit/reference/type-aliases/QueriesControllerOptions.md
new file mode 100644
index 00000000000..70ef5a77f2b
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/QueriesControllerOptions.md
@@ -0,0 +1,24 @@
+---
+id: QueriesControllerOptions
+title: QueriesControllerOptions
+---
+
+# Type Alias: QueriesControllerOptions\
+
+```ts
+type QueriesControllerOptions = Accessor>;
+```
+
+Defined in: [packages/lit-query/src/types.ts:74](https://github.com/TanStack/query/blob/main/packages/lit-query/src/types.ts#L74)
+
+Accessor-wrapped options accepted by `createQueriesController`.
+
+## Type Parameters
+
+### TQueryOptions
+
+`TQueryOptions` *extends* `any`[] = `any`[]
+
+### TCombinedResult
+
+`TCombinedResult` = `CreateQueriesResults`\<`TQueryOptions`\>
diff --git a/docs/framework/lit/reference/type-aliases/QueriesResultAccessor.md b/docs/framework/lit/reference/type-aliases/QueriesResultAccessor.md
new file mode 100644
index 00000000000..c780231ee2f
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/QueriesResultAccessor.md
@@ -0,0 +1,37 @@
+---
+id: QueriesResultAccessor
+title: QueriesResultAccessor
+---
+
+# Type Alias: QueriesResultAccessor\
+
+```ts
+type QueriesResultAccessor = ValueAccessor & object;
+```
+
+Defined in: [packages/lit-query/src/createQueriesController.ts:217](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueriesController.ts#L217)
+
+Accessor returned by `createQueriesController`.
+
+Call the accessor or read its `current` property to get the latest combined
+value.
+
+## Type Declaration
+
+### destroy()
+
+```ts
+destroy: () => void;
+```
+
+Removes the controller from its Lit host and unsubscribes observers.
+
+#### Returns
+
+`void`
+
+## Type Parameters
+
+### TCombinedResult
+
+`TCombinedResult`
diff --git a/docs/framework/lit/reference/type-aliases/QueryControllerOptions.md b/docs/framework/lit/reference/type-aliases/QueryControllerOptions.md
new file mode 100644
index 00000000000..104d98c5fb9
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/QueryControllerOptions.md
@@ -0,0 +1,36 @@
+---
+id: QueryControllerOptions
+title: QueryControllerOptions
+---
+
+# Type Alias: QueryControllerOptions\
+
+```ts
+type QueryControllerOptions = Accessor>;
+```
+
+Defined in: [packages/lit-query/src/types.ts:20](https://github.com/TanStack/query/blob/main/packages/lit-query/src/types.ts#L20)
+
+Accessor-wrapped options accepted by `createQueryController`.
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `TQueryFnData`
+
+### TQueryData
+
+`TQueryData` = `TQueryFnData`
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
diff --git a/docs/framework/lit/reference/type-aliases/QueryControllerResult.md b/docs/framework/lit/reference/type-aliases/QueryControllerResult.md
new file mode 100644
index 00000000000..853212d0536
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/QueryControllerResult.md
@@ -0,0 +1,24 @@
+---
+id: QueryControllerResult
+title: QueryControllerResult
+---
+
+# Type Alias: QueryControllerResult\
+
+```ts
+type QueryControllerResult = QueryObserverResult;
+```
+
+Defined in: [packages/lit-query/src/types.ts:33](https://github.com/TanStack/query/blob/main/packages/lit-query/src/types.ts#L33)
+
+Result object produced by a Lit query controller.
+
+## Type Parameters
+
+### TData
+
+`TData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
diff --git a/docs/framework/lit/reference/type-aliases/QueryResultAccessor.md b/docs/framework/lit/reference/type-aliases/QueryResultAccessor.md
new file mode 100644
index 00000000000..ce806098556
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/QueryResultAccessor.md
@@ -0,0 +1,61 @@
+---
+id: QueryResultAccessor
+title: QueryResultAccessor
+---
+
+# Type Alias: QueryResultAccessor\
+
+```ts
+type QueryResultAccessor = ValueAccessor> & object;
+```
+
+Defined in: [packages/lit-query/src/createQueryController.ts:41](https://github.com/TanStack/query/blob/main/packages/lit-query/src/createQueryController.ts#L41)
+
+Accessor returned by `createQueryController`.
+
+Call the accessor or read its `current` property to get the latest query
+result. The attached methods delegate to the active query observer.
+
+## Type Declaration
+
+### destroy()
+
+```ts
+destroy: () => void;
+```
+
+Removes the controller from its Lit host and unsubscribes observers.
+
+#### Returns
+
+`void`
+
+### refetch
+
+```ts
+refetch: QueryObserverResult["refetch"];
+```
+
+Refetches the current query.
+
+### suspense()
+
+```ts
+suspense: () => Promise>;
+```
+
+Resolves with an optimistic query result, fetching first when needed.
+
+#### Returns
+
+`Promise`\<`QueryObserverResult`\<`TData`, `TError`\>\>
+
+## Type Parameters
+
+### TData
+
+`TData`
+
+### TError
+
+`TError`
diff --git a/docs/framework/lit/reference/type-aliases/UndefinedInitialDataOptions.md b/docs/framework/lit/reference/type-aliases/UndefinedInitialDataOptions.md
new file mode 100644
index 00000000000..75aa69f4139
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/UndefinedInitialDataOptions.md
@@ -0,0 +1,42 @@
+---
+id: UndefinedInitialDataOptions
+title: UndefinedInitialDataOptions
+---
+
+# Type Alias: UndefinedInitialDataOptions\
+
+```ts
+type UndefinedInitialDataOptions = QueryObserverOptions & object;
+```
+
+Defined in: [packages/lit-query/src/queryOptions.ts:58](https://github.com/TanStack/query/blob/main/packages/lit-query/src/queryOptions.ts#L58)
+
+Query options where `initialData` can be omitted or undefined.
+
+## Type Declaration
+
+### initialData?
+
+```ts
+optional initialData:
+ | InitialDataFunction>
+| NonUndefinedGuard;
+```
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `TQueryFnData`
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
diff --git a/docs/framework/lit/reference/type-aliases/UnusedSkipTokenOptions.md b/docs/framework/lit/reference/type-aliases/UnusedSkipTokenOptions.md
new file mode 100644
index 00000000000..53acb8d9f5c
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/UnusedSkipTokenOptions.md
@@ -0,0 +1,40 @@
+---
+id: UnusedSkipTokenOptions
+title: UnusedSkipTokenOptions
+---
+
+# Type Alias: UnusedSkipTokenOptions\
+
+```ts
+type UnusedSkipTokenOptions = OmitKeyof, "queryFn"> & object;
+```
+
+Defined in: [packages/lit-query/src/queryOptions.ts:34](https://github.com/TanStack/query/blob/main/packages/lit-query/src/queryOptions.ts#L34)
+
+Query options where `queryFn` is present and not a `skipToken`.
+
+## Type Declaration
+
+### queryFn?
+
+```ts
+optional queryFn: Exclude["queryFn"], SkipToken | undefined>;
+```
+
+## Type Parameters
+
+### TQueryFnData
+
+`TQueryFnData` = `unknown`
+
+### TError
+
+`TError` = `DefaultError`
+
+### TData
+
+`TData` = `TQueryFnData`
+
+### TQueryKey
+
+`TQueryKey` *extends* `QueryKey` = `QueryKey`
diff --git a/docs/framework/lit/reference/type-aliases/ValueAccessor.md b/docs/framework/lit/reference/type-aliases/ValueAccessor.md
new file mode 100644
index 00000000000..642c42f37da
--- /dev/null
+++ b/docs/framework/lit/reference/type-aliases/ValueAccessor.md
@@ -0,0 +1,39 @@
+---
+id: ValueAccessor
+title: ValueAccessor
+---
+
+# Type Alias: ValueAccessor\
+
+```ts
+type ValueAccessor = () => T & object;
+```
+
+Defined in: [packages/lit-query/src/accessor.ts:32](https://github.com/TanStack/query/blob/main/packages/lit-query/src/accessor.ts#L32)
+
+A callable accessor with a `current` property for reading the latest
+controller result.
+
+Controller creators and cache state helpers return this shape so render code
+can use either `result()` or `result.current`.
+
+## Type Declaration
+
+### current
+
+```ts
+readonly current: T;
+```
+
+## Type Parameters
+
+### T
+
+`T`
+
+## Example
+
+```ts
+const query = this.todos()
+const sameQuery = this.todos.current
+```
diff --git a/docs/framework/lit/reference/variables/queryClientContext.md b/docs/framework/lit/reference/variables/queryClientContext.md
new file mode 100644
index 00000000000..56395991d49
--- /dev/null
+++ b/docs/framework/lit/reference/variables/queryClientContext.md
@@ -0,0 +1,18 @@
+---
+id: queryClientContext
+title: queryClientContext
+---
+
+# Variable: queryClientContext
+
+```ts
+const queryClientContext: object;
+```
+
+Defined in: [packages/lit-query/src/context.ts:11](https://github.com/TanStack/query/blob/main/packages/lit-query/src/context.ts#L11)
+
+Lit context key used by `QueryClientProvider` and host-bound APIs to share a
+`QueryClient` through the DOM tree.
+
+Most applications use `QueryClientProvider` instead of interacting with this
+context directly.
diff --git a/docs/framework/lit/typescript.md b/docs/framework/lit/typescript.md
new file mode 100644
index 00000000000..6a59b09b1d7
--- /dev/null
+++ b/docs/framework/lit/typescript.md
@@ -0,0 +1,132 @@
+---
+id: typescript
+title: TypeScript
+---
+
+Lit Query is written in TypeScript and reuses TanStack Query Core's type system. The most important rule is the same as every other adapter: give your query and mutation functions well-defined return types, and the result accessors will infer from them.
+
+## Query Inference
+
+```ts
+import { LitElement } from 'lit'
+import { createQueryController } from '@tanstack/lit-query'
+
+type Todo = {
+ id: number
+ title: string
+}
+
+async function fetchTodos(): Promise {
+ const response = await fetch('/api/todos')
+ if (!response.ok) throw new Error('Failed to fetch todos')
+ return response.json() as Promise
+}
+
+class TodosView extends LitElement {
+ private readonly todos = createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+ })
+
+ render() {
+ const query = this.todos()
+ // query.data is Todo[] | undefined until success is known.
+ }
+}
+```
+
+Checking `isSuccess`, `isPending`, `isError`, or `status` narrows the result just like TanStack Query Core result types:
+
+```ts
+const query = this.todos()
+
+if (query.isSuccess) {
+ query.data
+ // Todo[]
+}
+```
+
+## Mutation Inference
+
+```ts
+import { LitElement } from 'lit'
+import { createMutationController } from '@tanstack/lit-query'
+
+type CreateTodoInput = {
+ title: string
+}
+
+type Todo = {
+ id: number
+ title: string
+}
+
+async function addTodo(input: CreateTodoInput): Promise {
+ const response = await fetch('/api/todos', {
+ method: 'POST',
+ body: JSON.stringify(input),
+ })
+ if (!response.ok) throw new Error('Failed to create todo')
+ return response.json() as Promise
+}
+
+class AddTodoButton extends LitElement {
+ private readonly mutation = createMutationController(this, {
+ mutationFn: addTodo,
+ })
+
+ private add() {
+ this.mutation.mutate({ title: 'Learn Lit Query' })
+ }
+}
+```
+
+## Extracting Options
+
+Use [`queryOptions`](./reference/functions/queryOptions.md), [`infiniteQueryOptions`](./reference/functions/infiniteQueryOptions.md), and [`mutationOptions`](./reference/functions/mutationOptions.md) when you want to share typed options between controllers and `QueryClient` calls.
+
+```ts
+import { LitElement } from 'lit'
+import {
+ QueryClient,
+ createQueryController,
+ queryOptions,
+} from '@tanstack/lit-query'
+
+function todosOptions() {
+ return queryOptions({
+ queryKey: ['todos'],
+ queryFn: fetchTodos,
+ staleTime: 5_000,
+ })
+}
+
+const queryClient = new QueryClient()
+
+class TodosView extends LitElement {
+ private readonly todos = createQueryController(this, todosOptions())
+}
+
+void queryClient.prefetchQuery(todosOptions())
+```
+
+The branded `queryKey` returned from `queryOptions` also helps APIs like `queryClient.getQueryData` understand the data type.
+
+## Global Register Types
+
+Because `@tanstack/lit-query` re-exports TanStack Query Core, module augmentation is written against `@tanstack/lit-query` in Lit apps:
+
+```ts
+import '@tanstack/lit-query'
+
+type AppQueryKey = ['todos' | 'projects', ...ReadonlyArray]
+
+declare module '@tanstack/lit-query' {
+ interface Register {
+ queryKey: AppQueryKey
+ mutationKey: AppQueryKey
+ }
+}
+```
+
+See the generated reference for Lit-specific [option and result types](./reference/index.md).
diff --git a/examples/lit/basic/README.md b/examples/lit/basic/README.md
new file mode 100644
index 00000000000..6d79ad06c1a
--- /dev/null
+++ b/examples/lit/basic/README.md
@@ -0,0 +1,5 @@
+# Example
+
+To run this example from the repo root:
+
+- `pnpm --dir examples/lit/basic run dev`
diff --git a/examples/lit/basic/basic-query.html b/examples/lit/basic/basic-query.html
new file mode 100644
index 00000000000..19de73348a1
--- /dev/null
+++ b/examples/lit/basic/basic-query.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Lit Query Basic Example
+
+
+
+
+
+
diff --git a/examples/lit/basic/config/port.d.ts b/examples/lit/basic/config/port.d.ts
new file mode 100644
index 00000000000..12e9b85cc4d
--- /dev/null
+++ b/examples/lit/basic/config/port.d.ts
@@ -0,0 +1 @@
+export const DEMO_PORT: number
diff --git a/examples/lit/basic/config/port.js b/examples/lit/basic/config/port.js
new file mode 100644
index 00000000000..bff39bff2ee
--- /dev/null
+++ b/examples/lit/basic/config/port.js
@@ -0,0 +1,22 @@
+const DEFAULT_DEMO_PORT = 4173
+const envPort = process.env.DEMO_PORT
+
+function resolvePort() {
+ if (!envPort) {
+ return DEFAULT_DEMO_PORT
+ }
+
+ const parsedPort = Number.parseInt(envPort, 10)
+ const isValidPort =
+ Number.isInteger(parsedPort) && parsedPort > 0 && parsedPort <= 65535
+
+ if (!isValidPort) {
+ throw new Error(
+ `Invalid DEMO_PORT "${envPort}". Expected an integer between 1 and 65535.`,
+ )
+ }
+
+ return parsedPort
+}
+
+export const DEMO_PORT = resolvePort()
diff --git a/examples/lit/basic/index.html b/examples/lit/basic/index.html
new file mode 100644
index 00000000000..a2962e70475
--- /dev/null
+++ b/examples/lit/basic/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ TanStack Lit Query E2E Demo
+
+
+
+
+
+
diff --git a/examples/lit/basic/lifecycle-contract.html b/examples/lit/basic/lifecycle-contract.html
new file mode 100644
index 00000000000..5d0f5e5e5a1
--- /dev/null
+++ b/examples/lit/basic/lifecycle-contract.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ TanStack Lit Query Lifecycle Contract Fixture
+
+
+
+
+
+
diff --git a/examples/lit/basic/mutation.html b/examples/lit/basic/mutation.html
new file mode 100644
index 00000000000..1d5de500efb
--- /dev/null
+++ b/examples/lit/basic/mutation.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Lit Query Mutation Example
+
+
+
+
+
+
diff --git a/examples/lit/basic/package.json b/examples/lit/basic/package.json
new file mode 100644
index 00000000000..969932dc834
--- /dev/null
+++ b/examples/lit/basic/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "@tanstack/query-example-lit-basic",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc --noEmit && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@tanstack/lit-query": "^0.1.0",
+ "@tanstack/query-core": "^5.99.0",
+ "lit": "^3.3.1"
+ },
+ "devDependencies": {
+ "typescript": "5.8.3",
+ "vite": "^6.4.1"
+ }
+}
diff --git a/examples/lit/basic/src/basic-query.ts b/examples/lit/basic/src/basic-query.ts
new file mode 100644
index 00000000000..5cc208d0174
--- /dev/null
+++ b/examples/lit/basic/src/basic-query.ts
@@ -0,0 +1,90 @@
+import { LitElement, html } from 'lit'
+import {
+ QueryClient,
+ QueryClientProvider,
+ createQueryController,
+} from '@tanstack/lit-query'
+import { fetchTodosFromServer, resetTodoApi } from './todoApi'
+import type { TodosResponse } from './todoApi'
+
+resetTodoApi()
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: { retry: false },
+ },
+})
+
+class BasicQueryProvider extends QueryClientProvider {
+ constructor() {
+ super()
+ this.client = queryClient
+ }
+
+ protected override createRenderRoot(): HTMLElement | DocumentFragment {
+ return this
+ }
+}
+
+customElements.define('basic-query-provider', BasicQueryProvider)
+
+class BasicQueryExample extends LitElement {
+ private readonly todos = createQueryController(this, {
+ queryKey: ['todos'],
+ queryFn: fetchTodosFromServer,
+ })
+
+ protected override createRenderRoot(): HTMLElement | DocumentFragment {
+ return this
+ }
+
+ render() {
+ const query = this.todos()
+ return html`
+
+