### Simple Fastify View Setup Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Basic configuration for Fastify View with EJS. Ensure the 'ejs' package is installed. ```javascript fastify.register(fastifyView, { engine: { ejs: require('ejs') }, root: './views' }); ``` -------------------------------- ### Basic @fastify/view Setup with EJS Source: https://github.com/fastify/point-of-view/blob/main/README.md Register the @fastify/view plugin with Fastify, configuring it to use the EJS engine. This example demonstrates both synchronous and asynchronous handler implementations for rendering templates. ```html

Hello, <%= name %>!

``` ```javascript // index.js: const fastify = require("fastify")() const fastifyView = require("@fastify/view") fastify.register(fastifyView, { engine: { ejs: require("ejs") } }) // synchronous handler: fastify.get("/", (req, reply) => { reply.view("index.ejs", { name: "User" }); }) // asynchronous handler: fastify.get("/", async (req, reply) => { return reply.viewAsync("index.ejs", { name: "User" }); }) fastify.listen({ port: 3000 }, (err) => { if (err) throw err; console.log(`server listening on ${fastify.server.address().port}`); }) ``` -------------------------------- ### Install @fastify/view Source: https://github.com/fastify/point-of-view/blob/main/README.md Install the @fastify/view package using npm. ```bash npm i @fastify/view ``` -------------------------------- ### Basic Fastify View Setup with EJS Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/INDEX.md This snippet demonstrates the fundamental setup for using the Fastify View plugin with the EJS templating engine. It registers the plugin, configures the template root, and defines a basic route to render an EJS template. ```javascript const fastify = require('fastify')(); const fastifyView = require('@fastify/view'); fastify.register(fastifyView, { engine: { ejs: require('ejs') }, root: './views' }); fastify.get('/', (req, reply) => { reply.view('index.ejs', { name: 'User' }); }); fastify.listen({ port: 3000 }); ``` -------------------------------- ### Basic View Rendering with Handlebars Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Example of registering the view engine and rendering a Handlebars template with data in a Fastify route. ```javascript fastify.register(fastifyView, { engine: { handlebars: require('handlebars') }, options: { partials: { header: 'header.hbs', footer: 'footer.hbs' } } }); fastify.get('/', (req, reply) => { reply.view('index.hbs', { title: 'Home', items: [] }); }); ``` -------------------------------- ### Initialize Liquid Engine Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Instantiate the Liquid engine with specified root directory and file extension. This setup is required before registering it with Fastify. ```javascript const { Liquid } = require('liquidjs'); const engine = new Liquid({ root: path.join(__dirname, 'templates'), extname: '.liquid' }); engine: { liquid: engine } ``` -------------------------------- ### Fastify View Setup with Layouts and Default Context Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Configure Fastify View to use Handlebars with a specified layout file and default context variables. The 'handlebars' package must be installed. ```javascript fastify.register(fastifyView, { engine: { handlebars: require('handlebars') }, root: './views', layout: 'layout.hbs', defaultContext: { siteName: 'MyApp' } }); ``` -------------------------------- ### Basic Fastify Setup with Point-of-View Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Registers the @fastify/view plugin and sets up a basic route to render an EJS template. Ensure you have an 'index.ejs' file in a 'views' directory. ```javascript const fastify = require('fastify')(); const fastifyView = require('@fastify/view'); // Register the plugin fastify.register(fastifyView, { engine: { ejs: require('ejs') }, root: './views' }); // Render a template fastify.get('/', (req, reply) => { reply.view('index.ejs', { name: 'User' }); }); fastify.listen({ port: 3000 }); ``` -------------------------------- ### Edge.js Template Syntax Example Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Demonstrates Edge.js syntax for comments, variable interpolation, conditionals, loops, includes, and components. ```html @!-- Comments -- {{ variable }} @if(isAdmin) @endif @each(item in items)

{{ item.name }}

@endeach @include('header') @component('card', { title: 'Card Title' }) Card content here @endcomponent ``` -------------------------------- ### Pug Usage Examples Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Demonstrates rendering Pug templates using Fastify's reply.view method, including raw templates and pre-compiled functions. ```javascript fastify.register(fastifyView, { engine: { pug: require('pug') }, root: './views' }); fastify.get('/', (req, reply) => { reply.view('index.pug', { name: 'John' }); }); // Raw template fastify.get('/raw', (req, reply) => { reply.view({ raw: 'p Hello, #{name}!' }, { name: 'World' }); }); // Compiled function fastify.get('/compiled', (req, reply) => { const compiled = pug.compile('p= message'); reply.view(compiled, { message: 'Hello' }); }); ``` -------------------------------- ### Pug Template Syntax Example Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates Pug's syntax for comments, variable interpolation, conditional rendering, loops, includes, and inheritance. ```pug //- Comments in Pug Multiple lines //- Single line comment //Single line without dash (will be output as HTML comment) p Hello, #{name}! if loggedIn p Welcome back! else p Please log in. ul each item in items li= item include header.pug main block content p Default content extends layout.pug block content p Page content ``` -------------------------------- ### Twig Template Syntax Example Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates Twig's syntax for comments, variable output, conditional rendering, loops, includes, and macro imports. ```html {# Comments #} {{ variable }} {% if isAdmin %} {% endif %} {% for item in items %}

{{ item.name }}

{% endfor %} {{ name|uppercase }} {% include 'header.twig' %} {% import 'macros.twig' as macros %} ``` -------------------------------- ### doT Template Syntax Example Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates basic doT template syntax for comments, variable output (escaped and unescaped), conditionals, and loops. ```dot {{! Comments }} Escapes HTML by default: {{=it.variable}} Don't escape: {{~it.htmlContent}} Conditionals: {{?it.isAdmin}} {{?}} Loops: {{~it.items :item}}

{{=item.name}}

{{~}} In layout: {{~it.body}} ``` -------------------------------- ### Nunjucks Template Syntax Examples Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates common Nunjucks template syntax, including variable output, conditionals, loops, includes, inheritance, and filters. ```html

{{ variable }}

{% if isAdmin %} {% endif %} {% include "header.njk" %} {% extends "base.njk" %} {% block content %}

Page content

{% endblock %}

{{ name | uppercase }}

``` -------------------------------- ### Eta Template Syntax Examples Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates common Eta template syntax for HTML escaping, raw HTML output, conditionals, loops, layout rendering, and includes. ```html

<%= it.variable %>

<%~ it.htmlContent %>
<% if (it.isAdmin) { %> <% } %> <%~ it.body %> <%~ include('header') ``` -------------------------------- ### Squirrelly Template Syntax Examples Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates common Squirrelly template syntax for variable output, conditionals, loops, includes, and filters. ```html {{variable}} {{#if isAdmin}} {{/if}} {{#each items}}

{{this.name}}

{{/each}} {{#include('header')}} {{variable | uppercase}} ``` -------------------------------- ### Mustache Template Syntax Example Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates common Mustache template syntax including variable substitution, conditionals, loops, partials, and comments. ```html

Hello, {{name}}!

{{#loggedIn}}

Welcome back!

{{/loggedIn}} {{^loggedIn}}

Please log in.

{{/loggedIn}} {{> header}}
{{> content}}
{{> footer}} {{! This is a comment }} ``` -------------------------------- ### Twig Usage Examples Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Demonstrates rendering Twig templates using Fastify's reply.view method, including raw templates and pre-compiled template objects. ```javascript fastify.register(fastifyView, { engine: { twig: require('twig') }, root: './views' }); fastify.get('/', (req, reply) => { reply.view('index.twig', { items: [] }); }); // Raw template fastify.get('/raw', (req, reply) => { reply.view({ raw: '

{{ message }}

' }, { message: 'Hello' }); }); // Compiled template fastify.get('/compiled', (req, reply) => { const compiled = twig.twig({ data: '

{{ name }}

' }); reply.view(compiled, { name: 'World' }); }); ``` -------------------------------- ### Liquid Template Syntax Examples Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates common Liquid template syntax, including comments, variable output, conditional statements, loops, filters, includes, and variable assignments. ```liquid {# Comments #} {{ variable }} {% if isAdmin %} {% endif %} {% for item in items %}

{{ item.name }}

{% endfor %} {{ name | upcase }} {% include 'header.liquid' %} {% assign greeting = "Hello" %} ``` -------------------------------- ### Register and Use Liquid Engine for Views Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Register the configured Liquid engine with Fastify Point of View and demonstrate rendering a template. Includes an example for rendering a template directly from a string. ```javascript const { Liquid } = require('liquidjs'); const engine = new Liquid({ root: path.join(__dirname, 'templates'), extname: '.liquid' }); fastify.register(fastifyView, { engine: { liquid: engine } }); fastify.get('/', (req, reply) => { return reply.viewAsync('index.liquid', { items: [] }); }); // Raw template fastify.get('/raw', (req, reply) => { return reply.viewAsync( { raw: '{{ greeting }} {{ name }}' }, { greeting: 'Hello', name: 'World' } ); }); ``` -------------------------------- ### Fastify View Setup with HTML Minification Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Configure Fastify View with EJS and enable HTML minification using 'html-minifier-terser'. Specify minifier options to control the output. ```javascript const minifier = require('html-minifier-terser'); fastify.register(fastifyView, { engine: { ejs: require('ejs') }, options: { useHtmlMinifier: minifier, htmlMinifierOptions: { removeComments: true, collapseWhitespace: true } } }); ``` -------------------------------- ### Render Template with Fastify View (Promise-based) Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/api-reference.md Use fastify.view with async/await to render a template and get the HTML as a Promise. This method does not have access to reply.locals. ```javascript fastify.get('/', async (req, reply) => { const html = await fastify.view('template.ejs', { text: 'Hello' }); reply.type('text/html').send(html); }); ``` -------------------------------- ### EJS Layout Example Source: https://github.com/fastify/point-of-view/blob/main/README.md Defines a basic EJS layout structure, including how to render the main content body without escaping. ```html <%- body %>
``` -------------------------------- ### EJS Template Syntax Examples Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Illustrates common EJS template syntax for HTML escaping, raw HTML output, conditional rendering, and looping through data. ```html

<%= variable %>

<%- htmlContent %>
<% if (isAdmin) { %> <% } %> <%- body %> ``` -------------------------------- ### Register Fastify View Plugin Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Register the @fastify/view plugin using Fastify's register method. This is the basic setup before applying any specific configurations. ```javascript const fastify = require('fastify')(); const fastifyView = require('@fastify/view'); fastify.register(fastifyView, { // Configuration options here }); ``` -------------------------------- ### Catching Layout File Not Found Error Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/errors.md This example shows how to use a try-catch block to specifically catch errors related to a missing layout template file when registering Fastify View. ```javascript try { await fastify.register(fastifyView, { engine: { ejs: require('ejs') }, root: './views', layout: 'missing.ejs' }); } catch (err) { if (err.message.includes('unable to access template')) { console.error(`Layout file not found: ${err.message}`); } } ``` -------------------------------- ### Fastify View Setup with Custom Nunjucks Options Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Integrate Nunjucks with Fastify View, specifying a custom template directory and configuring Nunjucks options, such as adding custom filters. The 'nunjucks' package is required. ```javascript fastify.register(fastifyView, { engine: { nunjucks: require('nunjucks') }, templates: './views', options: { onConfigure: (env) => { env.addFilter('uppercase', s => s.toUpperCase()); } } }); ``` -------------------------------- ### Catching Template Syntax Error Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/errors.md This example demonstrates how to catch template syntax errors by using a try-catch block around `reply.viewAsync` and checking the error message for common indicators like 'Unexpected'. ```javascript fastify.get('/', async (req, reply) => { try { return reply.viewAsync('template.ejs', {}); } catch (err) { if (err.message.includes('Unexpected')) { reply.status(400).send({ error: 'Template syntax error' }); } else { reply.send(err); } } }); ``` -------------------------------- ### Configure Nunjucks Template Engine Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Specify Nunjucks as the template engine for @fastify/view. Ensure you have Nunjucks installed (`npm install nunjucks`). ```javascript // Using Nunjucks fastify.register(fastifyView, { engine: { nunjucks: require('nunjucks') } }); ``` -------------------------------- ### Configure EJS Template Engine Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Specify EJS as the template engine for @fastify/view. Ensure you have EJS installed (`npm install ejs`). ```javascript // Using EJS fastify.register(fastifyView, { engine: { ejs: require('ejs') } }); ``` -------------------------------- ### Configure Liquid Template Engine with Custom Options Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Configure the Liquid template engine with custom options, such as root directory and file extension. Ensure you have liquidjs installed (`npm install liquidjs`). ```javascript // Using Liquid with configuration const { Liquid } = require('liquidjs'); const engine = new Liquid({ root: path.join(__dirname, 'templates'), extname: '.liquid' }); fastify.register(fastifyView, { engine: { liquid: engine } }); ``` -------------------------------- ### Configure Edge.js Engine with Fastify View Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Set up the Edge.js template engine, mount its template directory, and register it with @fastify/view. ```javascript const { Edge } = require('edge.js'); const path = require('path'); const engine = new Edge(); engine.mount(path.join(__dirname, 'templates')); fastify.register(fastifyView, { engine: { edge: engine } }); ``` -------------------------------- ### EJS Template Example Source: https://github.com/fastify/point-of-view/blob/main/README.md A simple EJS template that displays a variable 'text'. ```html

<%= text %>

``` -------------------------------- ### Basic Nunjucks View Rendering Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Demonstrates registering Nunjucks with a single template directory and rendering a view with context data. ```javascript fastify.register(fastifyView, { engine: { nunjucks: require('nunjucks') }, templates: 'views', options: { onConfigure: (env) => { env.addFilter('lowercase', (str) => str.toLowerCase()); } } }); fastify.get('/', (req, reply) => { reply.view('index.njk', { title: 'Home', items: [] }); }); ``` -------------------------------- ### Register Squirrelly Engine with Fastify Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Register the Squirrelly template engine with Fastify Point-of-View. Ensure Squirrelly is installed via npm. ```javascript fastify.register(fastifyView, { engine: { squirrelly: require('squirrelly') }, templates: 'views' }); ``` -------------------------------- ### Configure Twig Engine Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Register the Twig engine with Fastify's Point-of-View plugin. Ensure Twig is installed via npm. ```javascript fastify.register(fastifyView, { engine: { twig: require('twig') }, root: './views' }); ``` -------------------------------- ### Configure Pug Engine Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Register the Pug engine with Fastify's Point-of-View plugin. Ensure Pug is installed via npm. ```javascript fastify.register(fastifyView, { engine: { pug: require('pug') }, root: './views' }); ``` -------------------------------- ### Register Handlebars Engine Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Register the Handlebars engine with Fastify's view plugin. Ensure Handlebars is installed via npm. ```javascript engine: { handlebars: require('handlebars') } ``` -------------------------------- ### Basic Fastify View Rendering with Eta Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Register the Eta engine and define a route to render a view using reply.view(). ```javascript const { Eta } = require('eta'); const eta = new Eta(); fastify.register(fastifyView, { engine: { eta: eta }, templates: 'views' }); fastify.get('/', (req, reply) => { reply.view('index.eta', { title: 'Home' }); }); ``` -------------------------------- ### Generate Static Site Pages Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/advanced-patterns.md Render multiple templates and write the output to static HTML files. This uses `fs/promises` for file operations and `fastify.view()` for rendering. The generation is hooked to run when the server is ready. ```javascript const fs = require('fs/promises'); async function generateStaticSite() { const pages = [ { path: 'index.html', template: 'home.ejs', data: {} }, { path: 'about.html', template: 'about.ejs', data: {} }, { path: 'contact.html', template: 'contact.ejs', data: {} } ]; for (const page of pages) { const html = await fastify.view(page.template, page.data); await fs.writeFile(`./dist/${page.path}`, html); } } // Run before server starts fastify.addHook('onReady', generateStaticSite); ``` -------------------------------- ### Register doT with Layout and Render View Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Configure doT with a layout file and demonstrate rendering a view with data. Extension is not needed when specifying a layout. ```javascript fastify.register(fastifyView, { engine: { dot: require('dot') }, root: 'templates', layout: 'layout.dot', options: { destination: 'dot-compiled' } }); fastify.get('/', (req, reply) => { reply.view('index', { items: [] }); // Note: no extension needed }); ``` -------------------------------- ### Configure Fastify Point-of-View with EJS Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Register the Point-of-View plugin with EJS as the engine, specifying the root directory for templates. This setup is required before rendering views. ```typescript import fastifyView from '@fastify/view'; import ejs from 'ejs'; fastify.register(fastifyView, { engine: { ejs }, root: './views' }); fastify.get('/', async (req, reply) => { return reply.viewAsync('index.ejs', { data: 'value' }); }); ``` -------------------------------- ### Register Eta Engine with Fastify Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Instantiate the Eta engine and register it with the fastify-view plugin. Specify the views directory and layout file. ```javascript const { Eta } = require('eta'); fastify.register(fastifyView, { engine: { eta: new Eta() }, templates: 'views', layout: 'layout.eta', options: { async: false, // Set to true for async rendering cache: true, // Enable caching templatesSync: null // Precompiled templates } }); ``` -------------------------------- ### Configuring Layouts for Templates Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Shows how to set a global layout file for all templates and how to override it for specific routes. Supported engines include EJS, Handlebars, Eta, and doT. ```javascript fastify.register(fastifyView, { engine: { ejs: require('ejs') }, layout: 'layout.ejs' // Global layout }); fastify.get('/special', (req, reply) => { // Override layout for specific route return reply.viewAsync('page.ejs', {}, { layout: 'special.ejs' }); }); ``` ```html ``` -------------------------------- ### Render Mustache Template with Data Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Example of rendering a Mustache template with dynamic data. The `reply.view` method is used to send the rendered template to the client. ```javascript fastify.get('/', (req, reply) => { reply.view('index.mustache', { name: 'John', loggedIn: true, items: ['Item 1', 'Item 2'] }); }); ``` -------------------------------- ### Configure Handlebars with Partials and Compile Options Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Sets up Handlebars with partial templates and specific compilation options. ```javascript fastify.register(fastifyView, { engine: { handlebars: require('handlebars') }, options: { partials: { header: 'header.hbs', footer: 'footer.hbs' }, compileOptions: { preventIndent: true }, useDataVariables: true // Access defaultContext and reply.locals as @data } }); ``` -------------------------------- ### Render EJS Template in Fastify Route Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Handles a GET request by rendering an EJS template. Pass data to the template for dynamic content generation. ```javascript fastify.get('/', (req, reply) => { reply.view('index.ejs', { username: 'John' }); }); ``` -------------------------------- ### Liquid Engine Configuration Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/types.md Configure the Liquid engine by importing 'Liquid' from 'liquidjs' and providing an instance of the Liquid class. Options can be passed to the constructor. ```javascript const { Liquid } = require('liquidjs'); engine: { liquid: new Liquid(/* options */) // Instance of Liquid class } ``` -------------------------------- ### Register Fastify View with EJS Engine Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/api-reference.md Register the Fastify View plugin with the EJS engine. Ensure the 'ejs' package is installed and the 'views' directory exists. ```javascript const fastify = require('fastify')(); const fastifyView = require('@fastify/view'); fastify.register(fastifyView, { engine: { ejs: require('ejs') }, root: './views', charset: 'utf-8' }); fastify.listen({ port: 3000 }); ``` -------------------------------- ### Async View Rendering with Eta Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Demonstrates how to perform asynchronous view rendering using reply.viewAsync() in a Fastify route. ```javascript // Async rendering fastify.get('/async', async (req, reply) => { const html = await reply.viewAsync('index.eta', { title: 'Async' }); reply.send(html); }); ``` -------------------------------- ### Eta Engine Configuration Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/types.md Configure the Eta engine by providing an instance of the Eta class. This instance must have .render(), .renderAsync(), and .compile() methods. ```javascript engine: { eta: new Eta() // Instance of Eta class with .render(), .renderAsync(), .compile() methods } ``` -------------------------------- ### Device-Specific Rendering with @fastify/view Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/advanced-patterns.md Implement device-specific rendering by registering multiple instances of @fastify/view, each with different layout files and root directories. The appropriate renderer is selected based on the user agent. ```javascript fastify.register(fastifyView, { engine: { ejs: require('ejs') }, layout: 'layouts/desktop.ejs', propertyName: 'desktop', root: './templates/desktop' }); fastify.register(fastifyView, { engine: { ejs: require('ejs') }, layout: 'layouts/mobile.ejs', propertyName: 'mobile', root: './templates/mobile' }); fastify.get('/', (req, reply) => { const isMobile = /mobile|tablet/i.test(req.headers['user-agent']); const renderer = isMobile ? reply.mobile : reply.desktop; return renderer('index.ejs', { data: 'value' }); }); ``` -------------------------------- ### Configure Nunjucks Environment with Callback Source: https://github.com/fastify/point-of-view/blob/main/README.md Allows custom configuration of the Nunjucks environment after initialization by providing an 'onConfigure' callback function. ```javascript options: { onConfigure: (env) => { // do whatever you want on nunjucks env } } ``` -------------------------------- ### Configure Nunjucks with Multiple Template Directories Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Register the Nunjucks engine with Fastify, specifying multiple template directories and configuring the Nunjucks environment with custom globals and filters. ```javascript fastify.register(fastifyView, { engine: { nunjucks: require('nunjucks') }, templates: ['views', 'node_modules/shared-components'], // Multiple paths options: { onConfigure: (env) => { // Configure Nunjucks environment env.addGlobal('siteName', 'MyApp'); env.addFilter('capitalize', (str) => { return str.charAt(0).toUpperCase() + str.slice(1); }); } } }); ``` -------------------------------- ### Register Edge.js and Render View Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Configures the Edge.js engine, registers it with @fastify/view, and shows how to render an Edge template with data. ```javascript const { Edge } = require('edge.js'); const path = require('path'); const engine = new Edge(); engine.mount(path.join(__dirname, 'templates')); fastify.register(fastifyView, { engine: { edge: engine } }); fastify.get('/', (req, reply) => { reply.view('index.edge', { title: 'Home' }); }); ``` -------------------------------- ### Pre-validate Template Existence Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/errors.md Implement a check for template file existence before rendering to prevent 'Missing page' errors. This example uses Node.js `fs` and `path` modules. ```javascript const fs = require('fs'); const path = require('path'); function templateExists(templatePath, root = './views') { return fs.existsSync(path.join(root, templatePath)); } fastify.get('/', (req, reply) => { if (!templateExists('index.ejs')) { reply.status(500).send({ error: 'Template not found' }); return; } reply.view('index.ejs', {}); }); ``` -------------------------------- ### Precompile EJS Templates at Startup Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/advanced-patterns.md Optimize template rendering performance by precompiling all EJS templates in a directory at application startup. This avoids repeated compilation during requests. ```javascript const ejs = require('ejs'); const fs = require('fs'); const path = require('path'); // Precompile templates at startup function precompileTemplates(templateDir) { const templates = new Map(); const files = fs.readdirSync(templateDir); for (const file of files) { if (file.endsWith('.ejs')) { const source = fs.readFileSync(path.join(templateDir, file), 'utf-8'); templates.set(file, ejs.compile(source)); } } return templates; } const precompiled = precompileTemplates('./templates'); fastify.get('/', (req, reply) => { return reply.viewAsync(precompiled.get('index.ejs'), { data: 'value' }); }); ``` -------------------------------- ### Clear Cache Periodically Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/advanced-patterns.md Set up an interval to periodically clear the template cache, for example, every hour. This is useful for ensuring updated templates are used without manual intervention. ```javascript // Clear cache periodically fastify.register(async (fastify) => { setInterval(() => { fastify.view.clearCache(); }, 60 * 60 * 1000); // Every hour }); ``` -------------------------------- ### Catching Missing Page Error with reply.viewAsync Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/errors.md This example demonstrates how to catch the 'Missing page' error when using `reply.viewAsync` by wrapping the call in a try-catch block and checking the error message. ```javascript fastify.get('/', async (req, reply) => { try { const html = await reply.viewAsync('index.ejs', {}); reply.send(html); } catch (err) { if (err.message === 'Missing page') { reply.status(500).send({ error: 'Template not specified' }); } } }); ``` -------------------------------- ### Configure Mustache with Partials Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Sets up Mustache rendering with specified partial templates. ```javascript fastify.register(fastifyView, { engine: { mustache: require('mustache') }, options: { partials: { header: 'header.mustache', footer: 'footer.mustache' } } }); ``` -------------------------------- ### Configure Liquid Engine and Root Path Source: https://github.com/fastify/point-of-view/blob/main/README.md Configures the Liquid engine for Fastify, specifying the root directory for templates and the file extension. ```javascript const { Liquid } = require("liquidjs"); const path = require('node:path'); const engine = new Liquid({ root: path.join(__dirname, "templates"), extname: ".liquid", }); fastify.register(require("@fastify/view"), { engine: { liquid: engine, }, }); fastify.get("/", (req, reply) => { reply.view("./templates/index.liquid", { text: "text" }); }); ``` -------------------------------- ### Global Layout with Content Blocks Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/advanced-patterns.md Configure a global default layout and default context for all views. The layout file uses Handlebars syntax to structure the HTML, with `{{{body}}}` rendering the content of the specific view. This is useful for maintaining a consistent site structure across your application. ```javascript fastify.register(fastifyView, { engine: { handlebars: require('handlebars') }, layout: 'layout.hbs', defaultContext: { siteName: 'MyApp' } }); // layout.hbs /* {{siteName}} - {{pageTitle}}

{{siteName}}

{{{body}}}
*/ fastify.get('/', (req, reply) => { return reply.viewAsync('home.hbs', { pageTitle: 'Home' }); }); fastify.get('/about', (req, reply) => { return reply.viewAsync('about.hbs', { pageTitle: 'About Us' }); }); ``` -------------------------------- ### Rendering Templates with Different Data Formats Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/INDEX.md Illustrates how to render templates using different data formats: a file path, a pre-compiled template function, or a raw template string. This provides flexibility in how templates are provided to the view engine. ```javascript // String: file path reply.view('index.ejs', {}) ``` ```javascript // Function: compiled template const compiled = ejs.compile('

<%= name %>

'); reply.view(compiled, { name: 'John' }) ``` ```javascript // Raw string: template content reply.view({ raw: '

<%= name %>

' }, { name: 'Jane' }) ``` -------------------------------- ### Configure Production Caching Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/advanced-patterns.md Enable production mode caching with a specified maximum cache size. Ensure 'production' is set to true when NODE_ENV is 'production'. ```javascript fastify.register(fastifyView, { engine: { ejs: require('ejs') }, production: process.env.NODE_ENV === 'production', maxCache: 500, // Increase for large applications includeViewExtension: true }); ``` -------------------------------- ### Register doT with Fastify Point-of-View Source: https://github.com/fastify/point-of-view/blob/main/README.md Configure Fastify to use the doT template engine. Ensure the 'root' or 'templates' option is provided to specify the template directory. This pre-compiles templates on application start. ```javascript fastify.register(require("@fastify/view"), { engine: { dot: require("dot"), }, root: "templates", options: { destination: "dot-compiled", // path where compiled .jst files are placed (default = 'out') }, }); fastify.get("/", (req, reply) => { // this works both for .jst and .dot files reply.view("index", { text: "text" }); }); ``` -------------------------------- ### Configure EJS with Async and Filename Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Enables asynchronous rendering and specifies the directory for EJS views. ```javascript fastify.register(fastifyView, { engine: { ejs: require('ejs') }, options: { async: true, // Enable async mode filename: path.join(__dirname, 'views') } }); ``` -------------------------------- ### TypeScript Typing for reply.locals in Fastify Source: https://github.com/fastify/point-of-view/blob/main/README.md Define TypeScript interfaces for reply.locals to enable type checking and autocompletion for custom reply properties. This setup is useful for managing application-specific data within Fastify replies. ```typescript interface Locals { appVersion: string; isAuthorized: boolean; user?: { id: number; login: string; }; } declare module "fastify" { interface FastifyReply { locals: Partial | undefined; } } app.addHook("onRequest", (request, reply, done) => { if (!reply.locals) { reply.locals = {}; } reply.locals.isAuthorized = true; reply.locals.user = { id: 1, login: "Admin", }; }); app.get("/data", (request, reply) => { if (!reply.locals) { reply.locals = {}; } // reply.locals.appVersion = 1 // not a valid type reply.locals.appVersion = "4.14.0"; reply.view<{ text: string }>("/index", { text: "Sample data" }); }); ``` -------------------------------- ### Catching Template File Not Found Error (ENOENT) Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/errors.md This example demonstrates how to catch a 'template file not found' error, identified by the 'ENOENT' error code, when using `reply.viewAsync`. It sends a 500 status with an error message if the file is not found. ```javascript fastify.get('/', async (req, reply) => { try { return reply.viewAsync('index.ejs', {}); } catch (err) { if (err.code === 'ENOENT') { reply.status(500).send({ error: 'Template not found' }); } else { reply.send(err); } } }); ``` -------------------------------- ### reply.view() Method Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Synchronously renders a view using the configured template engine. ```APIDOC ## reply.view() Method ### Description This method is available on the Fastify reply object and is used to synchronously render a view template. ### Method `reply.view(templatePath, [context], [options])` ### Parameters #### Path Parameters - **templatePath** (string) - Required - The path to the template file to render. #### Context - **context** (object) - Optional - Data to be passed to the template for rendering. #### Options - **options** (object) - Optional - Route-specific rendering options, overriding global plugin options. - **layout** (string) - Optional - Path to a layout template. - **viewExt** (string) - Optional - File extension for the template. - **context** (object) - Optional - Additional context data for this specific render. - **cache** (string) - Optional - Cache strategy for this render. ``` -------------------------------- ### fastify.view() Method Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Globally renders a view using the configured template engine. ```APIDOC ## fastify.view() Method ### Description This method is available on the Fastify instance and can be used to render a view template globally, outside of a request context. ### Method `fastify.view(templatePath, [context], [options])` ### Parameters #### Path Parameters - **templatePath** (string) - Required - The path to the template file to render. #### Context - **context** (object) - Optional - Data to be passed to the template for rendering. #### Options - **options** (object) - Optional - Global rendering options. - **layout** (string) - Optional - Path to a layout template. - **viewExt** (string) - Optional - File extension for the template. - **context** (object) - Optional - Additional context data for this render. - **cache** (string) - Optional - Cache strategy for this render. ``` -------------------------------- ### reply.view() / reply.{propertyName}() Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/api-reference.md Synchronously renders an HTML template and immediately sends the response. It accepts a template path, a compiled function, or a raw string, along with optional data and route-specific options. ```APIDOC ## reply.view() / reply.{propertyName}() ### Description Synchronous template rendering method that immediately sends the rendered HTML response. ### Signature ```typescript function view(page: string | Function | { raw: string }, data?: T, opts?: RouteSpecificOptions): FastifyReply ``` ### Parameters #### Path Parameters - **page** (string | Function | { raw: string }) - Required - Template file path, compiled template function, or raw template string via `{ raw: string }` object - **data** (object) - Optional - Data object passed to template for rendering - **opts** (RouteSpecificOptions) - Optional - Route-specific options, currently supports `layout` property to override global layout ### Returns `FastifyReply` - The reply object for method chaining ### Throws - `Error: Missing page` - if page parameter is falsy or undefined - Template engine errors - if template rendering fails - Immediately sends 500 response with error if rendering fails ### Usage Examples ```javascript // Basic rendering fastify.get('/', (req, reply) => { reply.view('index.ejs', { name: 'User' }); }); // With custom layout per-route fastify.get('/special', (req, reply) => { reply.view('special.ejs', { data: 'value' }, { layout: 'special-layout.ejs' }); }); // Rendering from compiled function fastify.get('/compiled', (req, reply) => { const compiled = ejs.compile('

<%= name %>

'); reply.view(compiled, { name: 'John' }); }); // Raw template string fastify.get('/raw', (req, reply) => { reply.view({ raw: '

<%= message %>

' }, { message: 'Hello' }); }); ``` ``` -------------------------------- ### reply.viewAsync() Method Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Asynchronously renders a view using the configured template engine. ```APIDOC ## reply.viewAsync() Method ### Description This method is available on the Fastify reply object and is used to asynchronously render a view template. It returns a Promise that resolves with the rendered HTML. ### Method `reply.viewAsync(templatePath, [context], [options])` ### Parameters #### Path Parameters - **templatePath** (string) - Required - The path to the template file to render. #### Context - **context** (object) - Optional - Data to be passed to the template for rendering. #### Options - **options** (object) - Optional - Route-specific rendering options, overriding global plugin options. - **layout** (string) - Optional - Path to a layout template. - **viewExt** (string) - Optional - File extension for the template. - **context** (object) - Optional - Additional context data for this specific render. - **cache** (string) - Optional - Cache strategy for this render. ``` -------------------------------- ### Render Raw Mustache Template String Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/template-engines.md Demonstrates rendering a template directly from a string using the `raw` option in `reply.view`, bypassing file loading. ```javascript fastify.get('/raw', (req, reply) => { reply.view({ raw: '

{{message}}

' }, { message: 'Hello' }); }); ``` -------------------------------- ### FastifyInstance View Methods Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/types.md Augments FastifyInstance with methods for rendering views without request context and for clearing the template cache. ```APIDOC ## FastifyInstance View Methods ### Description Augments `FastifyInstance` with methods to render views outside of a request context and to clear the template cache. ### Methods #### `view(page: string | Function | { raw: string }, data: T, opts?: RouteSpecificOptions): Promise` Renders a view without request context and returns a Promise resolving to the rendered string. #### `view(page: string | Function | { raw: string }, data?: object, opts?: RouteSpecificOptions): Promise` Renders a view without request context with optional data and options, returning a Promise resolving to the rendered string. #### `view.clearCache(): void` Clears the template cache. ``` -------------------------------- ### Render Email Template Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/advanced-patterns.md Use `fastify.view()` to render an EJS template for sending a welcome email. Pass user-specific data as the second argument. ```javascript async function sendWelcomeEmail(user) { const html = await fastify.view('emails/welcome.ejs', { name: user.name, activationUrl: `https://example.com/activate?token=${user.token}`, expiresIn: '24 hours' }); await mailer.send({ to: user.email, subject: 'Welcome to MyApp!', html: html }); } ``` -------------------------------- ### Registering Multiple Fastify View Instances for Different Properties Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/README.md Configure separate instances of Fastify View, each with its own property name, to handle different rendering contexts (e.g., desktop and mobile). Requires the 'ejs' package. ```javascript // Desktop fastify.register(fastifyView, { engine: { ejs: require('ejs') }, propertyName: 'desktop' }); // Mobile fastify.register(fastifyView, { engine: { ejs: require('ejs') }, propertyName: 'mobile' }); ``` -------------------------------- ### Configure Fastify View with Handlebars and Layouts Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/api-reference.md Register Fastify View with Handlebars, specifying a root directory for views, a global layout file, a custom view extension, and engine-specific options for partials. ```javascript fastify.register(fastifyView, { engine: { handlebars: require('handlebars') }, root: path.join(__dirname, 'views'), layout: './templates/layout.hbs', viewExt: 'handlebars', propertyName: 'render', maxCache: 200, production: true, defaultContext: { siteName: 'MyAwesomeSite', dev: process.env.NODE_ENV === 'development' }, options: { partials: { header: 'header.hbs', footer: 'footer.hbs' } } }); ``` -------------------------------- ### Edge Engine Configuration Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/types.md Configure the Edge engine by importing 'Edge' from 'edge.js' and providing an instance of the Edge class. ```javascript const { Edge } = require('edge.js'); engine: { edge: new Edge() // Instance of Edge class } ``` -------------------------------- ### Configure for Development Source: https://github.com/fastify/point-of-view/blob/main/_autodocs/configuration.md Disable template caching and set a development context flag for easier debugging during development. ```javascript fastify.register(fastifyView, { engine: { ejs: require('ejs') }, production: false, // Disable caching defaultContext: { dev: true } }); ```