FUNCTIONS / @SPFN/PAGES — A WEBSITE FROM A GITHUB REPO

A repo
is a site.

A public GitHub repo opts in with spfn.site.yaml, keeps its markdown under site/, and @spfn/pages turns it into a validated, sanitized, render-ready site model. No build pipeline on the author's side — push is deploy.

Read the reference Get started $ pnpm add @spfn/pages
01
The premise

No build step.
The repo is the input.

The presence of spfn.site.yaml at the repo root is the owner's consent to publish — registration rejects repos without it. From there the package reads AI-authored markdown from the content root and produces the whole site model: pages, posts, nav trees, theme CSS. Per-file failures never take the site down; they land in problems and the file is skipped. This is the first source driver of SPFN's frontend serving primitive — the tenant edge is shared infrastructure, and content sources plug in via the ContentSource interface.

github repo
spfn.site.yaml
loadSite()
render-ready site model
FIG 01 — PUSH IS DEPLOY · NO AUTHOR-SIDE BUILD · PER-FILE FAILURES NEVER FATAL
02
Core technique

Docs live with the code.
The site serves them.

A mount in spfn.site.yaml serves documentation that lives next to the code — a README, a whole guide tree — as site routes, so docs are consumed on-site instead of on GitHub. A source page is the curated version: a page whose frontmatter says source: packages/core/src/db/README.md serves that doc at the page's own clean URL, with no src/ leaking in. Every relative link in rendered markdown resolves in order — a served markdown file becomes its route, a public/ asset becomes its served URL, any other repo file links back to the repo — so authors link files the way the repo is laid out and the site just works. The reference this page points to is itself a package README served this way.

packages/core/README.md
mount / source page
links rewritten to routes
served on-site
FIG 02 — A SOURCE PAGE'S CLAIM BEATS A MOUNT'S · ROUTE CONFLICTS LAND IN PROBLEMS · LENIENT FRONTMATTER
03
What's inside

One yaml file,
then it's all content.

Just push.