Template Types Reference
Templates are React components that you can directly edit to add or change a given route's (e.g., page, product, collection...) structure and layout.

Each template renders the sections added in the Customizer or Pack Admin with the <RenderSections> component from @pack/react.
The examples below are trimmed from the Blueprint's routes. Their loader data types (Page, BlogPage, ArticlePage, ProductWithInitialGrouping, SelectedVariant) come from the Blueprint's ~/lib/types, and useProductWithGrouping from its ~/hooks. The collection example's ActiveFilterValue is in ~/components/Collection/CollectionFilters/CollectionFilters.types, and CollectionType is Shopify's Collection type from @shopify/hydrogen/storefront-api-types.
Available Types
You can find all available template types inside your storefront's Github repository in the /app/routes directory.
- Home — renders on
/home page visits - Page — renders on
/pages/:handlevisits - Blog — renders on
/blogs/:handlevisits - Article — renders on
/articles/:handlevisits - Product — renders on
/products/:handlevisits - Collection — renders on
/collections/:handlevisits - Account — renders on
/account/:subroutevisits - 404 — renders on
invalid-routesvisits
Default Templates
When you create a store, you’ll find several templates that are already created for you by default. Let’s review each template.
Home
This template will be used for your storefront's homepage.
Page
This template will be used for all pages that follow the /pages/ route in your storefront.
RenderSections renders the Customizer sections for /pages/:handle. To arrange
them yourself, call useSections with the same props instead. It returns an
array of the rendered sections, one element per section.
// app/routes/($locale).pages.$handle.tsx
export default function PageRoute() {
const { page } = useLoaderData<{ page: Page }>();
return (
<div data-comp="PageRoute">
<RenderSections content={page} />
</div>
);
}
Blog
This template will be used for all blog pages that follow the /blogs/ route in your storefront.
RenderSections renders the Customizer sections for /blogs/:handle. To arrange
them yourself, call useSections with the same props instead. It returns an
array of the rendered sections, one element per section.
// app/routes/($locale).blogs.$handle.tsx
export default function BlogRoute() {
const { blog } = useLoaderData<{ blog: BlogPage }>();
return (
<div data-comp="BlogRoute">
<RenderSections content={blog} />
</div>
);
}
Article
This template will be used for all article pages in your storefront. The Blueprint renders it from two routes, /articles/:handle and /blogs/:blogHandle/:handle.
RenderSections renders the Customizer sections for the article. To arrange
them yourself, call useSections with the same props instead. It returns an
array of the rendered sections, one element per section.
// app/routes/($locale).articles.$handle.tsx
// and app/routes/($locale).blogs.$blogHandle.$handle.tsx
export default function ArticleRoute() {
const { article } = useLoaderData<{ article: ArticlePage }>();
return (
<div className="py-contained" data-comp="ArticleRoute">
<section data-comp="article-header">
{/* author, date, title, and category */}
</section>
<RenderSections content={article} />
</div>
);
}
Product
This template will be used for all product pages that follow the /products/:handle route in your storefront.
RenderSections renders the Customizer sections for /products/:handle. To arrange
them yourself, call useSections with the same props instead. It returns an
array of the rendered sections, one element per section.
// app/routes/($locale).products.$handle.tsx
export default function ProductRoute() {
const {
product: initialProduct,
productPage,
selectedVariant,
} = useLoaderData<{
product: ProductWithInitialGrouping;
productPage?: Page;
selectedVariant?: SelectedVariant;
}>();
// Adds the product's Pack grouping: options and variants across the grouped products
const product = useProductWithGrouping(initialProduct);
return (
<ProductProvider
data={product}
initialVariantId={selectedVariant?.id || null}
>
<div data-comp="ProductRoute">
<Product product={product} initialSelectedVariant={selectedVariant} />
{productPage && <RenderSections content={productPage} />}
</div>
{/* The Blueprint also renders <Analytics.ProductView> here. See the route implementation guide. */}
</ProductProvider>
);
}
Collection
This template will be used for all collection pages that follow the /collections/:handle route in your storefront.
RenderSections renders the Customizer sections for /collections/:handle. To arrange
them yourself, call useSections with the same props instead. It returns an
array of the rendered sections, one element per section.
// app/routes/($locale).collections.$handle.tsx
export default function CollectionRoute() {
const { activeFilterValues, collection, collectionPage } = useLoaderData<{
activeFilterValues: ActiveFilterValue[];
collection: CollectionType;
collectionPage?: Page;
}>();
// Hide the default collection heading when the page has a hero or banner section
const hasVisibleHeroSection = !!collectionPage?.sections.nodes.some(
({ data }: any) => ['hero', 'banner'].includes(data?._template),
);
return (
<div data-comp="CollectionRoute">
{collectionPage && <RenderSections content={collectionPage} />}
<section data-comp="collection">
<Collection
activeFilterValues={activeFilterValues}
collection={collection}
showHeading={!hasVisibleHeroSection}
title={collectionPage?.title}
/>
</section>
{/* The Blueprint also renders <Analytics.CollectionView> here. See the route implementation guide. */}
</div>
);
}
Account
The account template comprises multiple other sub-templates for routes such as sign-in, order history, address book, payment methods, and more.
All available sub-templates for the account template can be found in the /app/routes directory.
404
This template will be used for all 404 pages in your storefront.
The Blueprint's catch-all route throws a 404 from its loader, so the route itself renders nothing:
// app/routes/$.tsx
export async function loader({ request }: Route.LoaderArgs) {
throw new Response(`${new URL(request.url).pathname} not found`, {
status: 404,
});
}
export default function Route404() {
return null;
}
The root route's ErrorBoundary then renders the 404 page. In the Blueprint, that page isn't built from sections. It shows a banner from the Not Found (404) group in your site settings, which you edit in the Customizer.