diff --git a/docs/how-to/use-multiple-queries-in-a-template/index.md b/docs/how-to/use-multiple-queries-in-a-template/index.md
new file mode 100644
index 000000000..2726419c0
--- /dev/null
+++ b/docs/how-to/use-multiple-queries-in-a-template/index.md
@@ -0,0 +1,152 @@
+---
+title: "Use Multiple Queries in a Template"
+description: "Guide to splitting a Faust.js template's data into several GraphQL queries with Component.queries and reading each result with useFaustQuery."
+---
+
+A template can run several GraphQL queries instead of one. This lets you reuse a query across templates, such as a layout query for the site title and menus, and keep a separate query for the content of the post, page or archive being rendered.
+
+Define the queries in a static `Component.queries` array, then read each result with the `useFaustQuery` hook.
+
+## 0. Prerequisites
+
+If you haven't already, follow the [Basic Setup](/docs/how-to/basic-setup/) steps to get Faust.js set up, and make sure your app renders templates from `wp-templates` through [`getWordPressProps`](/docs/reference/get-wordpress-props/) and `WordPressTemplate`.
+
+## 1. Create a reusable query
+
+Put the query you want to share in its own file so every template can import it. This layout query fetches the site's general settings and two menus:
+
+```js title="fragments/LayoutQuery.js"
+import { gql } from "@apollo/client";
+
+export const GET_LAYOUT_QUERY = gql`
+ query GetLayout(
+ $headerLocation: MenuLocationEnum
+ $footerLocation: MenuLocationEnum
+ ) {
+ generalSettings {
+ title
+ description
+ }
+ headerMenuItems: menuItems(where: { location: $headerLocation }) {
+ nodes {
+ id
+ uri
+ label
+ }
+ }
+ footerMenuItems: menuItems(where: { location: $footerLocation }) {
+ nodes {
+ id
+ uri
+ label
+ }
+ }
+ }
+`;
+```
+
+## 2. Add the queries to the template
+
+In the template, list each query in `Component.queries`. Each entry has a `query` and an optional `variables` function:
+
+```js title="wp-templates/single.js"
+import { gql } from "@apollo/client";
+import { GET_LAYOUT_QUERY } from "../fragments/LayoutQuery";
+
+const GET_POST_QUERY = gql`
+ query GetPost($databaseId: ID!, $asPreview: Boolean = false) {
+ post(id: $databaseId, idType: DATABASE_ID, asPreview: $asPreview) {
+ title
+ content
+ }
+ }
+`;
+
+export default function Component(props) {
+ // We'll fill this in next.
+}
+
+Component.queries = [
+ {
+ query: GET_LAYOUT_QUERY,
+ variables: () => ({
+ headerLocation: "PRIMARY",
+ footerLocation: "FOOTER",
+ }),
+ },
+ {
+ query: GET_POST_QUERY,
+ variables: ({ databaseId }, ctx) => ({
+ databaseId,
+ asPreview: ctx?.asPreview,
+ }),
+ },
+];
+```
+
+When the queries run on the server, each `variables` function receives the same arguments as `Component.variables`: the [seed node](/docs/explanation/seed-query/), a context object with `asPreview` and `locale`, and any [`extra` arguments](/docs/reference/get-wordpress-props/#passing-extra-arguments) passed to `getWordPressProps`.
+
+Faust runs all of the queries at the same time and stores each result for the template to read.
+
+## 3. Read the results with `useFaustQuery`
+
+Call `useFaustQuery` with the same query you listed in `Component.queries` to get its data:
+
+```js title="wp-templates/single.js"
+import { gql } from "@apollo/client";
+import { useFaustQuery } from "@faustwp/core";
+import { GET_LAYOUT_QUERY } from "../fragments/LayoutQuery";
+
+// GET_POST_QUERY from step 2
+
+export default function Component(props) {
+ const { post } = useFaustQuery(GET_POST_QUERY) ?? {};
+ const { generalSettings, headerMenuItems, footerMenuItems } =
+ useFaustQuery(GET_LAYOUT_QUERY) ?? {};
+
+ // Loading state for previews
+ if (props.loading) {
+ return <>Loading...>;
+ }
+
+ return (
+ <>
+
+
{generalSettings?.title}
+
+
+
+
{post?.title}
+
+
+
+ >
+ );
+}
+
+// Component.queries from step 2
+```
+
+`useFaustQuery` returns `undefined` until the query has data, for example while a preview loads in the browser, so fall back to an empty object as shown above. Call it before any early return, since it's a React hook. It reads from `FaustProvider`, so it throws if your app isn't wrapped in `FaustProvider` as shown in [Basic Setup](/docs/how-to/basic-setup/).
+
+> [!note] Learn More
+> The [getting started example](https://github.com/wpengine/faustjs/tree/canary/examples/next/faustwp-getting-started/wp-templates) uses `Component.queries` with a shared layout query in each of its templates.
+
+## Notes and limitations
+
+- **Use one or the other.** A template can define `Component.query` or `Component.queries`, not both. Faust throws ``Only either `Component.query` or `Component.queries` can be provided, but not both.`` if it finds both.
+- **Results come from `useFaustQuery`, not `props.data`.** `props.data` is only filled in for `Component.query`.
+- **Queries run again in the browser.** After the page loads, Faust runs the queries again in the browser. On previews, they only run in the browser. In the browser, the `variables` functions receive the seed node and `asPreview`, but not `locale` or `extra`.
+- **Each query can only be listed once.** Faust stores results by the query's text, so listing the same query twice with different variables keeps only the last result. To fetch the same data with different variables, define a second query with a different operation name. See [#1742](https://github.com/wpengine/faustjs/issues/1742).
diff --git a/docs/nav.json b/docs/nav.json
index d997ce3ab..b52fa5c31 100644
--- a/docs/nav.json
+++ b/docs/nav.json
@@ -59,6 +59,10 @@
"title": "Query Data in Next.js Routes",
"route": "/docs/how-to/query-data-in-nextjs-routes/"
},
+ {
+ "title": "Use Multiple Queries in a Template",
+ "route": "/docs/how-to/use-multiple-queries-in-a-template/"
+ },
{
"title": "Write Data to WordPress",
"route": "/docs/how-to/write-data-to-wordpress/"
diff --git a/docs/reference/get-wordpress-props/index.md b/docs/reference/get-wordpress-props/index.md
index 1ea09f9b8..97d94775c 100644
--- a/docs/reference/get-wordpress-props/index.md
+++ b/docs/reference/get-wordpress-props/index.md
@@ -76,3 +76,5 @@ Component.variables = ({ databaseId }, ctx, extra) => {
...
}
```
+
+The `variables` function of each query in [`Component.queries`](/docs/how-to/use-multiple-queries-in-a-template/) receives `extra` the same way when the queries run on the server.