fuzzyworld

fuzzyworld-tools / files / docs / code-site.md

code-site.md

5.1 KB · history · blame

The code site (code.fuzzyworld.net)

Static pages for every public repo, generated by server/gen.py on each push (the post-receive hook starts fw publish <name> in the background, so a push returns at once and pages update 1-5 seconds later). Every repo uses the shared hook through core.hooksPath=~/fw/tools/server/hooks.

Who sees what is set per repo; see Visibility.

Page URLs

Repo pages

URL Page
/ index of public repos: a table, newest code commit first, with description and an app link
/<name>/ summary: description, clone command, "Open in VS Code" links, license, CI status, screenshots, recent commits, README
/<name>/tree/<dir>/ directory listing (default branch)
/<name>/blob/<path>.html file view with line numbers and syntax highlighting (Pygments; files ≤ 512 KB); .md files rendered
/<name>/history/<path>.html commits that changed the file (up to 200; renames not followed)
/<name>/blame/<path>.html the commit that last changed each line (text files ≤ 256 KB)
/<name>/raw/<path> raw copies of images only (png, jpg, gif, webp, ico, avif, bmp, svg; ≤ 2 MB)
/<name>/log/ the branch's commits (up to 2000)
/<name>/commit/<sha>.html one commit with its diff (truncated at 300 KB); a page for every commit on every branch, up to 2000 per repo
/<name>/refs/ branches and tags
/<name>/branch/<branch>/... the same tree/blob/history/blame/log pages for another branch; / in a branch name is written ~

Pages for features

URL Page
/<name>/ci/, /<name>/ci/<sha>.html CI pipelines (newest 100) and one pipeline with its job logs (ci.md)
/<name>/ci/badge.svg status of the latest pipeline on the default branch
/ci/ CI dashboard: running pipelines, the queue, the last 50 results, for public repos
/<name>/issues/, /<name>/issues/<n>/ bug-report issues, when the repo's mode and the issue's state allow it (issues.md)
/<name>/usage/ Claude Code usage per commit and per session, only for repos with usage trailers (usage.md)
/usage/ the same, summed over all public repos (usage.md)
/<name>/files.json, /<name>/objects/<sha> for VS Code in the browser: every file's blob SHA and size, and each file's contents (≤ 1 MB)

Site pages

/projects/, /why-i-left-gitlab/, /my-ai-use/ and /contribute/ are files in server/content/, rendered by fw content into the common page layout.

/ci/, /usage/ and the other site pages cannot be repo names (repos with those names are skipped).

Branches

The default branch, and every branch not yet merged into it, get browse pages. A merged branch adds nothing new to read and would duplicate every page, so the branches page lists it with a link to its last commit. Every branch and tag can be cloned. Author email addresses are not shown.

License detection

The summary page names the repo's license, read from a root LICENSE, LICENCE or COPYING file (MIT, Apache-2.0, GPL, LGPL, AGPL, MPL-2.0, BSD, ISC, Unlicense, CC0), else from package.json.

Preview locally

npm run dev builds this repo's pages into a temp directory and serves them at http://localhost:8000/.

Security

The site never executes anything from a repo.

Rule How
Pages are pre-generated all repo content is HTML-escaped
Raw files are images only written only for image extensions; .htaccess also denies .php, .shtml, .cgi, .pl, .py and .sh and disables SSI/CGI (DreamHost runs .php files and SSI otherwise; tested 2026-10-26)
No scripts Content-Security-Policy: script-src 'none' on every response, which also covers SVG images
Clone copies hide internals inside public clone copies, config, description, hooks/ and logs/ return 404
File contents never render objects/<sha> is always sent as application/octet-stream with Content-Disposition: attachment, so a repo's .html or .svg can never render as a page. files.json and objects/ allow cross-origin reads, because VS Code runs on apps.fuzzyworld.net
CI logs are escaped CI pages exist only for public repos

apps.fuzzyworld.net gets the same server-side no-execution rules (no PHP, SSI or CGI). Apps themselves run JavaScript in the browser, so the apps site sends no script-blocking policy. HTML, service workers and manifests are sent with no-cache (a deploy is seen at once); /<app>/assets/ (hashed by vite) is cached for a year.

Source
1# The code site (code.fuzzyworld.net)
2
3Static pages for every public repo, generated by `server/gen.py` on each push (the `post-receive` hook starts
4`fw publish <name>` in the background, so a push returns at once and pages update 1-5 seconds later). Every repo uses
5the shared hook through `core.hooksPath=~/fw/tools/server/hooks`.
6
7Who sees what is set per repo; see [Visibility](../README.md#visibility).
8
9## Page URLs
10
11### Repo pages
12
13| URL | Page |
14|---|---|
15| `/` | index of public repos: a table, newest code commit first, with description and an app link |
16| `/<name>/` | summary: description, clone command, "Open in VS Code" links, license, CI status, screenshots, recent commits, README |
17| `/<name>/tree/<dir>/` | directory listing (default branch) |
18| `/<name>/blob/<path>.html` | file view with line numbers and syntax highlighting (Pygments; files ≤ 512 KB); `.md` files rendered |
19| `/<name>/history/<path>.html` | commits that changed the file (up to 200; renames not followed) |
20| `/<name>/blame/<path>.html` | the commit that last changed each line (text files ≤ 256 KB) |
21| `/<name>/raw/<path>` | raw copies of images only (png, jpg, gif, webp, ico, avif, bmp, svg; ≤ 2 MB) |
22| `/<name>/log/` | the branch's commits (up to 2000) |
23| `/<name>/commit/<sha>.html` | one commit with its diff (truncated at 300 KB); a page for every commit on every branch, up to 2000 per repo |
24| `/<name>/refs/` | branches and tags |
25| `/<name>/branch/<branch>/...` | the same tree/blob/history/blame/log pages for another branch; `/` in a branch name is written `~` |
26
27### Pages for features
28
29| URL | Page |
30|---|---|
31| `/<name>/ci/`, `/<name>/ci/<sha>.html` | CI pipelines (newest 100) and one pipeline with its job logs ([ci.md](ci.md)) |
32| `/<name>/ci/badge.svg` | status of the latest pipeline on the default branch |
33| `/ci/` | CI dashboard: running pipelines, the queue, the last 50 results, for public repos |
34| `/<name>/issues/`, `/<name>/issues/<n>/` | bug-report issues, when the repo's mode and the issue's state allow it ([issues.md](issues.md)) |
35| `/<name>/usage/` | Claude Code usage per commit and per session, only for repos with usage trailers ([usage.md](usage.md)) |
36| `/usage/` | the same, summed over all public repos ([usage.md](usage.md)) |
37| `/<name>/files.json`, `/<name>/objects/<sha>` | for VS Code in the browser: every file's blob SHA and size, and each file's contents (≤ 1 MB) |
38
39### Site pages
40
41`/projects/`, `/why-i-left-gitlab/`, `/my-ai-use/` and `/contribute/` are files in `server/content/`, rendered by
42`fw content` into the common page layout.
43
44- A file is Markdown, or an HTML fragment with a leading `<!-- title: … -->`.
45- An image in that folder that a page mentions (`![alt](./tower.png)`) is copied next to the page.
46- A file starting with `_` (the `/how/` draft) is not built.
47- `/why/` and `/principles/` redirect to `/why-i-left-gitlab/`; the old `fuzzyworld.net/projects/` redirects to `/projects/`.
48- `fw content` also writes `404.html`.
49
50`/ci/`, `/usage/` and the other site pages cannot be repo names (repos with those names are skipped).
51
52## Branches
53
54The default branch, and every branch **not yet merged** into it, get browse pages. A merged branch adds nothing new
55to read and would duplicate every page, so the branches page lists it with a link to its last commit. Every branch
56and tag can be cloned. Author email addresses are not shown.
57
58## License detection
59
60The summary page names the repo's license, read from a root `LICENSE`, `LICENCE` or `COPYING` file (MIT, Apache-2.0,
61GPL, LGPL, AGPL, MPL-2.0, BSD, ISC, Unlicense, CC0), else from `package.json`.
62
63## Preview locally
64
65`npm run dev` builds this repo's pages into a temp directory and serves them at <http://localhost:8000/>.
66
67- Pass other working copies after `--`: `npm run dev -- ~/code/explodorama`.
68- Set `PORT` to change the port.
69- It uses each repo's committed state. `server/site/*.css` edits show on reload; a change to `gen.py` needs a restart.
70
71## Security
72
73The site never executes anything from a repo.
74
75| Rule | How |
76|---|---|
77| Pages are pre-generated | all repo content is HTML-escaped |
78| Raw files are images only | written only for image extensions; `.htaccess` also denies `.php`, `.shtml`, `.cgi`, `.pl`, `.py` and `.sh` and disables SSI/CGI (DreamHost runs `.php` files and SSI otherwise; tested 2026-10-26) |
79| No scripts | `Content-Security-Policy: script-src 'none'` on every response, which also covers SVG images |
80| Clone copies hide internals | inside public clone copies, `config`, `description`, `hooks/` and `logs/` return 404 |
81| File contents never render | `objects/<sha>` is always sent as `application/octet-stream` with `Content-Disposition: attachment`, so a repo's `.html` or `.svg` can never render as a page. `files.json` and `objects/` allow cross-origin reads, because VS Code runs on apps.fuzzyworld.net |
82| CI logs are escaped | CI pages exist only for public repos |
83
84apps.fuzzyworld.net gets the same server-side no-execution rules (no PHP, SSI or CGI). Apps themselves run
85JavaScript in the browser, so the apps site sends no script-blocking policy. HTML, service workers and manifests are
86sent with `no-cache` (a deploy is seen at once); `/<app>/assets/` (hashed by vite) is cached for a year.