ypsilanti/README.md
Maxfield Luke bda33ef628
Some checks failed
ci / test (push) Failing after 2s
pages / build (push) Failing after 1s
pages / deploy (push) Has been skipped
Initial commit
2026-07-06 02:56:57 -04:00

204 lines
5.4 KiB
Markdown

# ypsilanti
minimal static site generator in zig.
`example/` is a demo site you can build and serve to see how everything fits together.
## install
requires [zig](https://ziglang.org/download/) (0.14+).
```
zig build -Doptimize=ReleaseFast
cp zig-out/bin/ypsilanti /usr/local/bin/
```
`-Doptimize` options: `Debug` (default), `ReleaseSafe`, `ReleaseFast`, `ReleaseSmall`. use `ReleaseFast` for production, skip the flag for development.
## usage
```
ypsilanti build ./site ./output # build site
ypsilanti serve ./site # dev server on :3000
ypsilanti serve ./site 8080 # custom port
```
## site structure
```
site/
├── content/ # markdown files → html
├── layouts/ # page templates
├── partials/ # reusable snippets
├── static/ # copied as-is (css, images, fonts)
└── config # optional site config
```
## config
```text
title: example.com
url: https://example.com
author: your name
description: site description
theme: darkode
paginate: 10
nav: home=/, posts=/posts/, tags=/tags/, rss=/feed.xml
```
## front matter
```markdown
---
title: Hello World
date: 2025-01-09
description: post summary for rss
layout: post
tags: linux, software
categories: technology
draft: false
aliases: /old-post/, /legacy/post.html
---
your content here
```
- `title` - page title, available as `{{title}}`
- `date` - includes page in rss feed
- `description` - rss item description
- `layout` - which layout to use from `layouts/`
- `tags` - comma-separated tags, used for generated tag pages
- `categories` - comma-separated categories, used for generated category pages
- `draft` - set to `true` to skip the page
- `aliases` / `alias` - comma-separated local URLs that emit static redirect pages
any key except reserved `content`, `nav_html`, and `toc` is available as `{{key}}` in templates.
## templates
layouts go in `layouts/`. use `{{content}}` for the rendered markdown:
```html
<!DOCTYPE html>
<html>
<head><title>{{title}}</title></head>
<body>
{{> header}}
{{{toc}}}
<main>{{{content}}}</main>
</body>
</html>
```
Template variables are HTML-escaped by default. Variables rendered directly inside `href` and `src` attributes are also checked for safe URL schemes. Triple braces render raw HTML only for built-in `content` and `nav_html` variables.
partials go in `partials/`. include with `{{> name}}`:
```html
<!-- partials/header.html -->
<nav><a href="/">home</a></nav>
```
## markdown
supported:
- `# headers` (h1-h6)
- `**bold**` and `*italic*`
- `[links](url)` with safe `http`, `https`, `mailto`, anchor, or relative URLs
- `` `inline code` ``
- fenced code blocks with language class
- basic syntax highlighting spans for common fenced code languages
- `- unordered lists`
- `> blockquotes`
- pipe tables
- footnotes with `[^id]` and `[^id]: text`
- whole-line shortcodes: `figure`, `youtube`, `vimeo`, and `callout`
Headings get generated `id` attributes and a raw `{{{toc}}}` template variable.
shortcode examples:
```markdown
{{< figure src="/img/photo.jpg" alt="Photo" caption="A caption" >}}
{{< youtube dQw4w9WgXcQ >}}
{{< vimeo 123456789 >}}
{{< callout type="warning" title="heads up" text="important note" >}}
```
## error pages
create `content/404.md` for custom 404 pages. works in dev server and most static hosts.
pages are generated with clean URLs: `content/about.md` becomes `about/index.html` and is served at `/about/`.
## rss + sitemap
auto-generated on build:
- `sitemap.xml` - all pages
- `feed.xml` - pages with `date:` front matter
- `posts/` - dated posts sorted newest first, paginated with `paginate:`
- `tags/` and `categories/` - taxonomy indexes and paginated term pages
set base url in `site/config` with `url:`. `site/url` is still supported as a fallback.
## link checking
`build` validates internal `href` and `src` links after writing pages and static files. Root-relative links, relative links, and fragment anchors must point to generated output or the build fails.
## deploy
### github pages (recommended)
ypsilanti ships a GitHub Action, so a full deploy is one `uses:` line. Copy
[`docs/github-pages.yml`](docs/github-pages.yml) into your site repo as
`.github/workflows/pages.yml`, then set Settings → Pages → Source to *GitHub
Actions*. The core of it:
```yaml
- uses: actions/checkout@v4
- uses: maxf1eld/ypsilanti@main # pin to a tag or SHA for stability
with:
source: ./site # your site source dir
- uses: actions/upload-pages-artifact@v3
with:
path: ./_site
```
The action builds ypsilanti and your site with no local Zig install needed.
Internal links are root-relative (`/about/`), so deploy at a **root domain**
a user/org page (`you.github.io`) or a custom domain. A *project* page
(`you.github.io/repo/`) serves under a subpath and will break those links.
### manual / other hosts
Build locally and push the output anywhere that serves static files (Netlify,
Cloudflare Pages, S3, a plain web server):
```
ypsilanti build ./site ./docs
git add docs && git commit -m "build" && git push
```
## dev workflow
```
ypsilanti serve ./site
```
opens dev server with live reload. edit any file in content/, layouts/, partials/, or static/ and browser refreshes automatically.
## tests
```
./test.sh
```
## contributing
Contributions are welcome. Run `./test.sh` before opening a pull request; CI
runs the same suite. See [CONTRIBUTING.md](CONTRIBUTING.md) for more.
## license
MIT — see [LICENSE](LICENSE).