Yext recommends using React as the templating language for your pages. However, under the hood you can use any JavaScript-based templating language you want on top of the Pages system — and you can mix and match templating languages within one site.
The repo structure and general data flow are the exact same regardless of templating language. The main difference is that instead of exporting a TSX component as the default export, you export a render function. Note: when not using a TSX component, your export should NOT be the default export.
Note: Any templates written in pure JS will not support a live dev server with hot module reloading (HMR). This feature is limited to React at the moment. To preview your changes locally, you must build, generate, and serve locally using the Pages CLI — see the instructions for
yext pages serve.
React
Here is an example of a template using React. Note that we are exporting the default function.
import * as React from "react";
import { GetPath, Template, TemplateProps, TemplateRenderProps } from "@yext/pages";
const template: Template<TemplateRenderProps> = ({ document }) => {
const { name, address } = document;
return (
<>
<h1>{name}</h1>
<div>
<div>{address.line1}</div>
<div>
{address.city}, {address.region}
</div>
</div>
</>
);
};
// EXPORT DEFAULT FUNCTION
export default template;
Pure JS
Here is an example that doesn't use React. A few things to notice:
- We are exporting a
renderfunction as a named export instead of the default. - The
renderfunction takes the same props as the React template. - In this example, a JavaScript template literal is used to render the page.
- The function returns the full
htmldocument instead of just the body. When using arenderfunction,getHeadConfigwon't work — embed anything in the head directly in the return value.
export const render: Render<TemplateRenderProps> = ({ document }) => {
const { name, address } = document;
return `
<!DOCTYPE html>
<html>
<head>
<title>${name}</title>
</head>
<body>
<h1>${name}</h1>
<div>
<div>${address.line1}</div>
<div>
${address.city}, ${address.region}
</div>
</div>
</body>
</html>
`;
};
// NO DEFAULT EXPORT
Handlebars
Because this is pure JS rendering, you can use any templating language that supports JS. For example, here is how you could use Handlebars as the templating language.
Note: First install Handlebars with
npm install handlebars.
Instead of using a template literal, we are compiling a Handlebars template and then using that to generate the HTML.
import * as hbs from "handlebars";
export const render: Render<TemplateRenderProps> = ({ document }) => {
const hbsTemplateString = `
<!DOCTYPE html>
<html>
<head>
<title>{{name}}</title>
</head>
<body>
<h1>{{name}}</h1>
<div>
<div>{{address.line1}}</div>
<div>
{{address.city}}, {{address.region}}
</div>
</div>
</body>
</html>
`;
// Compile Template
const hbsTemplate = hbs.compile(hbsTemplateString);
// Render HTML
return hbsTemplate(document);
};
// NO DEFAULT EXPORT
Recap
- Export
renderinstead of a default export. -
rendershould return the full HTML document as a string instead of just the TSX body. - Props to the
renderfunction are the same as props to the TSX component. -
getHeadConfigdoes not work when using a non-React templating language. -
getPathis the same between React and non-React template approaches.