Class

StepBuilder

class StepBuilder

A builder that collects pipeline steps.

Mentioned In

Instance Methods

@discardableResult
@preconcurrency
func createPage(
  _ output: Path,
  forEachLocale renderer: @escaping (PageRenderingContext) async throws -> String
) -> Self

Create a page per locale, driven purely by a template.

When i18n is configured, the renderer runs once per locale. The output path is automatically prefixed for non-default locales (e.g. "index.html""nl/index.html"). The rendering context’s allItems only contains items for the current locale, and locale is set.

try await Saga(input: "content", output: "deploy")
  .i18n(locales: ["en", "nl"], defaultLocale: "en")
  .register(...)
  .createPage("index.html", forEachLocale: swim(renderHome))
  .run()
@discardableResult
@preconcurrency
func createPage(
  _ output: Path,
  using renderer: @escaping (PageRenderingContext) async throws -> String
) -> Self

Create a page that is driven purely by a template.

Use this for pages such as a homepage showing the latest articles, a search page, or a 404 page. The renderer receives a PageRenderingContext with access to all items across all pipeline steps.

Pages created with createPage run after all registered writers have finished. This means generatedPages contains every page written by writers, plus pages from earlier createPage calls. Order matters: place the sitemap last if it needs to see all other pages.

try await Saga(input: "content", output: "deploy")
  .register(...)
  .createPage("index.html", using: swim(renderHome))
  .createPage("sitemap.xml", using: sitemap(baseURL: siteURL))
  .run()
@discardableResult
@preconcurrency
func register<M>(
  folder: Path? = nil,
  metadata: M.Type = EmptyMetadata.self,
  readers: [Reader] = [],
  itemProcessor: ((Item<M>) async -> Void)? = nil,
  filter: @escaping (Item<M>) -> Bool = { _ in true },
  claimExcludedItems: Bool = true,
  itemWriteMode: ItemWriteMode = .moveToSubfolder,
  sorting: ((Item<M>, Item<M>) -> Bool)? = nil,
  writers: [Writer<M>] = [],
  nested: ((StepBuilder) -> Void)? = nil
) -> Self where M : Metadata

Register a new pipeline step.

Parameters

folder

The folder (relative to input) to operate on. If nil, it operates on the input folder itself.

metadata

The metadata type used for the pipeline step. You can use EmptyMetadata if you don't need any custom metadata (which is the default value).

readers

The readers that will be used by this step.

itemProcessor

A function to modify the generated Item as you see fit.

filter

A filter to only include certain items from the input folder.

claimExcludedItems

When an item is excluded by the filter, should this step claim it? If true (the default), excluded items won't be available to subsequent pipeline steps.

itemWriteMode

The ItemWriteMode used by this step.

sorting

A comparison function used to sort items. Defaults to date descending (newest first).

writers

The writers that will be used by this step.

nested

An optional closure to register nested substeps that run within each subfolder.

Return Value

The instance itself, so you can chain further calls onto it.

@discardableResult
@preconcurrency
func register<M>(
  metadata: M.Type = EmptyMetadata.self,
  fetch: @escaping () async throws -> [Item<M>],
  cacheKey: String? = String(describing: M.self),
  itemProcessor: ((Item<M>) async -> Void)? = nil,
  sorting: @escaping (Item<M>, Item<M>) -> Bool = { $0.date > $1.date },
  writers: [Writer<M>]
) -> Self where M : Metadata

Register a pipeline step that fetches items programmatically instead of reading from files.

When SAGA_CACHE_DIR is set (which saga dev does automatically), fetched items are cached to disk so that subsequent rebuilds skip the fetch. Pass nil for cacheKey to disable caching (useful while developing the fetch function itself).

Parameters

metadata

The metadata type used for the pipeline step. You can use EmptyMetadata if you don't need any custom metadata (which is the default value).

fetch

An async function that returns an array of items.

cacheKey

The cache key for storing fetched items. Defaults to the metadata type name. Pass nil to disable caching.

itemProcessor

A function to modify each fetched Item as you see fit.

sorting

A comparison function used to sort items. Defaults to date descending (newest first).

writers

The writers that will be used by this step.

Return Value

The instance itself, so you can chain further calls onto it.

@discardableResult
@preconcurrency
func register(write: @escaping (Saga) async throws -> Void) -> Self

Register a custom write-only step.

Use this for logic outside the standard pipeline: generate images, build a search index, or run any custom logic as part of your build. The closure runs during the write phase, after all readers have finished and items are sorted.

try await Saga(input: "content", output: "deploy")
  .register(...)
  .register { saga in
    // custom write logic with access to saga.allItems
  }
  .run()

Relationships

Inherited By

Saga

Conforms To

Swift.Sendable