[idea:site-config]setup2026-08-20

Site-wide configuration

You can configure your rookery by calling a show rule after you import it.

#import "@rookery/core:0.1.0": rookery
#show: rookery.with(
  // Names are now `note:etal` rather than `idea:etal`
  prefix: "note",
  // a window written inside a windowed idea unfurls one level
  window-unfurl: 1,
  // the accent every rookery link takes on hover
  theme: (link-color: rgb("#e68c00")),
)

We suggest that you wrap this configuration in a template function that fronts every page:

// template.typ
#import "@rookery/core:0.1.0": rookery
#let template(doc) = {
  show: rookery.with(
    theme: THEME,
    idea-page-template: idea-page,
    window-unfurl: 1,
    bibliography: BIBLIOGRAPHY,
  )
  doc
}

// ...
// at the start of each file
#import "template.typ": template
#show: template
[idea:config-reference]reference

Argument reference

ParameterDefaultWhat it sets
prefix"idea"The namespace an idea’s name lives in; non-empty, no : (the separator is added for you). See referencing ideas.
note-dirnoneThe directory the minted idea pages are written to. Left unset, it is ideas under the default prefix, and the prefix itself under any other — prefix: "maths" mints maths/, not mathss/. Names one directory: no / and no :.
css-prefixnoneThe stem every class this package emits is built from. Left unset, it follows prefix, so renaming the name namespace renames .idea-box to .note-box along with it; set it to hold the classes still while the names move. See HTML class reference.
window-unfurl1How many levels of transclusion are allowed before a window bottoms out as a link to the idea’s own page. 0 allows none. See controlling window unfurl.
theme(:)The ten keys the package will style for you — five colors, three lengths, a font stack, and tags-color. Every key but tags-color is also a parameter in its own right, and the granular form wins. See theming a rookery.
display(:)What every idea and window in the rookery shows of itself, as a dictionary of the same nine flags #idea takes. This is the bottom of the stack: an idea or a window that leaves a key at auto is asking for the value set here. date and tags resolve to false when nothing is said, the other seven to true. Each key is also a parameter in its own right — display-date: true — and the granular form wins. See #idea.
idea-page-templatenoneYour own chrome for the standalone page rookery mints per idea. See idea template.
bibliographynoneTypst’s own #bibliography arguments, for the single bibliography a rookery’s citations all draw from.
index-pagetrueWhether to mint ideas/index.html, a landing page listing every idea in the rookery. It goes in the same directory the idea pages do, so a rookery that moved them with note-dir or prefix gets maths/index.html rather than ideas/index.html. Set it to false where your site already publishes an index of its own.
refstrueWhether rookery installs the show ref: rule that renders @idea:etal as the idea rather than a figure number. Set it to false to keep Typst’s own behavior, or to install a rule of your own. See hyperlinks.
hyperlink-target-mintedtrueWhere every @idea:etal in the document lands: true on the idea’s standalone minted page, false in the context it was hatched in. The same parameter #hyperlink itself takes. Ignored when refs is false. See hyperlinks.
syndicatefalseWhether each minted page also carries a <feeds:item> beacon — the label @rheo/feeds’s items() reads by default — so a feed package can collect your ideas without either package importing the other. Off by default: a package should not write into another’s label namespace unasked. An idea with no date never gets one.
page-titles"title"What the context and backlinks footer on an idea’s page calls the pages it lists: "title" is Rheo’s own spine title, "path" the source path with the content directory and the extension dropped — jobs/cfps, institutions. Rheo derives a title from the file stem, so in a project with a page per directory every index.typ is titled ‘Index’, which is a poor answer to a footer asking where an idea was written; a path is longer and plainer, and unique by construction. A rookery-wide choice, since one idea’s footer disagreeing with another’s about what a page is called would be worse than either answer.
invisible-tags()Tags that leave no trace in the HTML: no pill in any hat, no .idea-tag-<tag> class on the heading, the card, an outline row or an index row, and no generated rule for a tags-color entry naming one. Filtering still sees them everywhere — #window(tagged: ..), #ideas, #idea-tag-names, a search query — which is what makes an invisible tag usable as a build-level key. The presentational complement to exclude-tags, which drops the idea itself.
[idea:theming]reference

Theming a rookery

You can theme rookery using a show rule:

#import "@rookery/core:0.1.0": rookery
#show: rookery.with(
  theme: (
    // the accent every rookery link takes on hover
    link-color: rgb("#e68c00"),
    // the quieter hover a window gets
    fold-color: "rgba(230, 140, 0, .05)",
    // the left rule, where it should not follow `link-color`
    border-color: rgb("#3d3d3d"),
  ),
)

Every key but tags-color can also be passed as a parameter directly to the rookery function, which will take precedence over the theme dictionary:

#show: rookery.with(
  theme: MY-THEME,
  link-color: rgb("#ffd166"),
)

tags-color has no such parameter: it is a dictionary of its own, keyed by tag, and lives only inside theme.

The five colors each take a Typst color or a raw CSS string. Rookery allows a string so that you can specify rgba(...), color-mix(...), var(--your-own) and anything else CSS accepts. The three lengths — rule-width, pad and label-size — take a Typst length or a CSS length string, the string being how you reach the units Typst has no literal for: px for a hairline, and the rem label-size wants. label-font is a CSS font stack rather than either, passed through unvalidated, and an array of family names is joined for you: ("Berkeley Mono", "monospace") and "Berkeley Mono, monospace" are the same thing.

    [idea:theme-reference]reference

    Theme reference

    KeyDefaultWhat it sets
    link-colorrgba(128, 0, 255, .12)The hover background on any rookery link, and the fallback border-color takes when you leave it unset.
    fold-colorrgba(0, 100, 255, .05)The hover background on a window block, unless that window sets display-background: false.
    name-colorgrayThe [idea:etal] name’s own text.
    date-colorgrayAn idea’s or a window’s date, where it is shown.
    border-colorlink-colorThe left rule that an idea, a window and an outline all carry.
    rule-width2pxHow thick that rule is. The card’s corner is arithmetic against it, so the tab the name straddles stays shut when you move it.
    pad0.5emThe padding every rookery block measures from—an idea’s box, a window’s, and the indent a nested one takes.
    label-fontmonospaceThe face the [idea:etal] name is set in, and the outline’s ‘Contents’ title with it. Both are machinery rather than writing, so both leave the prose face behind.
    label-size0.57remThe size of that name. Load-bearing beyond the label: the tab’s lift, a window’s summary and the footer’s padding are all measured against it, so the corner closes at whatever size you choose. rem rather than em, so it does not shrink again inside a window.
    tags-color(:)One color, or a (text:, background:) pair, per tag—delivered as a rule on .idea-tag-<tag> so it reaches the pill, the outline row’s marker and a search result’s chip alike.
      [idea:class-reference]reference

      HTML class reference

      You can also style more granularly with your own CSS using the classes below. A trailing * below stands for a family whose members are named in the description.

      ClassWhat it is
      .idea-boxAn idea’s own block where it was written, carrying the left rule and the padding every rookery block nested inside it measures from.
      .idea-head, .idea-tabThe heading group, and the short top rule the name straddles at the card’s corner.
      .idea, .idea-titleThe idea’s heading element—which carries the anchor an @idea:etal fragment resolves to—and the title text inside it.
      .idea-label, .idea-dateThe [idea:etal] permalink and the date beside it, in a heading, a window summary or prose, wherever either is shown.
      .idea-tag, .idea-tag-<tag>A tag pill in the hat, and one extra class per tag the idea carries. The second reaches every surface that names the tag—the idea’s heading, its box, its outline row, its pill, and a search result’s chip, which JavaScript builds in the browser—so a single rule of your own styles a tag everywhere it shows up.
      .idea-refAn @idea:other reference in prose. See referencing ideas.
      .idea-windowA transclusion, wearing the same rule and indent as .idea-box; the second class .idea-window-plain opts a bare #idea-body out of that box.
      .idea-window-*The fold: -details the <details>, -summary the row you click, -title the name in that row, -body what folds away under it. The date beside the title is .idea-date, the same class it wears in a heading.
      .idea-window-more*The second fold a limit: makes inside the body: .idea-window-more its <details>, -more-summary the shown blocks you click to see the rest, and .idea-window-ellipsis the … at the end of them.
      .idea-outline*A page’s outline: .idea-outline the list at each level of nesting, -title its “Contents” label, -row one row per idea.
      .idea-footnote*An idea’s own footnotes, carried on every surface it appears on: .idea-footnotes the block, -title its label, .idea-footnote-list and .idea-footnote its entries.
      .idea-fn-*-ref the superscript mark in prose, -backlink the way back up to it from the entry.
      .idea-references, .idea-page-refsThe bibliography an idea’s citations draw from, and the page’s own for citations written outside any idea.
      .idea-footer*On an idea page: .idea-footer the ruled-off apparatus under the note, -title the label on each of its sections.
      .idea-context, .idea-backlinksThat footer’s two sections: where the note was written, and the notes pointing at it.
      .idea-page-list, .idea-page-rowA list of pages in either section, and one row in it—a page cannot fold, so it wears a window’s shape without being one.
      .idea-row*One row of an #idea-row list: .idea-row the <li>, -when its date cell, -title the title, -cell each extra cell, -badges the chip strip at the end. @rookery/search and @rookery/timeline draw the same row, so a rule of yours here reaches all three.
      .idea-index-countThe “n ideas” line on the minted index page.
      .idea-dup-warningThe build-time notice shown when two ideas claim the same name.

      Every one of those elements also carries a data-rookery attribute naming the same thing without the prefix—.idea-box is [data-rookery="box"], .idea-window-summary is [data-rookery="window-summary"]—and it is the attribute, not the class, that rookery’s own stylesheet selects on. The two say the same thing, so write whichever reads better in your CSS; the attribute is there because css-prefix moves the classes and nothing should have to follow them to find an element. .idea-window-plain is the one that does not repeat itself: a plain window is [data-rookery="window"] wearing data-rookery-plain besides.

      Anything that names a tag—a card, a window, a pill, an outline row, an index row, a badge—carries one more, data-rookery-tags, listing those tag names, minus any made invisible by invisible-tags.

        [idea:css-reference]reference

        CSS variable reference

        You can override any value from the theme reference as a CSS variable, as well as other aspects of a rookery’s appearance.

        PropertyDefaultWhat it sets
        --idea-tag-size--idea-label-sizeA tag pill’s font size. Follows the name’s size unless you separate them.
        --idea-tag-radius999pxA pill’s corner radius.
        --idea-tag-color, --idea-tag-bg--idea-name-color, rgba(128, 128, 128, .18)An untagged-by-tags-color pill’s text and background. Setting tags-color writes these per tag for you.
        --idea-tag-line--idea-border-colorThe tick an outline row draws off the outline’s rule, where the row’s idea carries a tag.
        --idea-external-color--idea-name-colorThe underline an outbound link takes on hover, in a references block or an idea page’s footer—so a link that leaves your rookery reads differently from one that stays in it.
        --idea-heading-margin-top0.75emThe space above an idea’s heading. Set this in your own stylesheet to return the heading to your site’s own vertical scale.
        --idea-row-pad-block0.45remAn #idea-row row’s vertical padding. Published on purpose, and it inherits, so a cell that paints a background can stretch past it rather than reading as a chip sitting in the row.
        --idea-row-gutter7.5emThe width of a row grid’s first column.
        --idea-muted-colorgrayThe color of a de-emphasized row cell, and of a row date marked soft:.
        --idea-row-rule-colorunsetThe color of a row’s vertical rule. Read and never set by this package’s own stylesheet, precisely so a layered stylesheet can point it somewhere—a sibling package can run an urgency band down that bar.
        [idea:idea-template]reference

        Idea page template

        Every idea in your rookery gets its own standalone page. By default, this page shows the idea’s title and name, its body, and the context and backlinks footer.

        You can customize the idea page’s chrome when you first instantiate rookery, like so:

        #let idea-page-template(id: none, note: (:), doc) = {
          show: chrome.with(current-page: id)
          doc
        }
        
        #show: rookery.with(
          idea-page-template: idea-page-template,
        )