Guide

chimera builds static websites from Luwu code. You describe each page as a tree of objects like Paragraph, Menu and CodeBlock, and chimera renders that tree to HTML with a stylesheet, light and dark themes and a theme switcher. Parse the HTML later and you get the same objects back.

This whole site is built that way. Its source is the examples folder of the repository, and every example on these pages renders from the code shown under it.

Install

chimera runs on seal, a runtime for Luwu. You need a seal built with Luwu support: seal 0.9, from the luwu-classes branch. Clone chimera into your project:

git clone https://github.com/seal-runtime/chimera libraries/chimera

Then point an alias at it in your project's .luaurc, and require("@chimera") will find it:

{
    "aliases": {
        "chimera": "./libraries/chimera"
    }
}

Your first page

A Document is one HTML page. Add elements to it, render it with to_html, and write the result with seal's fs library:

const fs = require("@std/fs")
const chimera = require("@chimera")
const .{ Document, elements.{ Heading, Paragraph, Main, Link } } = chimera
const .{ h1 } = Heading

const page = Document("Hello")
    :add(Main {
        h1("Hello"),
        Paragraph({ "Built with ", Link("chimera", "https://github.com/seal-runtime/chimera"), "." }),
    })

fs.writefile("hello.html", page:to_html(true))

Run it with seal ./hello.luwu and the page's body looks like this:

Hello

Built with chimera.

const hello = Main {
    h1("Hello"),
    Paragraph({ "Built with ", Link("chimera", "https://github.com/seal-runtime/chimera"), "." }),
}

You didn't write any CSS, but the page is styled and follows the reader's light or dark mode. to_html(true) indents the HTML for reading. Leave out true for compact output.

Your first site

Once you have more than one page, use a Site. It renders every page with the same header, footer and themes, and the default header already has a menu of your pages and a theme switcher.

const .{ site.{ Site, Page } } = chimera

const home = Page("Home", { h1("Hello"), Paragraph("Welcome!") }, "index.html")
const notes = Page("Notes", { h1("Notes"), Paragraph("Things I learned.") })

Site("My site")
    :add_page(home, notes)
    :build("out")

That writes out/index.html and out/notes.html. Sites and pages covers nested pages, links between them and tables of contents.

What's where

chimera groups its classes by what they're for. Destructure the ones you need from require("@chimera"):

Module What's in it Guide
elements One class per HTML tag Elements
components Menus, tabs, cards, code blocks, layouts Components, Layout, Code
style Typed CSS, colors and theme tokens Styling
themes Light, Dark and the Catppuccin flavors Theming
site Sites, pages and the links between them Sites and pages
top level Traits for your own elements, Document, Parser, MarkdownReader Custom components, Parsing HTML, Markdown and JSON