Getting things prepared:
- Install Deno. Either the curl shell or brew.
- Serve the website locally:
deno task serve - Build the static website:
deno task build
Deno doesn't have a specific step for installing dependencies, instead the first run will download and cache what is needed.
The site uses Pagefind for search functionality. Pagefind
is integrated into Lume via _config.ts and runs automatically after each build.
Available tasks:
| Task | Command | Description |
|---|---|---|
serve |
deno task serve |
Build with Pagefind + start dev server |
build |
deno task build |
Build the static site with Pagefind |
Just run deno task serve and search will work automatically.
_components- Components are a primary concept in Lume, can be written in many different
syntaxes, and referenced from other syntaxes.
In this repo, we have components written injsxand these can be referenced from any content or layout file.
Generally, anything written in here will be used as a snippet inside our content files. Otherwise put it in_includes
- Components are a primary concept in Lume, can be written in many different
syntaxes, and referenced from other syntaxes.
_data- A data directory, very similar to Jekyll or Eleventy. Files in this
directory are available on the global scope (not a
datascope). i.e. it issite.navigationnotsite.data.navigation.
- A data directory, very similar to Jekyll or Eleventy. Files in this
directory are available on the global scope (not a
_includes- An includes directory. Various tsx templates live in here for building
the site layouts.
Thescriptsdirectory here contains files that are bundled into the site javascript using esbuild.
Thestylesdirectory here contains files that are bundled into the site css using sass.
- An includes directory. Various tsx templates live in here for building
the site layouts.
articles,changelogs,guides- Our main collections, output at
/documentation/[collection]/[slug]/.
Written as MDX to enable nicer snippets, otherwise standard markdown.
- Our main collections, output at
assets- Files that are part of the site/layouts. SCSS and JS files here will be
processed through the appropriate bundler. Other files will not be passed
through.
Most SVGs in here will likely be inlined into the site. More on that below.
- Files that are part of the site/layouts. SCSS and JS files here will be
processed through the appropriate bundler. Other files will not be passed
through.
uploads- Our directory for CMS-uploaded files.
ye_olde_images- All images migrated from the old docs codebase, flattened to images that are actually referenced in the content.
Lume is configured in the _config.ts file. This is where we import and define
all of our plugins
Components are available under the comp namespace wherever you are.
In a njk file:
In an mdx file:
<comp.Notice info_type="info">
Alternatively, drag and drop files into the File Browser.
</comp.Notice>In a jsx file:
export default function ({ comp }) {
return (
<comp.Notice info_type="info">
Alternatively, drag and drop files into the File Browser.
</comp.Notice>
);
}A good sample is _components/DocsImage.jsx:
Usage: <comp.DocsImage path="/img.png" alt="Alt text" type="screenshot" />export default function ({ comp, type, path, alt }, helpers) {
let imageClass = "c-docs-image";
if (type === "screenshot") {
imageClass += " c-docs-image--type-screenshot";
}
return (
<div className="c-docs-image__wrapper">
<div className={imageClass}>
<img
className="c-docs-image__image"
src={helpers.url(path)}
alt={alt}
loading="lazy"
/>
</div>
</div>
);
}The first argument is an object that contains the comp namespace, as well as
any props that were passed to the component. If it is a component that wraps
markdown, that content will be available as children in this object.
The second argument contains any helpers on the site — e.g. the filters that
would be available for a njk template. Where the layout might do
{{ title | md }}, your JSX component can do { helpers.md(title) }
Lume allows us to write rich postprocessing using a DOM as part of the SSG, for example to add hash links to all of our headings we can write:
site.process([".html"], (page) => {
page.document.querySelectorAll('h1').forEach((el) => {
el.addAttribute("id", slugify(el.innerText));
}
});The inline attribute can be added to an img tag, and the build process will
convert that to an inline image rather than a URL. If the path leads to an SVG,
the img tag will be turned into an svg one.
This lets us keep our SVG icons in a sane location within assets, but inline
them as needed without the indirection of an include. e.g.:
<img src="/assets/img/arrow.svg" class="my-class-name" inline>becomes:
<svg
class="my-class-name"
width="8"
height="12"
viewBox="0 0 8 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.589844 1.41L5.16984 6L0.589844 10.59L1.99984 12L7.99984 6L1.99984 0L0.589844 1.41Z"
fill="#393939"
/>
</svg>The esbuild flow on this website utilizes Deno rather than Node for module
resolution, so Deno packages should be imported by URL. Node packages can be
imported by their npm name & version, prefixed with npm:. See
_includes/scripts/alpine.js:
import Alpine from "npm:alpinejs@latest";
import intersect from "npm:@alpinejs/intersect@latest";These don't need to be added to a package.json anywhere, Lume/Deno will fetch
them on first run. (This repo should never have a package.json in it).