Website
Site Overview
What Blueprint's docs site is, which tools it uses, and how to run it locally.
Documentation site for Blueprint, built with Saga, a Swift static site generator.
Markdown lives in Documentation/Content/en/. A Swift executable in Website/ renders HTML with Swim templates, compiles Tailwind CSS during the build through SwiftTailwind, highlights code with Moon, and deploys static files to Vercel via GitHub Actions.
No Node.js app. No runtime server. Build on macOS, ship HTML.
Technologies
If you only know the iOS app, this stack is new. Short intro to each piece:
| Tool | What it is | Role in Blueprint |
|---|---|---|
| Saga | Static site generator written in Swift | Reads Markdown folders, runs hooks, writes Website/deploy/ |
| Parsley | Saga Markdown reader plugin | Turns .md frontmatter + body into HTML |
| Swim | Type-safe HTML in Swift | templates.swift builds page shells (sidebar, footer, layout) |
| Moon | Syntax highlighter | Colors fenced code blocks in articles |
| SwiftTailwind | Tailwind CLI wrapper for Swift | Compiles CSS at build time (no npm) |
| Mermaid (CDN) | Diagram renderer | Architecture pages use ```mermaid blocks |
Saga is not Markdown-only. You can generate pages from Swift with no content file. Blueprint uses Markdown because architecture notes fit that format. For a polished personal site with the same stack, see rychillie.pages.dev (source).
Requirements
- Swift 6.0+
- macOS 14+ (Saga build runs on Mac; CI uses
macos-latest) - Saga CLI for local dev
Install Saga with Homebrew:
brew install loopwerk/tap/saga
CI does not use Homebrew. It runs swift build and the compiled Website binary instead.
Development
From the repo root:
./scripts/saga dev --port 3000
Open http://localhost:3000. Saga watches Documentation/ and Website/Sources/ and rebuilds on change.
The wrapper script cds into Website/ before calling Saga. Running saga from the repo root without the script fails because Package.swift lives inside Website/.
Build
./scripts/saga build
Saga reads from Documentation/Content/en/ and writes to Website/deploy/.
| Path | Committed? |
|---|---|
Documentation/Content/en/**/*.md |
Yes (source of truth) |
Documentation/Content/en/static/input.css |
Yes (Tailwind entry) |
Documentation/Content/en/static/output.css |
Generated locally; copied to deploy |
Website/deploy/ |
No (gitignored) |
Do not commit Website/deploy/. Production HTML comes from CI, not from git.
Styling
Tailwind CSS is compiled during the Saga build through SwiftTailwind.
| File | Role |
|---|---|
Documentation/Content/en/static/input.css |
Tailwind v4 entry (@import "tailwindcss", typography plugin) |
Documentation/Content/en/static/output.css |
Generated minified CSS |
Website/Sources/Website/Theme.swift |
Tailwind utility strings used by templates |
templates.swift |
Links CSS with Saga.hashed("/static/output.css") for cache busting |
When changing visuals, edit Theme.swift or input.css. Do not hand-edit output.css.
Details: Implementation.
Content
English content only today (Documentation/Content/en/). Portuguese placeholder: Documentation/Content/pt-BR/.
| Folder | URL | Purpose |
|---|---|---|
index.md |
/ |
Home, setup, roadmap |
architecture/ |
/architecture/ |
iOS architecture notes |
website/ |
/website/ |
This section (meta-docs) |
Article frontmatter:
---
title: MVVM
summary: Optional short line for index tiles and page lead.
order: 1
---
order sorts list pages and sidebar entries. SiteCatalog.swift must list every page you want in the sidebar.
Site generation
The Saga pipeline lives in Website/Sources/Website/main.swift:
beforeRead: compile Tailwind when Swift sources or CSS change- Read: Parsley parses Markdown per registered folder
- Write: Swim renderers emit HTML to
deploy/ afterWrite: copyoutput.csstodeploy/static/, writevercel.json
Registrations today:
| Folder | Output |
|---|---|
architecture/ |
/architecture/* + index |
website/ |
/website/* + index |
root index.md |
/ (home) |
Templates use Moon for code blocks and MermaidProcessor for diagrams. See Implementation.
Project layout
Website/
├── Package.swift Saga, Swim, Moon, SwiftTailwind deps
├── Sources/Website/
│ ├── main.swift Pipeline, hooks, folder registration
│ ├── templates.swift docsShell, section renderers
│ ├── Theme.swift Tailwind class constants
│ ├── SiteCatalog.swift Sidebar navigation catalog
│ └── MermaidProcessor.swift Diagram post-processing
├── deploy/ Generated output (gitignored)
└── vercel.json Hosting config reference
Documentation/Content/en/
├── index.md
├── architecture/
├── website/
└── static/ input.css, output.css (generated)
scripts/saga Repo-root wrapper for saga dev/build
.github/workflows/website.yml macOS build + Vercel deploy
CI and deployment
Pull request and push CI runs from .github/workflows/website.yml when Website/, Documentation/, or the workflow file change.
The workflow:
- Runs on
macos-latest - Restores SwiftPM /
.buildcache - Runs
swift build+ theWebsiteexecutable (no Homebrew Saga) - Verifies
Website/deploy/index.html - Uploads artifact
On push to main, a second job deploys Website/deploy/ to Vercel with vercel deploy --prod.
Vercel Git integration is disabled for builds (Ignored Build Step → Don’t build anything). Only GitHub Actions publishes production.
Full deploy notes: Build & Preview.
Read next
- Implementation: templates, Tailwind, Mermaid in depth
- Build & Preview: troubleshooting and Vercel setup