Html
HTML routes are simply routes defined with the .tsx extension, where they use the @kitajs/fastify-html-plugin plugin to render the content.
WARNING
This documentation covers the @kitajs/html 4.0.0-beta version. It’s recommended to wait for the stable release before using it in production.
export function get() {
return `
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
`;
}Read more about what the plugin does in the official documentation and how to use it in your application.
The above route simply returns an HTML string with the Content-Type header of text/html; charset=utf-8.
JSX
The development experience can be even better with the use of JSX via @kitajs/html
Installing
To use the @kitajs/html package, follow these steps:
Install the required npm packages,
@kitajs/htmland@kitajs/ts-html-plugin, to enable editor intellisense. Open your terminal and run:shnpm i @kitajs/html @kitajs/ts-html-plugin1Configure your TypeScript project to transpile TSX/JSX into JavaScript and using our LSP Plugin. Update your
tsconfig.jsonfile with the following settings:jsonc// tsconfig.json { "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@kitajs/html", "plugins": [{ "name": "@kitajs/ts-html-plugin" }] } }1
2
3
4
5
6
7
8
9Append the
xss-scancommand into your test script. This CLI comes from @kitajs/ts-html-plugin, which catches XSS vulnerabilities that may be introduced into your codebase, automating the xss scanning process to run everytime you test your code, like inside your CI/CD environment. Open yourpackage.jsonfile and add the following script:jsonc// package.json { "scripts": { "test": "xss-scan" } }1
2
3
4
5
6
7Ensure that your code editor is using the TypeScript version from your project’s
node_modulesinstead of the globally installed TypeScript. For Visual Studio Code, you can configure this in your workspace settings:jsonc// .vscode/settings.json { "typescript.tsdk": "node_modules/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true }1
2
3
4
5
6
Using JSX in Routes
To use JSX in your routes, you need to create a .tsx file and export a function that returns JSX. Here’s an example:
export function get() {
return (
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
);
}Streaming HTML
Another feature of the @kitajs/html package is the ability to stream HTML content in the first render. This is useful for rendering the base template layout while fetching data from the database or other services.
Suspense works by default with the @kitajs/html package.
import { Suspense } from '@kitajs/html/suspense';
import type { FastifyRequest } from 'fastify';
export function get({ id }: FastifyRequest) {
return (
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<Suspense rid={id} fallback={<div>Loading...</div>}>
<MyAsyncComponent />
</Suspense>
</body>
</html>
);
}The above example will render the initial template instantly and when the MyAsyncComponent, a async component function, resolves, it will replace the Suspense fallback component with the resolved content.
Read more about Suspense and Async Components in their respective documentation.
Interacting with the server
Kita/HTML is a simple JSX -> HTML package, no reactivity or state management is included.
It follows the widely used MVC concept. But other strategies can also be used, like with Htmx, Alpine.js or Hotwire Turbo
Take a look at this example using Htmx:
export function get() {
return (
<html>
<head>
<title>Hello World</title>
<script src="https://unpkg.com/htmx.org/dist/htmx.js"></script>
</head>
<body>
<button hx-post="/" hx-swap="outerHTML">
Click Me
</button>
</body>
</html>
);
}
export function post() {
return (
<div>
<h2>Data Fetched</h2>
</div>
);
}The hx-post attribute sends a POST request to the server, and the hx-swap attribute replaces the content of the element with the response from the server.
The above will swap the <button> element with the <div> element when the button is clicked.
Learn more about Htmx, it’s awesome!