Type-safe, extensible, and fast. Build your site with Swift's compile-time safety, from metadata to markup.
Install the CLI, scaffold a project, and start a dev server with auto-reload. Your site is a Swift program, ready to build and serve.
brew install loopwerk/tap/sagamint install loopwerk/saga-cli$ saga init mysite
$ cd mysite
$ saga devEverything you need to build fast, type-safe static sites.
No YAML, no magic. Your site is a Swift program: explicit, readable, debuggable. Discoverable methods with auto-complete versus a hundred config options.
Strongly typed metadata in your Markdown and type-safe HTML templates. Everything is checked by the compiler, from your data to your markup.
Built-in support for multilingual sites. Fully localized URLs, automatic translation linking, and a locale-aware sitemap generator.
Not everything lives on disk. Load items from APIs, databases, or any async source and run them through the same rendering pipeline.
A full toolchain: saga init, saga dev, saga build. Incremental builds and live reload included.
Pluggable readers, processors, and writers. Swap Markdown parsers, add syntax highlighting, chain HTML transforms. Compose your build from modular steps.
Define your entire pipeline in Swift. From a simple blog...
struct ArticleMetadata: Metadata {
let tags: [String]
let summary: String
var public: Bool = true
}
try await Saga(input: "articles", output: "deploy")
.register(
metadata: ArticleMetadata.self,
readers: [.parsleyMarkdownReader],
writers: [
.itemWriter(swim(renderArticle)),
.listWriter(swim(renderArticles), paginate: 20),
.tagWriter(swim(renderTag), tags: \.metadata.tags),
.listWriter(atomFeed(
title: "My Blog",
baseURL: URL(string: "https://www.example.com")
), output: "feed.xml"),
]
)
.run()...to a complex documentation site with API references, syntax highlighting, and HTML minification.
let saga = try Saga(input: "content", output: "deploy")
try await saga
// Guide documentation (from DocC Markdown files)
.register(
folder: "docs",
metadata: DocMetadata.self,
readers: [.parsleyMarkdownReader],
itemProcessor: sequence(
processDocItem,
syntaxHighlight,
swiftSoupProcessor(processExternalLinks, renderToc)
),
sorting: docSorting,
writers: [.itemWriter(swim(renderDocPage))]
)
// API Reference (from symbol graph)
.register(
metadata: APIMetadata.self,
fetch: { try loadSymbolGraph(rootPath: saga.rootPath) },
writers: [
.itemWriter(swim(renderAPIPage)),
.listWriter(swim(renderAPIIndex), output: "api/index.html"),
]
)
// Landing page
.createPage("index.html", using: swim(renderHomePage))
// Minify all HTML output (prod only)
.postProcess { html, _ in
guard !Saga.isDev else { return html }
return Bonsai.minifyHTML(html)
}
// Run everything!
.run()From a simple blog to a complex multi-content site, Saga scales with you.
A single site can include blog articles with tags, a project portfolio with App Store links, movie reviews with ratings. Each with their own strongly typed metadata, indexed, paginated, or grouped independently.
Not all content lives on disk. Fetch items from APIs, databases, or any async data source and feed them through the same writer pipeline. Generate pages from code: landing pages, sitemaps, search indexes, 404 pages. No content file on disk needed.
Chain processing steps hierarchically to render complex content. Photos in albums in folders? No problem, use Saga to build your photo gallery.
Generate tag pages, Atom feeds, and XML sitemaps with dedicated writers. Help your visitors and search engines discover your content.
Build multilingual sites with fully localized URLs, automatic translation linking, and locale-aware sitemaps.
Add CSS classes, IDs, and custom attributes directly in your Markdown. Style content without leaving your prose.
Pre- and post-build hooks, custom processing steps, HTML transforms: generate images, build a search index, or minify output. If Swift can do it, your build can too.
Compose your site with readers, renderers, and plugins that fit your needs.
Use these packages directly in your build pipeline for syntax highlighting, HTML transforms, and more.