bongo replaces <bongo:*> elements in the HTML of each page, after the layouts render. They work in layouts, partials, and content. Write one as <bongo:style src="app.css" /> or as <bongo:style src="app.css"></bongo:style>. For an introduction, see the Templates guide.
- Each
srcis a path relative toassets/.<bongo:image>also takes paths incontent/. - A
srcthat does not exist fails the build. The error shows the element, and the content file and layouts that rendered it. - The built files get content-hashed names, such as
/app.3f9a1c2e.css. On a site under/blog/, the URLs start with/blog/. - bongo does not replace them in output files or in the templates of dynamic images.
Attribute values
bongo reads attribute values as data, and never runs them as code:
- A quoted value,
"…"or'…', is a string. - A bare value is a number,
true,false,null, or else text, sosrc=img/a.pngis a string. - A name with no value is
true.
<bongo:style>
Builds a stylesheet with LightningCSS. See CSS.
<bongo:style src="app.css" />becomes:
<link rel="stylesheet" href="/app.3f9a1c2e.css"/>src— the stylesheet. Required.inline— write the built CSS in a<style>element, in place of the<link>.global— turn off CSS modules for a*.module.cssfile.
All other attributes, such as media, nonce, and title, go on the <link> or the <style>:
<bongo:style src="print.css" media="print" nonce="__CSP_NONCE__" />becomes:
<link rel="stylesheet" href="/print.3f9a1c2e.css" media="print" nonce="__CSP_NONCE__"/>A built page is the same for each request, but a CSP nonce must change for each response. Thus give a placeholder, such as __CSP_NONCE__, and let your host put a new nonce in its place for each response.
<bongo:script>
Bundles a script with Rolldown.
<bongo:script src="main.ts" />becomes:
<script type="module" src="/main.DFHWkANP.js"></script>src— the entry file. Required.inline— write the built JavaScript in the<script>element. bongo builds an inline script alone, with no shared chunks, so it imports nothing.format—esm,iife, orcjs. See Formats.async— addasync.defer— adddeferto aniifeorcjsscript. A module script is deferred already.target— a browserslist query for this script. It replaces$build.target.
All other attributes, such as nonce and id, go on the <script>. format sets its type.
Formats
format |
Element | Runs |
|---|---|---|
esm, the default |
<script type="module"> |
after the page is parsed |
iife |
<script>, with the code in a function |
at once, and blocks parsing |
cjs |
<script>, with CommonJS code |
at once, and blocks parsing |
A module script can share chunks with the other module scripts of the site. bongo builds each iife and cjs script alone, with its dynamic imports inlined, since a classic script cannot load chunks. A browser has no require or exports, so prefer iife to cjs. Any other format fails the build.
Use an inline iife script for code that must run before the page paints, such as code that sets a color theme:
<head>
<bongo:script src="theme.ts" format="iife" inline />
</head><bongo:asset>
Publishes any file of assets/, such as a font, an image, or an icon. A file that <bongo:asset> and a CSS url() both use gets one copy and one URL.
Without preload, the element becomes the URL of the file, and nothing else. Thus it works inside an attribute. Give it single quotes, or no quotes, so that its attributes do not end the outer attribute:
<link rel="icon" href="<bongo:asset src='img/favicon.png' />"/>becomes:
<link rel="icon" href="/favicon.5ba42deb.png"/>With preload, it becomes a <link rel="preload">. Preload a font that your CSS loads:
<bongo:asset preload src="fonts/inter.woff2" />becomes:
<link rel="preload" href="/inter.22f9b928.woff2" as="font" type="font/woff2" crossorigin/>bongo finds as, type, and crossorigin from the file extension:
| Files | as |
type |
crossorigin |
|---|---|---|---|
.woff2, .woff, .ttf, .otf |
font |
font/woff2, … |
yes, as preload requires for fonts |
images, such as .png, .jpg, .svg, .webp, .avif |
image |
image/png, … |
no |
.css |
style |
text/css |
no |
.js, .mjs |
script |
text/javascript |
no |
anything else, such as .json or .wasm |
fetch |
when known | yes |
src— the file. Required.preload— write a<link rel="preload">, in place of the URL.as,type— replace the value from the extension.type=falseleavestypeout.crossoriginorcrossorigin="use-credentials"— replace the value from the extension.crossorigin=falseleaves it out.media,fetchpriority— copied onto the<link>.
The URL is percent-encoded, so it is safe in any attribute.
<bongo:client>
Bundles the client runtime, and starts it. It has no src. Its attributes become the client options:
<bongo:client transitions prefetch="hover" />becomes:
<script type="module">import { client } from "/client.Cl9e57TG.js"; client({ transitions: true, prefetch: "hover" });</script>It writes only that script, so you can put it anywhere in <head> or <body>. More than one <bongo:client> on a page share one bundled runtime. A nonce goes on the <script>, not into the options.
<bongo:image>
Resizes and converts an image with Bun.Image, and writes a <picture> with a srcset for each format. Under Deno and Node, bongo copies the image as it is. See Images.
<bongo:image src="img/hero.jpg" alt="A hero" sizes="(min-width: 800px) 720px, 100vw" />The src is relative to assets/. A path that starts with ./, ../, or / resolves against the URL of the page, and bongo reads the file from content/. See Source paths.
src— the image. Required.sizes— defaults to$images.sizes.widths="640,1280",formats="webp,jpeg",quality="60"— replace the$imagesvalues for this image.width,height— default to the size of the source. If you give only one, bongo calculates the other from the aspect ratio.loading— defaults tolazy, or toeagerwhenfetchpriority="high".decoding— defaults toasync.
All other attributes, such as alt, class, and fetchpriority, go on the <img>.
<bongo:alternate>
Writes a <link rel="alternate">, which names another version of the page. For type="text/markdown", bongo also writes a Markdown copy of the page. See Alternates and Markdown copies.
<bongo:alternate type="text/markdown" />becomes, on the page /config/:
<link rel="alternate" type="text/markdown" href="/config.md"/>type— the media type of the other version. Required.href— its URL. Fortext/markdown, it defaults to the route of the page plus.md, as$utils.url.ext()gives it. Other types need it. A relativehrefresolves against the URL of the page, as a browser resolves it.
All other attributes, such as title and hreflang, go on the <link>. Other types are a plain link, such as a feed or a translation:
<bongo:alternate type="application/rss+xml" href="/feed.xml" title="Blog" />
<bongo:alternate type="text/html" hreflang="fr" href="/fr/config/" />Markdown copies
When the type is text/markdown, and the href is a file of the site, bongo writes a copy of the page there: the title and the summary of its frontmatter, then the Markdown of the page as you wrote it.
- A page from an
.htmlor.hbsfile has no Markdown to copy. It gets no copy and no<link>, so one layout can serve every page. - bongo reads the source again when it writes the copy, so the build does not keep it in memory.
bongo devmakes a copy the first time that you open it. - The same
hreftwice on one page writes one copy. Two pages that name the same file, or a copy that lands on another file of the site, fail the build.
Output files and data modules see the alternates of each page in $pages. A page's own templates do not, because bongo finds the element after the layouts render.
Reserved names
With @bongo/markdown, a <bongo:name> element in Markdown calls the partial with that name. The names alternate, asset, client, image, script, and style belong to bongo. Markdown passes those elements through, for bongo to replace, so a partial with one of these names cannot be called from Markdown. Call it with {{#partial}} instead.