kgames

KGames — free keyboard games for kids
git clone https://www.keyboard.games/code/kgames.git
Log | Files | Refs | README | LICENSE

commit d5b89decce3fee0676dd96522c7867f8eed946fc
parent 001e26b7497c2ad35770e162656bdca46bb96ef5
Author: Kyle Barlow <kb@kylebarlow.com>
Date:   Mon, 17 Aug 2026 20:48:30 -0700

Self-host git on NearlyFreeSpeech; drop Codeberg

Point "Open source" at https://www.keyboard.games/code/, a static stagit
code browser served alongside a dumb-HTTP clone source. Nothing runs
server-side: the mirror and HTML are generated locally by deploy.sh and
rsynced up, and a pre-push hook runs the deploy on every push to origin.

tools/stagit-style.css restyles the browser to the site palette.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C3gaidQGTXzcyXKfEaw45a

Diffstat:
MCLAUDE.md | 17+++++++++++++++++
MREADME.md | 11+++++++++++
Mindex.html | 2+-
Atools/stagit-style.css | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 204 insertions(+), 1 deletion(-)

diff --git a/CLAUDE.md b/CLAUDE.md @@ -136,6 +136,23 @@ unchanged — game logic never references this module. 9. Add browser test cases to `tests/browser/runner.js` 10. Run `npm test` — all must pass before committing +## Hosting & deploy + +The project is self-hosted on NearlyFreeSpeech — there is no Codeberg/GitHub forge. + +- `origin` is `ssh://…@ssh.nyc1.nearlyfreespeech.net/home/private/kgames.git` + (a bare repo outside the document root). +- A **`pre-push` hook** runs `deploy.sh` on every push to `origin`, which rsyncs + the site, refreshes the restic-backed mirror at + `/media/bespin/kyle/backups/gits/kgames.git`, and publishes a static + [stagit](https://codemadness.org/stagit.html) code browser + dumb-HTTP clone + source to `https://www.keyboard.games/code/`. Skip with `KG_SKIP_DEPLOY=1`. +- `deploy.sh` and the hook are **untracked**, so a fresh clone does not reproduce + this setup — copies plus restore notes live in + `/media/bespin/kyle/backups/gits/kgames-untracked/`. +- The mirror is deliberately **never repacked** so restic dedups its objects. +- `tools/stagit-style.css` is the code browser's stylesheet (site palette). + ## Color palette `#E63946` red · `#1D7CF2` blue · `#FFD23F` yellow · `#2EC4B6` teal diff --git a/README.md b/README.md @@ -58,6 +58,17 @@ Standard static file hosting. No `.htaccess` tricks needed. 4. Add unit tests in `tests/unit/` and browser test cases in `tests/browser/runner.js` 5. Run `npm test` — must pass before committing +## Source + +Browse the code at <https://www.keyboard.games/code/>, or clone it: + +``` +git clone https://www.keyboard.games/code/kgames.git +``` + +The browser and the clone URL are static files generated by +[stagit](https://codemadness.org/stagit.html) — no forge, no server-side code. + ## License GPL-3.0 — see [LICENSE](LICENSE) diff --git a/index.html b/index.html @@ -22,7 +22,7 @@ </main> <footer> - <p><a href="https://codeberg.org/ursidaureus/keyboard_games">Open source</a></p> + <p><a href="https://www.keyboard.games/code/">Open source</a></p> </footer> <script src="js/main.js"></script> diff --git a/tools/stagit-style.css b/tools/stagit-style.css @@ -0,0 +1,175 @@ +/* KGames stylesheet for the stagit-generated code browser. + Based on stagit's default style.css, recoloured to the site palette: + #E63946 red · #1D7CF2 blue · #FFD23F yellow · #2EC4B6 teal */ + +body { + color: #2b2b2b; + background-color: #FFF5F5; + font-family: 'Fredoka', system-ui, sans-serif; + margin: 1.2em; +} + +pre, td.num, #blob, .code, pre a { + font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; +} + +a { + color: #1D7CF2; +} + +a:hover { + color: #E63946; +} + +h1, h2, h3, h4, h5, h6 { + font-size: 1em; + margin: 0; +} + +h1 { + font-size: 1.4em; + font-weight: 600; +} + +img, h1, h2 { + vertical-align: middle; +} + +img { + border: 0; +} + +a:target { + background-color: #FFD23F; +} + +a.d, +a.h, +a.i, +a.line { + text-decoration: none; +} + +#blob a { + color: #9a9a9a; +} + +#blob a:hover { + color: #1D7CF2; + text-decoration: none; +} + +table thead td { + font-weight: 600; +} + +table td { + padding: 0.1em 0.5em; +} + +#content table td { + vertical-align: top; + white-space: nowrap; +} + +#branches tr:hover td, +#tags tr:hover td, +#index tr:hover td, +#log tr:hover td, +#files tr:hover td { + background-color: #FFE8E8; +} + +#index tr td:nth-child(2), +#tags tr td:nth-child(3), +#branches tr td:nth-child(3), +#log tr td:nth-child(2) { + white-space: normal; +} + +td.num { + text-align: right; +} + +.desc { + color: #6b6b6b; +} + +hr { + border: 0; + border-top: 2px solid #2EC4B6; + height: 2px; +} + +pre a.h { + color: #1D7CF2; +} + +.A, +span.i, +pre a.i { + color: #17836f; +} + +.D, +span.d, +pre a.d { + color: #E63946; +} + +pre a.h:hover, +pre a.i:hover, +pre a.d:hover { + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + body { + background-color: #141418; + color: #d8d8d8; + } + hr { + border-color: #2EC4B6; + } + a { + color: #5FA8FF; + } + a:hover { + color: #FF6B76; + } + a:target { + background-color: #5c4a00; + } + .desc { + color: #a0a0a0; + } + #blob a { + color: #5a5a5a; + } + #blob a:target { + color: #eee; + } + #blob a:hover { + color: #5FA8FF; + } + pre a.h { + color: #2EC4B6; + } + .A, + span.i, + pre a.i { + color: #4fd6a0; + } + .D, + span.d, + pre a.d { + color: #FF6B76; + } + #branches tr:hover td, + #tags tr:hover td, + #index tr:hover td, + #log tr:hover td, + #files tr:hover td { + background-color: #22222a; + } +}