Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 404.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<div class="wrap cover-grid">
<div>
<h1>Nothing built here yet.</h1>
<p class="lead">There's no page at this address. All the mods are one click away, or go straight to a mod's own site.</p>
<p class="lead">There's no page at this address. Go back to the mods, or straight to a mod's own site.</p>
<p><a class="btn" href="/">Back to the mods</a></p>
</div>
<nav class="needs" aria-label="The mods' own sites">
Expand Down
21 changes: 20 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,24 @@ main).
- The hub has no shared `release.js`; `assets/site.js` is hub-only. If you change or add a selector in it, update the
stub DOM in `scripts/test-site.mjs` too (the stub throws on any selector it doesn't know).

## Writing README and website text

Kyler, 2026-09-24: "simplicity and elegance is effective and desirable." Every change to the README, the website
text and the player docs follows these rules.

- **Write for a Timberborn player** who wants to download, install and use the mod. Developer detail goes in
`DEVELOPING.md`; link to it rather than repeating it.
- **Short.** One idea per sentence, most under about 20 words. A paragraph or FAQ answer is one to three sentences,
a troubleshooting answer a few numbered steps.
- **Lead with the action.** Menu paths as arrow chains; on-screen labels in bold, exactly as in game.
- **Say each thing once**, where a player would look for it; link to it elsewhere.
- **Plain words.** No internals (class names, ids, formats) unless the player needs them to act.
- **Cut** filler, repeated caveats, edge cases a player won't meet, and history ("since …", "no longer", older
builds). Describe the mod as it is now.
- **Check every fact against the code** before writing it; changelogs lag.
- **Keep, briefly:** credits, the unofficial line, the status, and safety facts.
- **Reread as a new player before publishing.** Every step works as written, and nothing is said twice.

## Website

- **Where:** the repo root: `index.html` (opening with the need index, three walnut boards of mods, install, footer),
Expand Down Expand Up @@ -104,6 +122,7 @@ main).

### Content rules

- Every word follows *Writing README and website text* above.
- Describe each mod as it is now. No "New in <version>", "added in …" or version history; that belongs in each mod's
own release notes.
- Each card's status line and caution wording match that mod's README exactly in substance (read it with
Expand All @@ -120,7 +139,7 @@ main).

A new release alone needs **no** edit: the button, size, date, pill and "Newer preview" link update themselves. Edit
the hub when a mod's features, status, requirements or caution change, when a mod is added, or when a mod's site
changes its look.
changes its look. Write every change by *Writing README and website text* above.
1. Read the mod: `gh release list -R timbermods/<Repo> -L 5`, `gh release view <tag> -R timbermods/<Repo>`, its README
(command above) and its site. List what changed for players.
2. Update every place the hub states that fact:
Expand Down
78 changes: 78 additions & 0 deletions DEVELOPING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Developing the Timbermods site

A static page with no build step and no dependencies. The maintainer rules (what never to edit, the markup hooks,
the checklist for a changed mod) are in [CLAUDE.md](CLAUDE.md). The look is in [DESIGN.md](DESIGN.md).

## Preview

```bash
node scripts/serve.mjs
```

Then open <http://127.0.0.1:8765/>. A missing path gets a plain 404, so open `/404.html` directly.

## Publishing

GitHub Pages builds from `main`, folder `/ (root)`. Merging to `main` publishes in about a minute. Every path is
relative, except in `404.html`: Pages serves it at any missing address, so it uses root paths.

## How "Download latest" works

The buttons never hard-code a version. Each mod's `<article class="card">` carries `data-repo` and `data-asset`, a
regex that picks the mod ZIP from a release's assets. In the browser, `assets/site.js`:

1. paints at once from `data/releases.json`, the release snapshot;
2. then checks the GitHub API live (two requests per mod, cached 30 minutes) and updates the button;
3. if both fail, leaves the button as a plain link to the repo's Releases page.

It offers the release GitHub marks as **Latest**, however many pre-releases follow it. A repo with only pre-releases
gets its newest one, marked **Preview**. A pre-release published after the offered release adds a "Newer preview"
link under the button.

The pill says **Stable** unless the mod has a caution. Then it shows the `data-maturity` label (such as **Beta**), so
the two never disagree.

## The release snapshot

`.github/workflows/refresh-releases.yml` runs `node scripts/update-releases.mjs` every hour (GitHub often runs it
only every few hours; it can also be started from the Actions tab). It commits `data/releases.json` to `main`, so
never edit that file by hand.

The script keeps each repo's newest 12 releases and, under `latest`, GitHub's Latest release (`null` when there is
none). It rewrites the file, and its `generated` time, only when the data changed. The footer reads "Release data last
changed <date>". To run it yourself, set `GITHUB_TOKEN` to avoid rate limits.

## Tests

```bash
node scripts/test-site.mjs
```

Every check must pass. They run offline: `assets/site.js` against a stub page and a fake GitHub API, and
`update-releases.mjs` in a scratch folder against the same fake API. `.github/workflows/tests.yml` runs them on every
pull request and every push to `main`.

## Adding or changing a mod

Copy an existing mod's `<article class="card">` in `index.html`. Set its `--c` accent colour, `data-repo`,
`data-asset`, links and text. The snapshot script finds the new repo by itself. Add the mod to the need index,
`404.html` and the README too; the full checklist is *Update the website* in [CLAUDE.md](CLAUDE.md).

A mod with a caution (`<p class="caution">Beta: …</p>`) also needs `data-maturity` on its `<article>`, set to the
caution's label (`data-maturity="Beta"`). When the mod is ready, remove both. The tests check that they match.

## Files

| Path | What it is |
| --- | --- |
| `index.html` | The page, with all eight mods |
| `404.html` | The not-found page, with a link to each mod's site |
| `assets/style.css` | Styles: walnut boards on birch by day, on a forest floor at night |
| `assets/site.js` | The download buttons and the theme toggle |
| `assets/fonts/` | Anybody, self-hosted (SIL Open Font License, `OFL-Anybody.txt`) |
| `assets/img/` | The opening valley by day and at dusk (`make_valley.py`), the birch, forest-floor and walnut textures (`make_textures.py`), and the social preview `og.png` |
| `assets/img/cards/` | Each mod's picture, a 960×600 capture from its own site |
| `data/releases.json` | The release snapshot (generated) |
| `scripts/` | `serve.mjs` (preview), `test-site.mjs` (tests), `update-releases.mjs` (snapshot) |
| `scripts/card-art.py` | Recaptures the mods' pictures from their live sites: `python scripts/card-art.py [id ...]` (Playwright, Pillow, installed Microsoft Edge) |
| `.github/workflows/` | The hourly snapshot refresh (`refresh-releases.yml`) and the tests (`tests.yml`) |
5 changes: 3 additions & 2 deletions PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ the card `id`, its accent `--c` (taken from that mod's own site), its category p
- Co-op with fewer crashes and desyncs: an independent fork of BeaverBuddies with Steam friend invites, a connection
panel, teammate cursors and desync fixes.
- **Feature-complete**: game-update and bug-fix releases only; new features go into Timber Together. GitHub's Latest.
- Its status line follows its README (the newest release is fixes only and hasn't been played yet). GPL-3.0.
- Its status line follows its README (the newest release has been played and works). GPL-3.0.
2. **Timber Together** (`timber-together`, `#1a6a77`, Multiplayer; Harmony, Mod Settings;
`data-maturity="Beta"` with a Beta caution).
- Tagline *Build apart. Thrive together.* A colony each on one map; the colonies' roads never join, and they trade only at Trading Posts. Or
Expand Down Expand Up @@ -173,7 +173,8 @@ this file. Terms to use: Trading Post (capitalized); Timber Together has no land
- **Words players use:** never "card", "binder", "pocket" or "sleeve" in anything a visitor reads; say "mod", or
write the sentence without it. (The `.card` class name stays in the code: the tests and `site.js` need it.)
- **Voice:** fellow players sharing mods they find useful. Plain, exact, friendly; say what each mod does and what it
needs. Never hype, never "the best", no superlatives the READMEs don't support.
needs. Never hype, never "the best", no superlatives the READMEs don't support. Short and plain: one idea per
sentence, each thing said once, no internals and no history (see CLAUDE.md, *Writing README and website text*).
- **Unofficial:** community mods, not affiliated with or endorsed by Mechanistry. The footer says so and credits
BeaverBuddies by thomaswp and contributors ("the multiplayer design is theirs") for the two BeaverBuddies mods. Keep
both.
Expand Down
77 changes: 19 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,27 @@
# Timberborn Mods catalog
# Timbermods

A static, no-build catalog site for the Timberborn mods: BeaverBuddies Stability Fork, Timber Together, MixedStorage, Persistent Work Areas, Optimized Local Housing, Late Game Performance, The Tipsy Tail and Hungry Pathing. Each card links to the mod's own site and has a **Download latest** button.
Every Timbermods mod for Timberborn on one page: **<https://timbermods.github.io/>**. Each mod has a **Download
latest** button for its current release and a link to its own site.

## Preview locally
## The mods

```bash
node scripts/serve.mjs
```
- [BeaverBuddies Stability Fork](https://timbermods.github.io/BeaverBuddies-Stability-Fork/): co-op in one shared colony
- [Timber Together](https://timbermods.github.io/TimberTogether/): co-op with a colony for each player
- [Late Game Performance](https://timbermods.github.io/LateGamePerformance/): fewer lag spikes in big colonies
- [Optimized Local Housing](https://timbermods.github.io/OptimizedLocalHousing/): shorter walks to work
- [Hungry Pathing](https://timbermods.github.io/HungryPathing/): working beavers eat before the hunger penalty
- [MixedStorage](https://timbermods.github.io/MixedStorage/): several goods in one warehouse
- [Persistent Work Areas](https://timbermods.github.io/PersistentWorkAreas/): working-area outlines that stay on screen
- [The Tipsy Tail](https://timbermods.github.io/timberborn-tipsy-tail/): a swim-up pool bar

Then open <http://127.0.0.1:8765/>.
Every mod installs the same way: see [Installing any of these](https://timbermods.github.io/#install).

## Deploy to GitHub Pages

1. Create a repo (the name `timbermods.github.io` gives you `https://timbermods.github.io/`), and push this folder to it.
2. **Settings → Pages → Build and deployment**: deploy from branch `main`, folder `/ (root)`.

All paths are relative, so it also works from a project repo (`.../some-repo/`).

## How "Download latest" works

The mods release often, so the buttons never hard-code a version. Each card has `data-repo` and `data-asset` (a regex that picks the mod ZIP from the release's assets). In the browser, `assets/site.js`:

1. paints immediately from `data/releases.json`, a snapshot kept fresh by `.github/workflows/refresh-releases.yml` (scheduled hourly, though GitHub often runs it only every few hours; or run it from the Actions tab);
2. then checks the GitHub API live (two requests per mod, cached 30 minutes) and updates the button;
3. if both fail, the button is still a plain link to the repo's Releases page.

Which release it offers: the one GitHub marks as **Latest** (the newest release that isn't a draft or a pre-release), however many pre-releases came after it. If a repo only has pre-releases it offers the newest of those and marks the card **Preview**. If the newest listed release is a pre-release published after the offered one, a small "Newer preview" link to it appears under the button. The main rule (GitHub's Latest, else the newest pre-release) is the one the shared `release.js` on most of the mods' own sites follows; the two differ in edge cases, such as a Latest release without a mod ZIP.

The pill says **Stable** for a stable release, unless the card has a caution: then it shows the card's `data-maturity` (such as **Beta** or **Preview**), so it never contradicts the caution.

Refresh the snapshot by hand: `node scripts/update-releases.mjs` (set `GITHUB_TOKEN` to avoid rate limits). For each repo it stores the newest 12 releases and, under `latest`, GitHub's Latest release (`null` when there is none). It rewrites the file, and its `generated` time, only when that data changed, so the footer reads "Release data last changed <date>"; after a live check of every card it says so instead.

## Tests

```bash
node scripts/test-site.mjs
```

Offline checks with no dependencies: `assets/site.js` runs against a stub page and a fake GitHub API, and `scripts/update-releases.mjs` runs in a scratch folder against the same fake API. `.github/workflows/tests.yml` runs them on every push to `main` and every pull request.

## Adding or changing a mod

Copy an existing `<article class="card">` in `index.html`, then update its `--c` accent color, `data-repo`, `data-asset`, links and text. Running `scripts/update-releases.mjs` picks up the new repo automatically.

A card with a caution (`<p class="caution">Beta: …</p>`) also needs `data-maturity` on its `<article>`, set to the caution's label (`data-maturity="Beta"`). When the mod is ready, remove both, and the pill says Stable. `scripts/test-site.mjs` checks that the two match.

## Files

| Path | Purpose |
| --- | --- |
| `index.html` | The page and all eight cards |
| `404.html` | The not-found page, with a link to each mod's site |
| `assets/style.css` | Styling: walnut boards on birch by day, on a forest floor at night; light and dark themes |
| `assets/fonts/` | Anybody, self-hosted (SIL Open Font License, `OFL-Anybody.txt`) |
| `assets/site.js` | Download buttons and theme toggle |
| `assets/img/cards/` | Each mod's picture, a capture from that mod's own site (960×600) |
| `assets/img/` | The opening valley by day and at dusk (`make_valley.py` draws them), birch, forest-floor and walnut textures (`make_textures.py`), and the social preview `og.png` |
| `data/releases.json` | Release snapshot (generated) |
| `scripts/` | `update-releases.mjs` (snapshot), `serve.mjs` (local preview), `test-site.mjs` (tests) |
| `scripts/card-art.py` | Recaptures card art from each mod's live site: `python scripts/card-art.py [card-id ...]` (Playwright, Pillow, installed Edge) |
| `.github/workflows/` | Hourly snapshot refresh (`refresh-releases.yml`) and the tests (`tests.yml`) |
Working on the site itself? See [DEVELOPING.md](DEVELOPING.md).

## License

MIT. See [LICENSE](LICENSE). Timberborn, its name and its artwork belong to Mechanistry and are not covered by this license; the card art in `assets/img/cards/` comes from each mod's own site, and some of it shows the game.
MIT. See [LICENSE](LICENSE). Timberborn, its name and its artwork belong to Mechanistry and are not covered. Each
mod's picture comes from that mod's own site, and some show the game.

Unofficial, fan-made mods for Timberborn. Not affiliated with or endorsed by Mechanistry. BeaverBuddies Stability Fork
and Timber Together build on [BeaverBuddies](https://github.com/thomaswp/BeaverBuddies) by thomaswp and contributors.
Loading
Loading