Class
StepBuilder
class StepBuilderA builder that collects pipeline steps.
Mentioned In
Instance Methods
@discardableResult
@preconcurrency
func createPage(
_ output: Path,
forEachLocale renderer: @escaping (PageRenderingContext) async throws -> String
) -> SelfCreate 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
) -> SelfCreate 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 : MetadataRegister a new pipeline step.
Parameters
folderThe folder (relative to
input) to operate on. Ifnil, it operates on theinputfolder itself.metadataThe metadata type used for the pipeline step. You can use
EmptyMetadataif you don't need any custom metadata (which is the default value).readersThe readers that will be used by this step.
itemProcessorA function to modify the generated
Itemas you see fit.filterA filter to only include certain items from the input folder.
claimExcludedItemsWhen 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.itemWriteModeThe
ItemWriteModeused by this step.sortingA comparison function used to sort items. Defaults to date descending (newest first).
writersThe writers that will be used by this step.
nestedAn 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 : MetadataRegister 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
metadataThe metadata type used for the pipeline step. You can use
EmptyMetadataif you don't need any custom metadata (which is the default value).fetchAn async function that returns an array of items.
cacheKeyThe cache key for storing fetched items. Defaults to the metadata type name. Pass
nilto disable caching.itemProcessorA function to modify each fetched
Itemas you see fit.sortingA comparison function used to sort items. Defaults to date descending (newest first).
writersThe 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) -> SelfRegister 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
Conforms To
Swift.Sendable