The public website of EmiBSD: plain Jekyll, one stylesheet of its own (assets/css/site.css),
no theme and no framework. The code lives in EmiBSD/Kernel
(the redesigned kernel) and EmiBSD/LandingZone (the
file-by-file port, formerly EmiBSD.LZ); this repository holds only the site and reads nothing
from them at build time.
| File | URL | Nav |
|---|---|---|
index.md |
/ |
Home |
about.md |
/about/ |
About |
process.md |
/process/ |
Process |
status.md |
/status/ |
Status |
news/index.md, news/_posts/ |
/news/ |
News |
docs-site.md |
/docs/ |
Docs |
contributing.md |
/contributing/ |
Contributing |
support.md |
/support/ |
footer only |
The navigation is the nav list in _config.yml; keep it at seven entries.
The devlog is _data/news.json, one object per line shown on the pages. The home page shows
the latest five, /news/ all of them, both through _includes/news-list.html, which sorts by
date, newest first, whatever the order in the file. Fields:
date: ISO 8601 with the offset, asgit log -1 --date=iso-strictprints it; the pages sort by it and show its day. Keep one offset for every entry so the string order is the time order.post: the slug of a filenews/_posts/YYYY-MM-DD-slug.md(n4-metfor2026-10-24-n4-met.md); the line takes that post'stitleand URL. A post has atitleand an optionaldescriptionin its front matter;/news/feed.xmlcarries the posts only.titleandurl, when there is no post: the line itself and where it links (a milestone's tag in Kernel, its closing commit in LandingZone).repo:LandingZone,Kernel,Userland,DevToolsorOS, shown before the line: a LandingZone milestone or sub-milestone (M16a), a Kernel slice (N5.0 done: ..., linking to its merge commit), or a step of another repository, linking to its commit.
Kernel's slices are written here, one line each when it merges; Kernel's milestones are not:
the list adds every met milestone of
_data/status.json (its date, url and optional post), labelled Kernel, so a milestone
close is recorded once, in that file.
status.md renders _data/status.json, which holds what changes at a milestone close, taken
from the Kernel repository at the commit it names:
commit,date,at: the commit the figures come from, its day, and what it was (the close of N4).crates: one object per crate,name,files,unsafe(the totals ofcargo xtask unsafe-report),note, and an optionallabelshown after the name.milestones: one object perNmilestone,name,title,scope; a met one hasdate(the tag's,git log -1 --date=iso-strict n<N>-<name>) andurl(the tag), andpostwhen a news post tells the story; one under way hasstate: "in progress"; the rest are pending.next: the milestone under way,nameand itsslices(slice,what, optionalstatedoneorin progress).
The prose of status.md (what works, the next milestone's paragraph) is edited by hand when
a milestone closes, in the same change as the data.
The site-updater agent (.claude/agents/site-updater.md) makes all of these edits from the
records of the two code repositories, checked out beside this one as ../Kernel and
../LandingZone: launch it with the tag of the close (n5-vfs) or the LandingZone commit.
It builds the site, reports every figure with its source, and never pushes.
bundle config set --local path vendor/bundle # once: gems stay inside vendor/
bundle install
bundle exec jekyll build # into _site/
bundle exec jekyll serve # http://127.0.0.1:4000The Gemfile pins the Jekyll, Liquid, kramdown and jekyll-feed versions of GitHub Pages'
github-pages gem (v232); that gem itself does not install on Ruby 4.
Every push to main runs .github/workflows/jekyll.yml, which builds the site and deploys it to
GitHub Pages (Settings > Pages > Source: GitHub Actions). CNAME holds www.emibsd.org,
and _config.yml sets url: "https://www.emibsd.org" and baseurl: "". The DNS for emibsd.org points www at GitHub Pages (CNAME to
emibsd.github.io) and the apex at GitHub's Pages addresses, which redirect to www.
GitHub Pages sets the response headers and lets a site set none of its own. Cloudflare proxies
www.emibsd.org (the DNS of emibsd.org is there, every record proxied, SSL/TLS Full (strict)),
and a Response Header Transform Rule on that zone sets the headers GitHub does not:
Content-Security-Policy (the policy below plus frame-ancestors 'none'), X-Frame-Options: DENY,
X-Content-Type-Options: nosniff, Strict-Transport-Security: max-age=31536000 and
Referrer-Policy, and removes GitHub's Access-Control-Allow-Origin: *. Turning the proxy off
loses them all; what a page can carry itself, it still does:
_layouts/default.htmlhas a<meta http-equiv="Content-Security-Policy">that allows the site's own stylesheet and images, and one script source besides the site's own: the Cloudflare Web Analytics beacon (static.cloudflareinsights.com, reporting tocloudflareinsights.com), which the proxy injects into each page with anintegrityattribute. No forms, no<base>, nothing inline. So nostyle=attribute, no<style>element and no<script>without asrcmay appear in a page; the build fails if one does. The Cloudflare rule's header must carry the samescript-srcandconnect-src, or it blocks the beacon; a browser applies the header and the meta tag both, so a source missing from either is blocked. Kramdown's|---:|column alignment writes astyleattribute, so a table that needs it takes the{: .numbers}class instead (assets/css/site.css). Browsers ignoreframe-ancestorsin a meta tag, which is why the header exists.404.htmlreplaces GitHub's own 404 page, whose policy allows inline styles.robots.txtcarries only theSitemap:line (sitemap.xmlis jekyll-sitemap's). Cloudflare's Bot Preference Sync, with the Training policy on Disallow, prepends its own block to the file it serves: aUser-agent: *group with the Content-Signal andAllow: /, then aDisallow: /per AI training crawler. The repo's file has no group of its own so the served file has one, and with Cloudflare's block gone a file with no group allows everything.
A ZAP scan of the site should report only the two informational cache alerts; a Content Security Policy alert means a page broke the rule above, a header alert means the proxy or its rule is off.
GitHub Pages renders no Mermaid and the site's CSP allows no inline styles, so diagrams are
rendered here and committed: the sources are _diagrams/*.mmd with the site's palette in
_diagrams/theme-{light,dark}.json; tools/diagrams.sh (needs mermaid-cli,
npm install -g @mermaid-js/mermaid-cli) writes assets/img/<name>.svg and <name>-dark.svg;
a page shows them with <picture> and a prefers-color-scheme source, inside <figure class="diagram">.