Skip to main content

Templates Overview

Templates in Faust bring the power of the WordPress Template Hierarchy to your JavaScript frontend application.

How Templates Are Resolved

The template resolver works by sending a preliminary GraphQL request (called the Seed Query) for the given URI in WordPress. The response includes data like the databaseId, slug, content type, etc, which is then used to determine what the possible templates are for the given URI.

For example, let's say a user visits the /sample-page URI on our Faust app, and in WordPress we have a page called "Sample Page" with the same URI. The template resolver will receive the following data as the Seed Query:

Seed Query Response
{
"data": {
"node": {
"__typename": "Page",
"uri": "/sample-page/",
"id": "cG9zdDoyNjQ=",
"databaseId": 264,
"isContentNode": true,
"slug": "sample-page",
"contentType": {
"node": {
"name": "page"
}
},
"template": {
"templateName": "Default"
},
"isFrontPage": false,
"isPostsPage": false
}
}
}

With this data, we then apply a set of rules/logic to get all the possible templates for the /sample-page route.

Setting Up the Template System

To setup your Faust template system, start by creating a directory in your project (it can be named anything, but we typically call it wp-templates). Inside this newly created directory, create index.js with an empty object as the default export:

wp-templates/index.js
export default {
// Templates go here
};

Templates must be placed in this object with the key being the template name, and the value being the default export of the template. For example:

wp-templates/index.js
import page from './page';
import single from './single';

export default {
page: page,
single: single,
};

Finally, you must include the templates in faust.config.js at your project root:

faust.config.js
import { setConfig } from '@faustwp/core';
import templates from './wp-templates/index.js';

/**
* @type {import('@faustwp/core').FaustConfig}
**/
export default setConfig({
templates: templates,
});

Template Structure

A faust template has three parts, the component, query, and variables. Here is an example template in its most basic form:

wp-templates/single.js
import { gql } from '@apollo/client';

// The Component is required
export default function Component(props) {
const { title, content } = props?.data?.post;

return (
<>
<h1>{title}</h1>
<div dangerouslySetInnerHTML={{ __html: content }} />
</>
);
}

// Query is optional
Component.query = gql`
query GetPost($databaseId: ID!) {
post(id: $databaseId, idType: DATABASE_ID) {
title
content
}
}
`;

// Variables is optional
Component.variables = (seedQuery, ctx) => {
return {
databaseId: seedQuery?.databaseId,
};
};

Component

The Component portion of the template serves as the rendering layer. You can compare this to a traditional Next.js file based page, where the contents of this component will be rendered to the webpage.

props are exposed to the Component as usual in React. There are two props that are specific to a template:

  • props.data: the response to the template's query
  • props.loading: a boolean flag to determine if the template's query is still being fetched

Component Variables

The Component.variables portion of the template is a callback function which returns an object of GraphQL variables for the template's GraphQL query.

The Component.variables() callback has two parameters: seedQuery, and context:

Component.variables(seedQuery, context) => {
return {
// Return GraphQL variables here as needed
}
}

The seedQuery parameter is the data resulted from the seed query. You can learn more about the request and response of the seed query here.

The context of Component.variables has the following properties:

interface {
asPreview?: boolean
}

Finally, the object returned from this function will be usable in your template's GraphQL Query.

Component Query

The Component.query portion of the template is a GraphQL query string used to fetch the template's data. It can be used as follows:

import { gql } from '@apollo/client';

Component.query = gql`
query GetPost($databaseId: ID!, $asPreview: Boolean = false) {
post(id: $databaseId, idType: DATABASE_ID, asPreview: $asPreview) {
title
content
}
}
`;

Notice the $databaseId and $asPreview variables as well. These are available because they were configured in the Component.variables callback:

Component.variables = (seedQuery, context) => {
return {
databaseId: seedQuery?.databaseId,
asPreview: context?.asPreview,
};
};