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:
{
"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:
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:
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:
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:
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'squery
props.loading
: aboolean
flag to determine if the template'squery
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
locale?: string
}
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,
};
};