On this page
Project structure
The following is the typical file structure for a Root.js project. You can also explore one of our many examples on GitHub.
routes/
Routes are defined using .tsx files within the routes/ folder and will automatically render the default export as a TSX server-rendered component. Under the hood, the TSX is rendered using Preact's renderToString() function.
Below are a few examples of routes files and the final serving path:
Route | Matching URL(s) |
---|---|
@/routes/index.tsx |
/ |
@/routes/about.tsx |
/about |
@/routes/blog/index.tsx |
/blog |
@/routes/blog/[slug].tsx |
|
For more info, check out the Routes guide.
elements/
One of the key magical features that Root.js provides is the ability scan the rendered HTML page for custom elements and automatically inject inject any matching .ts/.tsx file found in the elements/ folder.
Example:
Create a file that defines your custom element:
// @/elements/custom-heading/custom-heading.ts
declare module 'preact' {
namespace JSX {
interface IntrinsicElements {
'custom-heading': CustomHeadingProps;
}
}
}
interface CustomHeadingProps {...}
class CustomHeading {...}
window.customElements.define('custom-heading', CustomHeading);
Use that custom element within your route:
// @/routes/index.tsx
export default function Page() {
return (
<custom-heading>Hello World!</custom-heading>
);
}
Within your rendered HTML you should see that the dependency is automatically added to the page:
<!-- rendered html -->
<!doctype html>
<html>
<head>
<script type="module" src="/elements/custom-heading/custom-heading.ts"></script>
</head>
<body>
<custom-heading>Hello World!</custom-heading>
</body>
</html>
translations/
Translations are stored as JSON files, where each locale is in its own file and stores a map of source string to translated string.
Example:
// @/translations/es.json
{
"Hello World!": "¡Hola Mundo!",
"Hello {name}!": "¡Hola {name}!"
}
Pages can use the useTranslations() hook which returns a function to translate strings for the current locale. The translations are provided via a Preact context at the root of the rendering tree.
// @/routes/index.tsx
import {useTranslations} from '@blinkk/root';
export default function Page() {
const t = useTranslations();
return (
<h1>{t('Hello {name}!', {name: 'Alice'})}</h1>
);
}
bundles/
The "bundles" directory is used for bundling client-side code outside of custom elements. This may be useful for loading 3rd-party libraries and other common global utilities that aren't necessarily encapsulated within a custom element.
Since files within "bundles" are compiled together with the files in the "elements" directory, the rendered output will smartly generate a module graph and intelligently chunk shared dependencies into separate files, minimizing the overall build output.
Example:
// @/routes/index.tsx
import {Script} from '@blinkk/root';
export default function Page() {
return (
<Script type="module" src="/bundles/main.ts" />
);
}
public/
Use the public/ directory to serve static files. Useful for things like robots.txt and site verification files.