Skip to main content
Version: Canary 🚧

Installation

Setting up the Engine

Loom is distributed as a standard Typst package. However, because Loom is a meta-engine that manages its own context and state, you shouldn't just import it directly into every file.

Instead, we use the Wrapper Pattern to create a dedicated instance for your project.

1. Import the Package​

Loom is available on Typst Universe. You can import it using the standard package syntax.

#import "@preview/loom:0.1.0": construct-loom

(Note: Check the Typst Universe for the latest version number.)

To keep your code clean and prevent namespace collisions, you should initialize Loom once in a central library file and export the tools you need.

Create a file named loom-wrapper.typ (or lw.typ) in your project root.

loom-wrapper.typ
#import "@preview/loom:0.1.0"
#import loom: query, guards, mutator, matcher, collection

// 1. Construct a unique instance for your project.
// The key (<my-project>) isolates your components from other libraries.
#let (weave, motif, prebuild-motif) = loom.construct-loom(<my-project>)

// 2. Export the specific tools you want to use.
// This keeps your API clean for the rest of your document.

// The Engine
#let weave = weave

// The Component Constructors
#let managed-motif = motif.managed
#let compute-motif = motif.compute
#let content-motif = motif.content
#let data-motif = motif.data
#let motif = motif.plain

// Prebuild Motifs
#let apply = prebuild-motif.apply
#let debug = prebuild-motif.debug

Why do this?

  • Isolation: By passing <my-project>, you ensure that your components don't accidentally receive signals from a different library that also uses Loom.
  • Convenience: You can type #motif(..) instead of #(loom.motif.plain)(..).
  • Control: You decide exactly which modules (query, mutator) are exposed to your users.

3. Usage in Your Document​

Now, in your main document (main.typ), you simply import your wrapper.

main.typ
#import "loom-wrapper.typ": *

// Now you can use the tools directly
#let my-component = content-motif(
draw: (ctx, body) => block(stroke: 1pt, body)
)

// Start the engine
#show: weave.with(debug: false)

#my-component[
Hello, Loom!
]

Quick Start Template​

If you want to copy-paste a complete setup, here is the minimal boilerplate:

loom-wrapper.typ
#import "@preview/loom:0.1.0"
#let (weave, motif, ..) = loom.construct-loom(<app>)

#let content-motif = motif.content
main.typ
#import "loom-wrapper.typ": *
#show: weave.with()

#content-motif(draw: (ctx, body) => [
= Reactive Document
#body
])[
It works!
]