Querying Specific Blocks
Select, split, and render only the block content you need
Use these patterns when a view or block needs a targeted block selection instead of every contentBlocks item.
For the broader data model, see Block Data, View Data, and Template Parts.
Pull One Block Type From Another Post
Use contentBlocks(include: [...]) when you want a specific block from related posts. Sol People uses this shape for a hero block that pulls only services/service-card blocks from Service posts.
query ServicesHero {
block {
hero_services_hero {
theme
}
}
services(where: { orderby: [{ field: MENU_ORDER, order: ASC }] }) {
nodes {
contentBlocks(include: ["services/service-card"], limit: 1)
}
}
}import { ContentBlocks, defineBlock } from "eddev/blocks"
export default defineBlock("hero/services-hero", (props) => {
const cards =
props.services?.nodes
.flatMap((service) => service?.contentBlocks ?? [])
.filter(Boolean) ?? []
return <ContentBlocks blocks={cards} />
})include accepts block names, tags, flags, and wildcards. Add limit: 1 when you only expect one matching block per post.
Exclude A Block From Related Posts
Use exclude when related posts should render their body content but skip the block that is used somewhere else.
query ServicesArchive($postId: ID!) {
page(id: $postId, idType: DATABASE_ID) {
contentBlocks
}
services(where: { orderby: [{ field: MENU_ORDER, order: ASC }] }) {
nodes {
contentBlocks(exclude: ["services/service-card"])
}
}
}import { ContentBlocks } from "eddev/blocks"
import { defineView } from "eddev/views"
export default defineView("archive-services", (props) => {
return (
<>
<ContentBlocks blocks={props.page?.contentBlocks} />
{props.services?.nodes.map((service, index) => (
<ContentBlocks key={index} blocks={service?.contentBlocks} />
))}
</>
)
})Pull One Page Header From A Known Page
When an archive or app-like route has a fixed CMS page backing its intro content, query that page by URI and include just the header block.
query ArchiveBlog {
blogPosts(first: 9999, where: { orderby: [{ field: DATE, order: DESC }] }) {
nodes {
title
uri
}
}
page(id: "blog", idType: URI) {
title
contentBlocks(include: ["page/page-header"], limit: 1)
}
}import { ContentBlocks } from "eddev/blocks"
import { defineView } from "eddev/views"
export default defineView("archive-blog", (props) => {
return (
<>
<ContentBlocks blocks={props.page?.contentBlocks} />
{/* Render the listing UI below the page header. */}
</>
)
})Split A Hero From The Rest
If the current page stores the hero in normal contentBlocks, find it in React and render the remainder separately.
import { ContentBlocks, SingleContentBlock } from "eddev/blocks"
import { defineView } from "eddev/views"
export default defineView("template-home", (props) => {
const blocks = props.page?.contentBlocks ?? []
const hero = blocks.find((block) => block.slug === "homepage/homepage-carousel")
const rest = blocks.filter((block) => block.slug !== "homepage/homepage-carousel")
return (
<>
{hero && <SingleContentBlock block={hero} />}
<ContentBlocks blocks={rest} />
</>
)
})Use this when the split is mostly presentational. If the split affects payload size or repeated related posts, prefer include and exclude in GraphQL.
Query A Template Part Subset
Use aliases plus contentBlocks filters when _app.graphql needs both a whole template part and a small subset.
query CommonData {
templateParts {
siteHeader {
contentBlocks
}
headerButtons: siteHeader {
contentBlocks(flattenExcluded: true, include: ["parts/header-button"])
}
siteFooter {
contentBlocks
}
}
}import { ContentBlocks } from "eddev/blocks"
import { useAppData } from "eddev/hooks"
export function MobileMenuButtons() {
const blocks = useAppData((data) => data.templateParts?.headerButtons?.contentBlocks)
return <ContentBlocks blocks={blocks} />
}flattenExcluded: true is useful when the matching blocks may sit inside layout wrappers that you do not want to render.