Saga 3 See what's new logo

Set sail with Saga,
a static site generator in Swift

Type-safe, extensible, and fast. Build your site with Swift's compile-time safety, from metadata to markup.

Up and running in seconds

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.

Homebrew brew install loopwerk/tap/saga
Mint mint install loopwerk/saga-cli
$ saga init mysite
$ cd mysite
$ saga dev

Built for developers who love Swift

Everything you need to build fast, type-safe static sites.

Code over Configuration

No YAML, no magic. Your site is a Swift program: explicit, readable, debuggable. Discoverable methods with auto-complete versus a hundred config options.

Type-Safe From Top To Bottom

Strongly typed metadata in your Markdown and type-safe HTML templates. Everything is checked by the compiler, from your data to your markup.

Internationalization

Built-in support for multilingual sites. Fully localized URLs, automatic translation linking, and a locale-aware sitemap generator.

Programmatic Content

Not everything lives on disk. Load items from APIs, databases, or any async source and run them through the same rendering pipeline.

CLI & Dev Server

A full toolchain: saga init, saga dev, saga build. Incremental builds and live reload included.

Extensible Pipeline

Pluggable readers, processors, and writers. Swap Markdown parsers, add syntax highlighting, chain HTML transforms. Compose your build from modular steps.

Everything is Swift, everything is typed

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()

Grows with your site

From a simple blog to a complex multi-content site, Saga scales with you.

Typed metadata

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.

Programmatic content

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.

Nested processing

Chain processing steps hierarchically to render complex content. Photos in albums in folders? No problem, use Saga to build your photo gallery.

Tags, feeds, and sitemaps

Generate tag pages, Atom feeds, and XML sitemaps with dedicated writers. Help your visitors and search engines discover your content.

Internationalization

Build multilingual sites with fully localized URLs, automatic translation linking, and locale-aware sitemaps.

Markdown attributes

Add CSS classes, IDs, and custom attributes directly in your Markdown. Style content without leaving your prose.

Your build, your rules

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.

Modular by design

Compose your site with readers, renderers, and plugins that fit your needs.

Markdown readers

Renderers

Utilities

Tap into an ecosystem of Swift packages

Use these packages directly in your build pipeline for syntax highlighting, HTML transforms, and more.