100 Commits
Author SHA1 Message Date
e01d116d06 Shop: a game-style item shop (hero pack, big tiles, detail with Buy and Gift) (#75)
/shop now opens on the season pack (its three looks rendered side by side,
its name, its price, one button), then rows of big tiles that show only the
item itself, its name and its price: the looks, the collection's items by
slot, the founder set while its claim is open, the Supporter badge. Hover
lifts a tile (none with reduced motion).

A tile opens a detail sheet (a <dialog>, full screen on phones): the live
3D viewer on your skin, a look's or the pack's items as small tiles to try
on, and Buy or Gift. The basket is gone: one offer, one checkout, through
the same POST /v1/web/checkout and pricing.ts rules (items: [id], amount for
the Supporter badge, gift: true for a friend), then /shop/pay as before.

Thumbnails: the same shared WebGL renderer, framed ~30 degrees round and
from above (auras higher, back items from behind, trails with the whole
player from behind), whole players fill the card's height, supersampling up
to 2048 px, redrawn when a card changes size. The viewer also looks from
slightly above.

Cut: the intro paragraph, the "three steps" claim explainer, every
description line on cards, the per-set item price lists, and the "Good to
know" list. Kept: "Ask whoever pays before you buy. Refunds within 14 days
for any reason." by Buy/Gift, the seller and Paddle terms, the legal links,
NOT_OFFICIAL, contact, the founder claim and its anti-phishing line.

Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-07 17:57:49 +01:00
6d130e9602 Downloads: Intel Macs get the x64 launcher, Windows on ARM the ARM64 setup (#73)
Every Mac was sent the Apple Silicon disk image, which an Intel Mac cannot open
(horizon#4235), and the docs said there was no Intel or Windows ARM build; both
ship in every launcher release. When the browser names the processor
(Chromium's client hints), an Intel Mac gets horizon-launcher-macos-x64.dmg and
a Windows on ARM PC horizon-launcher-setup-arm64.exe; otherwise nothing
changes. The supported systems, install steps, FAQ and llms.txt name both, and
the minimum macOS is 12 (the launcher's LSMinimumSystemVersion).

Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-07 02:38:36 +01:00
Ludovic Marie b426e147d0 Merge pull request #72 from horizon-rust/shop/unify
Shop: Amberfall as one pack, three looks, every item by slot; emotes play
2026-11-06 12:42:54 +01:00
Ludovic Marie 3df65c7819 Merge pull request #71 from horizon-rust/shop/fx-viewer
Shop: show companions, trails and auras in the 3D viewer
2026-11-05 19:30:35 +01:00
Ludovic Marie 8c0e58541e Merge pull request #70 from horizon-rust/shop/3d-framing
Shop viewer: lift the name tag above tall items, wider close-ups
2026-11-05 16:48:54 +01:00
Ludovic Marie 94d9a1b48f Merge pull request #69 from horizon-rust/shop/3d-try-on
Shop: try items on your own skin in 3D, sets, Supporter, gifts, one basket
2026-11-05 16:37:11 +01:00
Ludovic Marie fafd2ebbec Merge pull request #68 from horizon-rust/shop/3d-renderer
Shop: draw cosmetics in WebGL with the game's model math
2026-11-05 16:33:33 +01:00
c8a7166d97 Mods: "Edit project" for a project's owners (#67)
* Mod submit form: every kind, required page, icon and screenshot uploads

Registry v2's form (horizon docs/design/registry-v2.md), for the new submission service:
- Every kind: mod, native mod, modpack, resource pack, shader pack (.hshader), shader pack (.zip with a
  shaders/ folder) and data pack. The file picks the kind; a .zip is read (its central directory only) to
  tell a data pack, a resource pack and a shaders/ pack apart, and asks when it can't.
- Required, with a message beside each field: description (Markdown, 50 to 10,000 characters, live
  count), 1 to 3 categories of the kind (chips), an icon upload (square PNG, 64 to 1024 px, at most
  256 KiB, checked in the browser with a preview). Optional: tags (at most 10, plain, no gambling words)
  and up to 8 screenshots (PNG/JPEG, at most 1 MiB, 320x180 to 3840x2160; previews, reorder, remove).
- A shaders/ pack needs the "I made this pack and its licence allows Horizon's registry to distribute
  it" box (own_work).
- No icon address any more: the service refuses it.
- A new version of a listed project: the icon is optional, and "Fill in from its page" loads the page
  fields from the index so the submission doesn't replace them with blanks.
- Sends entry (with categories, tags, own_work), icon, screenshot parts and the file; the proxy's body
  limit follows the service's (76 MiB).

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Mods: "Edit project" for a project's owners

/mods/<id>/edit changes a listed project's page with no new version: name, summary, description,
authors, licence, source, categories, tags, a new icon, and its screenshots (keep, remove, reorder,
add). It sends the submission service `edit: true` with no file, the kept screenshots as their registry
paths (screenshots/<id>/<n>.<ext>) in order, and the new images; uploads always come after the kept ones,
as the service places them. It shows the pull request the service opens.

/mods/<id> shows an "Edit project" button in the Publisher box to a signed-in account whose login the
index lists among the owners; the service decides by GitHub ID. The edit page can't be framed, like
the submit form.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-05 14:09:40 +01:00
ef7ba22edc Mod submit form: every kind, required page, icon and screenshot uploads (#66)
Registry v2's form (horizon docs/design/registry-v2.md), for the new submission service:
- Every kind: mod, native mod, modpack, resource pack, shader pack (.hshader), shader pack (.zip with a
  shaders/ folder) and data pack. The file picks the kind; a .zip is read (its central directory only) to
  tell a data pack, a resource pack and a shaders/ pack apart, and asks when it can't.
- Required, with a message beside each field: description (Markdown, 50 to 10,000 characters, live
  count), 1 to 3 categories of the kind (chips), an icon upload (square PNG, 64 to 1024 px, at most
  256 KiB, checked in the browser with a preview). Optional: tags (at most 10, plain, no gambling words)
  and up to 8 screenshots (PNG/JPEG, at most 1 MiB, 320x180 to 3840x2160; previews, reorder, remove).
- A shaders/ pack needs the "I made this pack and its licence allows Horizon's registry to distribute
  it" box (own_work).
- No icon address any more: the service refuses it.
- A new version of a listed project: the icon is optional, and "Fill in from its page" loads the page
  fields from the index so the submission doesn't replace them with blanks.
- Sends entry (with categories, tags, own_work), icon, screenshot parts and the file; the proxy's body
  limit follows the service's (76 MiB).

Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-05 14:08:10 +01:00
222c0c7b2d Mods: data packs and shaders/-folder packs, categories, tags and screenshots (#65)
- KINDS gains datapack ("Data packs") and shaderpack ("Shader packs (shaders/ folder)"), so the index's
  projects of those kinds are listed instead of dropped; a data pack's page says to put it in a world's
  datapacks/ folder.
- /mods/<id> shows the project's categories (linking to the filtered list) and tags (linking to a search)
  as chips, and its screenshots as a lazy-loaded gallery that scrolls on phones and opens full size.
  Only the kind's own categories, plain tags and screenshots on the registry's Pages site are shown;
  nothing is drawn when the index has none.
- /mods gets a category filter with the selected kind's list (registry v2's lists), combined with the
  kind, the search (which now also matches tags) and the order; all four live in the address
  (?kind=&category=&q=&sort=) so a filtered list can be shared.

Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-05 13:29:46 +01:00
ba6e026d3e Docs: shader packs are back (Horizon's .hshader and Iris/OptiFine packs) (#64)
settings.md and the FAQ still said shader packs were removed; the current Nightly loads both formats
from shaderpacks/ (Options > Horizon Settings > Shader Packs) and the launcher installs .hshader packs.

Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-05 12:48:43 +01:00
9db9414885 Mods: open the submit form to Horizon shader packs (.hshader) (#63)
The registry, its checks, the submission service and launcher 0.2.42 all take
the `shader` kind already; only the form kept it disabled. It now takes a
.hshader (and only a .hshader) as a shader pack, says what one is, and the mod
page's manual install points at shaderpacks/ and Options > Horizon Settings >
Shader Packs instead of "can't be installed yet".

Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-05 12:38:23 +01:00
Ludovic MarieandClaude Opus 5.5 ff11317390 Download: Windows gets the per-user setup exe (#62)
The home and header Download buttons served horizon-launcher-windows-x64.zip.
Run from inside the ZIP (or from a protected folder) the launcher can't replace
itself and stays on its version (horizon#9287). horizon-launcher-setup.exe
installs it in %LOCALAPPDATA%, where it updates itself. The setup exes now count
in the download total too.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 21:39:58 +01:00
Ludovic MarieandClaude Opus 5.5 36e5abf65c Install docs: put the launcher where it can update itself; download an old one again once (#59)
* Install docs: put the launcher where it can update itself; stuck on an old one, download it again once

A launcher opened from the disk image, a Mac app never moved out of Downloads, or a ZIP opened in
Explorer can't replace itself, and launchers up to 0.2.40 say so only in Settings (horizon#9287).
The install steps now say where to put it, Updating describes the new "A new version is available"
prompt, and a short section tells players on an old launcher to download it again once. The GitHub
link no longer filters on the old launcher-v tags.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Install docs: say what an old launcher shows when it can't update

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Install docs: launcher 0.2.41 still lacks the update prompt

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 21:30:25 +01:00
Ludovic MarieandClaude Opus 5.5 a5c2db7a06 Shop: players where Paddle doesn't serve claim in the Wardrobe; privacy says what that keeps (#61)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 19:49:32 +01:00
Ludovic MarieandClaude Opus 5.5 c8a185aff4 Benchmarks: Mac mini and desktop measured again with Nightly 2026-11-04 (#58)
* Benchmarks: the Mac mini and the desktop measured again with Nightly 2026-11-04

- Mac mini (M4 Pro) and desktop (RTX 4080): Horizon Nightly 2026-11-04 (67dad0d, the bundle players get,
  resources from its own horizon-prepare) against vanilla 26.3, render distance 12 and 32, 3 games each,
  tools/perf_bench.py (seed 1234, 1280x720, VSync off), the 10-22 recipe.
- What differs from 10-22, said in each machine's note: the Mac's session was locked, so Horizon drew
  offscreen (no longer held at 144 Hz); the desktop ran at load 28-30 at each start, 40-70 during the runs
  (CI and builds), and vanilla went through sway's Wayland (Xwayland timed out each frame).
- The ThinkPad keeps its 10-22 runs (no benchmarks on it any more); its note says so, and that players with
  the same HD Graphics 620 see less in real play (opt-in telemetry, aggregates only).
- summary.json and public/benchmarks.json rebuilt with the old site's scripts/benchmarks.mjs (now outside the
  repo), which reproduces the previous summary exactly; the Mac's Horizon entries are allowed offscreen.
- "Measured on" shows the span of dates, since the machines were measured on different days.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Benchmarks: keep the Mac mini's 2026-10-22 runs

The 2026-11-04 Mac mini runs had Horizon offscreen against a windowed Java Edition, which skips presenting
and isn't a fair comparison with the page's "1280x720 window" method. The Mac mini keeps its 10-22 files,
and its note says its runs are older, as the ThinkPad's does. summary.json and public/benchmarks.json
rebuilt with the same script.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 17:47:31 +01:00
Ludovic MarieandClaude Opus 5.5 8dcc740829 Shop: claim the founder set on the site, with Paddle's overlay (#56)
The shop is the site's only: the buyer types their Minecraft name, the
cosmetics service looks it up and the page shows the account's skin
face to confirm, then Paddle's checkout (0 CHF) opens over the page.
After Paddle's "completed" the page waits for the service to grant it
and says the items are in the launcher's Wardrobe, with the order
number and paddle.net for the receipt. Closing the checkout, errors
and an already claimed account have their own states. ?preview shows
the form before the window opens; the service decides who may claim.

Terms, privacy and /shop/pay now say claims and purchases happen on
the shop page, bound to the account named, and that the skin comes
from textures.minecraft.net.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 16:10:14 +01:00
Ludovic MarieandClaude Opus 5.5 28704d4b65 /shop/pay: Paddle's checkout page (the account's default payment link) (#55)
The cosmetics service's checkouts open as /shop/pay?_ptxn=txn_…; Paddle.js opens that
transaction's overlay by itself. The page only shows where the checkout is (open, done,
closed, refused); the webhook grants. The client-side token comes from PADDLE_CLIENT_TOKEN at
request time. Privacy: this page alone loads Paddle.js from cdn.paddle.com.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 15:43:52 +01:00
Ludovic MarieandClaude Opus 5.5 2228d526a1 Shop and legal pages: [email protected] for purchases (#54)
* Shop and legal pages: [email protected] for purchases

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Terms: free items cost nothing (whether Paddle asks for payment details at 0 CHF isn't confirmed)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 14:57:03 +01:00
Ludovic MarieandClaude Opus 5.5 93aaf6e44b Shop for Paddle's review: /shop with prices, /terms, /refunds, purchases in /privacy (includes #51) (#53)
* Add /shop: the founder set, free to claim in the launcher (hidden until the window opens)

A Shop page in the site's look: the four founder items (Founder Visor, Sunlet,
Founder Tag, First Light) as free for a limited time, with the end date and the
days left, a 3D preview of the set on a player, and how to claim it in the
launcher with a Microsoft sign-in. No prices, currency or payment; the site
never signs anyone in.

- The preview draws the service's own item files (parts, pivots, box UV,
  inflate, animations) in CSS 3D, on a made-up player skin.
- The data is read on the server only (cosmetics.playhorizon.dev
  /v1/catalogue and the item files), cached for a minute, and checked field by
  field before it reaches the page.
- Gate: /shop, its nav entry and its sitemap line exist only while the
  service's claim window is open. With the window unset (today), the service
  down or an unexpected answer, /shop is a 404. SHOP_PREVIEW=1 shows a sample
  window for previews and is ignored on Railway's production environment.
- With the Shop entry in the nav, its gaps are tighter below xl so Download
  stays inside 1024 px; without it the header is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Shop: the claim step names the launcher's Shop tab

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Shop: the new founder set (cap, tee, backpack, tag), a 7-day preview window, no theme

- The founder set is now Founder Visor (a six-panel cap), Founder Tee (new
  slot `torso`, "Shirt"), Founder Backpack and Founder Tag, in the order the
  service lists them. Cards show the catalogue's name and line; no price.
- Launcher themes are free in the launcher's Settings: the shop drops theme
  items, the theme card, its sky and its copy.
- 3D preview: the item's attachment scale (models in half pixels) now also
  frames the cards; a top-level part with its own `bone` rides that bone
  (the tee's sleeves on the arms) under the same attachment. Head and shirt
  cards sit on a faint mannequin of the bones they ride.
- SHOP_PREVIEW's sample window was hardcoded to 31 March 2027: it is now
  seven days from the start of the current hour. Production still reads
  only the service's claim dates; the gate is unchanged.
- Countdown: whole days left ("7 days left"), hours on the last day.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Shop for Paddle's review: /terms, /refunds, purchases in /privacy, prices on /shop

- /shop is always there with its prices (Free, 0 CHF) before sign-in; the claim's dates
  and countdown, the header link and the sitemap line still wait for the open window.
- /terms (terms of sale: a licence to visual items, sold by Ludovic Marie through
  Paddle.com as merchant of record, no capes, no random rewards, no gameplay effect),
  /refunds (14 days, any reason, through Paddle), and what the cosmetics service keeps
  for purchases on /privacy.
- The footer links privacy, terms, refunds and the shop on every page; Mojang's line
  on the shop and legal pages.
- The contact email is one constant (components/legal.tsx), unset until a
  playhorizon.dev address exists: lu4ovic.com's contact page until then.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-04 14:31:24 +01:00
Ludovic MarieandClaude Opus 5.5 85a56690c5 Add /artists: Horizon is looking for 3D artists (#50)
A short page saying Horizon welcomes 3D artists to make cosmetics for
Horizon players (head, back, shoulder pets, auras, emotes), what fits
(blocky, own designs, all ages, no capes), and how to get in touch: the
Discord, or privately through lu4ovic.com. Linked by one line under the
Community cards and listed in the sitemap.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-02 20:55:09 +01:00
Ludovic MarieandClaude Opus 5.5 51de19f19f Mod submit: let iOS pick .hmod/.hnmod/.hpack files (#49)
iOS greys out files whose extension it has no type for, so the picker's accept list (.hmod,.hnmod,.hpack,.zip)
blocked every mod there. accept now also names application/octet-stream (and application/zip, text/plain for
.minisig), and submit checks the file's extension itself.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-02 19:21:40 +01:00
Ludovic MarieandClaude Opus 5.5 8fd9018e25 Hub market: no tax once the SMP drops it (#46)
horizon-mods#153 removes the market tax and the Treasury, and market.json
loses taxes_collected. The tax tile and sentences now show only while a tax
is set.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-02 17:28:29 +01:00
Ludovic MarieandClaude Opus 5.5 f6db7f55dd Add the hub's People tab and the launcher's download count (#47)
People (/hub#people): the Discord server's staff roles top to bottom, read
from Kira's GET /staff.json (cached 10 minutes), with each person's
Discord name, confirmed GitHub login and job; a message when Kira can't be
read.

The hero's launcher line shows the launcher's downloads over every release
(GitHub's counts, updates included), read on the server through Kira's
GitHub proxy and kept half an hour; hidden when GitHub can't be read.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-02 16:12:49 +01:00
Ludovic Marie d7e5d31f05 Merge pull request #43 from horizon-rust/fix/mods-proxy-origin
Forward Origin to the mod registry (submits were refused)
2026-11-02 06:21:00 +01:00
Ludovic MarieandClaude Opus 5.5 a393ac8026 Forward Origin to the mod registry
The registry refuses a submission or a rating unless its Origin is the
site's (from_the_site in horizon-mod-registry). The /api/mods proxy
did not forward that header, so every submit came back with "send it
from the registry's pages". The proxy has already checked that the
request comes from the same site; the staff route forwards it the same
way.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 06:20:47 +01:00
Ludovic MarieandClaude Opus 5.5 d240c29176 Docs: read the current path inside Suspense so doc pages render again (#41)
Every /docs/* page answered 500: DocsNav and SiteHeader call usePathname()
outside <Suspense>, which Next.js 16 with cacheComponents refuses when it
renders /docs/[...slug] at request time (CLIENT_HOOK_DYNAMIC). Both now
read the path in a small child inside <Suspense>; the fallback is the same
markup with no item marked as current, so the page looks the same.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-02 02:22:33 +01:00
Ludovic MarieandClaude Opus 5.5 1c7dad20f3 Market: one price per item, to buy and to sell (#40)
The SMP mod (0.29.0) gives each item one price (market.json `price`; `buy`
and `sell` repeat it on the sides the market trades). The board shows that
price, notes buy-only and sell-only items, and says the tax comes on top.
Older pages without `price` fall back to `mid`.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-02 01:18:06 +01:00
Ludovic MarieandClaude Opus 5.5 1f92679b2d Hub: draw the moon below the header so it stops covering Download (#39)
On /hub and /hub/market the pixel moon was drawn at 32 px, right under the
header's translucent Download button (1280, 1920) and the menu button (360,
768), so players saw the moon over the button. Use moonTop={104}, as the mod
pages already do, so the moon sits just below the 72 px header.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-11-01 23:26:48 +01:00
Ludovic Marie 31d0bed664 Merge pull request #37 from horizon-rust/feat/hub-market
Hub: the official server's market (/hub/market)
2026-11-01 22:14:14 +01:00
Ludovic MarieandClaude Opus 5.5 fd6e40bbc5 The official server's market in the hub: /hub/market
Live prices, 1 h and 24 h moves, volumes, a 24 h / 30 d chart per item and
the day's summary, from the page the SMP mod writes, through Kira
(/smp/market.json) and /api/market.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 18:45:59 +01:00
Ludovic Marie eb8940f275 Merge pull request #35 from horizon-rust/feat/hub-appeal
Hub: appeal page for bans, Cases tab on /hub/mod
2026-11-01 17:40:50 +01:00
Ludovic MarieandClaude Opus 5.5 fb8b721adc Hub: /hub/appeal for banned users and official-server bans, and a Cases tab on /hub/mod
The appeal form reads Kira's appeal/* routes through the staff proxy: the link Kira DMs before a ban, or Discord
sign-in once Kira has its client secret. Timeouts and quarantines are appealed on Discord. The Cases tab lists
Kira's numbered mod cases and the appeals with their status (GET mod/cases).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 17:40:36 +01:00
Ludovic Marie f86477051e Merge pull request #34 from horizon-rust/feat/revalidate-on-push
Fresh GitHub data within a minute: revalidate on Kira's call
2026-11-01 16:46:02 +01:00
Ludovic MarieandClaude Opus 5.5 3314bf9cbb Read GitHub's REST API through Kira's proxy, straight from GitHub as a fallback
The service has no GitHub token (60 requests an hour); revalidating on
every change would spend them in minutes. GITHUB_PROXY_URL with the
REVALIDATE_SECRET bearer reads through Kira's GitHub App and its ETag
cache. No visual change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 16:44:26 +01:00
Ludovic MarieandClaude Opus 5.5 57cb79bca4 Revalidate GitHub data on Kira's call: fresh within a minute of a push
Every GitHub loader gets a cache tag (the game's main, its issues and
pull requests, its releases, horizon-mods' main). POST /api/revalidate,
with REVALIDATE_SECRET as a bearer token, expires the tags Kira names
when GitHub's webhook reports a change. Files of a main branch are read
at main's current commit, since raw.githubusercontent.com keeps a
branch's files for five minutes. No visual change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 16:29:35 +01:00
Ludovic Marie 9e68bb1653 Merge pull request #33 from horizon-rust/feat/staff-in-hub
Move the staff dashboards into the hub
2026-11-01 15:28:42 +01:00
Ludovic MarieandClaude Opus 5.5 0be2a3bbc0 Move the staff dashboards into the hub
The staff pages are now part of the hub: /hub/team, /hub/mod, /hub/sign-in,
/hub/setup (Kira's password link) and /hub/staff-help, under the hub's tab
bar. In a browser that signed in, /hub shows the member's Team or
Moderation tab after the public ones (a localStorage hint only; every
dashboard still checks the session with Kira). /staff/* redirects to the
new addresses, fragment included, so links already sent keep working.

Also: an expired or used setup link now shows Kira's message instead of
"This page needs the link Kira DMs you".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 15:27:55 +01:00
Ludovic Marie db4b406030 Merge pull request #32 from horizon-rust/fix/staff-proxy-origin
Staff proxy: forward Origin so staff sign-in and setup links work
2026-11-01 15:13:44 +01:00
Ludovic MarieandClaude Opus 5.5 40355686b3 Staff proxy: forward the browser's Origin to Kira
Kira's staff API refuses every POST whose Origin isn't the site's. The
Next.js rebuild's proxy stopped forwarding Origin, so every staff POST
(password setup, sign-in, writes, the /apply form) got 403 "Wrong origin.".
The proxy already refuses cross-site writes before forwarding.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 15:12:09 +01:00
Ludovic Marie 6477e028a0 Merge pull request #30 from horizon-rust/feat/stats-page
Players page (/stats): the live count, its history and the official server's
2026-10-31 17:59:54 +01:00
Ludovic Marie c1b4abd3f7 Merge pull request #31 from horizon-rust/chore/discord-invite
Discord: the new official invite discord.gg/playhorizon
2026-10-31 17:12:16 +01:00
Ludovic MarieandClaude Opus 5.5 6b5c61f55f Discord: the new official invite discord.gg/playhorizon
Ludovic (2026-10-31): replace the old invite everywhere.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-31 17:11:51 +01:00
Ludovic MarieandClaude Opus 5.5 490e981d5f Players page (/stats): the live count, its history and the official server's
A new page at /stats with the exact live count, today's and the all-time peak, the share
with a world open and the split per system, and charts over 24 hours, 7 days, 30 days or
everything, for every game's ping and for the official server (its status ping). The
charts are inline SVG drawn by src/stats.js (no library): one y axis, the highest count
per point as an area and the average as a dashed line, a tooltip under the pointer or the
arrow keys, a table view, and both themes. Data from the telemetry server's
GET /v1/live/history (horizon-rust/horizon#5217, #5235).

The home page's "Playing now" row and the footers link to it, and Privacy says what the
server now writes down (totals only).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-31 17:04:50 +01:00
Ludovic Marie b5c8755c11 Merge pull request #27 from horizon-rust/chore/close-team-applications
Apply page: Support and Mod only
2026-10-30 14:54:47 +01:00
Ludovic MarieandClaude Opus 5.5 7604214da5 Apply page: Support and Mod only (Horizon Team applications closed)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:54:40 +01:00
Ludovic Marie 304461126b Merge pull request #26 from horizon-rust/fix/staff-null-fields
Staff dashboards: Kira's cards without a link; each part renders on its own
2026-10-30 14:54:11 +01:00
Ludovic MarieandClaude Opus 5.5 6d2f5087ad Staff dashboards: Kira's cards without a link; each part renders on its own
The live Team dashboard went blank ("Cannot read properties of null (reading
'replace')"): Kira's work board sends its own cards (kind "card", e.g. #20, #23) with
url: null, and the board drew every card as a link with escape(k.url). horizon-site#24
made escape() take null; this fixes the cause and the blast radius:

- Kira's cards without a link are plain cards ("Card #20"), never href="".
- section() renders each part on its own (the board's two halves, the roadmap, the
  decisions, the Inbox, the moderation numbers, each application): one that fails
  shows a one-line error in its place and the rest of the dashboard still renders.
- Lists Kira may send as null (links, history, people, areas...) are read as empty.
- src/staff-dashboards.test.js builds both dashboards from payloads with every
  optional field null, and checks a failing part leaves the others intact.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:53:52 +01:00
Ludovic Marie 6e2b339f23 Merge pull request #25 from horizon-rust/feat/staff-inbox-wording
Staff: "Needs your decision"; the moderation counts say they are counts only
2026-10-30 14:48:55 +01:00
Ludovic MarieandClaude Opus 5.5 822744ee3c Staff: "Needs your decision"; the moderation counts say they are counts only
- Ludovic's Inbox section for the applications only he decides (stalled, too few
  voters) is named "Needs your decision".
- Under the moderation counters: "Counts only: Kira stores no list of who or what."
  They stay unclickable by design.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:48:38 +01:00
Ludovic Marie a3637706a5 Merge pull request #24 from horizon-rust/fix/escape-null
Staff dashboards: escape() takes null as empty text
2026-10-30 14:29:03 +01:00
Ludovic MarieandClaude Opus 5.5 d06826aaab Staff dashboards: escape() takes null as empty text
The Team dashboard stopped with "Cannot read properties of null (reading
'replace')" when the API sent a field as null.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:28:50 +01:00
Ludovic Marie e916a3a208 Merge pull request #23 from horizon-rust/fix/mod-submit-unreadable-file
Submit form: read the picked file first, say to pick it again when it changed
2026-10-30 14:28:18 +01:00
Ludovic Marie c5165e9039 Merge remote-tracking branch 'origin/main' into fix/mod-submit-unreadable-file 2026-10-30 14:27:45 +01:00
Ludovic MarieandClaude Opus 5.5 a38ed9975f Submit form: read the picked file before sending, name it when it can't be read
A browser keeps a picked file by reference. When the file changes on disk after it was picked (a mod rebuilt while
the form is open), moves, or is locked by another program, Chrome aborts the upload before any byte is sent: fetch
throws "Failed to fetch" and the form said "The service didn't answer". Railway's http logs show exactly that for the
10 failed submissions of 2026-10-30 13:06-13:09Z: 499, client closed the request, after 1 ms.

The form now reads the file and the signature first. A file the browser can no longer read gets a message that says
to pick it again; a file over the registry's 64 MB limit is refused before the upload.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:27:44 +01:00
Ludovic Marie 47a0f23009 Merge pull request #22 from horizon-rust/feat/staff-inbox
Staff dashboards: Inbox first, a clearer application card, "How this works"
2026-10-30 14:27:40 +01:00
Ludovic MarieandClaude Opus 5.5 f6d1648e91 Help: sessions wording
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:27:16 +01:00
Ludovic Marie 8fc71d764b Merge main into feat/staff-inbox 2026-10-30 14:25:40 +01:00
Ludovic MarieandClaude Opus 5.5 a7497fbb84 Staff Inbox: one-line items, Approve now and Veto inline, decisions that name you
- Each Inbox item says what to do and the time left on one line ("Vote on harbor's
  Team application · closes in 31 h"); Ludovic's veto-window items carry Approve now and
  Veto right there, with the same confirmations as the card.
- The Team Inbox lists the decisions of the last week that name you.
- The vote line in plain words: "1 of 2 votes needed · closes in 2 days".
- While a vote runs Ludovic sees the counts and the Against comments without names
  (kira#83); names show once it closes.
- "How this works": what is stored and for how long, sessions, resetting a password.
- Tests for the Inbox and the vote line.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:25:40 +01:00
Ludovic Marie fab212bfc8 Merge pull request #21 from horizon-rust/chore/remove-hub-suggest
Hub: remove the suggest form; ideas go to #horizon-ideas
2026-10-30 14:16:54 +01:00
Ludovic MarieandClaude Opus 5.5 568705b4c7 Hub: remove the suggest form; ideas go to #horizon-ideas
Roadmap suggestions now come only from #horizon-ideas posts on Discord (Ludovic's
rule; Kira's /suggest is gone too). The hub's "Suggest something" form, its POST to
/hub/suggest and the item list it offered are removed; the hub links to Discord instead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:16:32 +01:00
Ludovic MarieandClaude Opus 5.5 04bc14734e Staff dashboards: Inbox first, a clearer application card, "How this works" (proposal)
Both dashboards open on an Inbox listing only what needs you now (applications waiting for your vote with the
time left, votes you are in closing within a day; for Ludovic his veto window and the ones he decides; on the
Team dashboard your open cards), each item one line with a button. The same short nav in both: Inbox,
Applications, then the dashboard's tabs, Stats, and "How this works" (/staff/help: the vote, the veto, the log,
privacy). An application card's first screen holds the applicant, the role, the contributor badge with PR
links, the answers, where the vote stands in plain words, the tally once you voted and your buttons (For,
Against, Abstain as large targets: two taps); the votes, history and recusal fold under "More". Veto asks for
an optional private note.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 14:13:03 +01:00
Ludovic Marie b0be71e721 Merge pull request #20 from horizon-rust/fix/staff-referrer
Caddy: the staff pages' no-referrer header is no longer overwritten
2026-10-30 13:59:35 +01:00
Ludovic MarieandClaude Opus 5.5 e41343ae2f Caddy: the staff pages' no-referrer header is no longer overwritten
Caddy runs the unmatched header block after the matched ones, so the site-wide Referrer-Policy replaced the
staff and apply pages' no-referrer. The site-wide one is now a default (?Referrer-Policy).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 13:59:16 +01:00
Ludovic Marie 6b21653034 Merge pull request #19 from horizon-rust/feat/staff-mod
Staff dashboards: the Moderation dashboard (applications, moderation stats)
2026-10-30 13:57:22 +01:00
Ludovic MarieandClaude Opus 5.5 2c3dcb0707 Staff dashboards: the Moderation dashboard (applications, moderation stats)
/staff/mod loads staff-mod.js: Mod and Support applications (the shared staff-apps.js view, now with the
voters' names Kira sends) and the moderation counters from mod/stats: tiles for the last 7 and 30 days,
weekly charts (reports and mod-mail, warnings and timeouts, kicks and bans, AutoMod, joins and leaves) and
the weekly table with CSV and JSON export. Nothing of the Team's data.

The applications view no longer says a closed ballot can be changed, never reports a role for a decline, and
its "Decided" heading is the dashboard's section size.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 13:56:52 +01:00
Ludovic Marie 97f10b7ba6 Merge pull request #18 from horizon-rust/feat/staff-team-stats
Staff dashboards: the Team dashboard's Stats and Data tabs
2026-10-30 13:51:57 +01:00
Ludovic MarieandClaude Opus 5.5 5874d2df0e Staff dashboards: the Team dashboard's Stats and Data tabs
Stats: tiles (pull requests ready, CI, open bugs, last game release) and inline SVG bar charts over 12
weeks from Kira's team/stats: pull requests opened and merged, median hours to first review and to merge,
releases, Discord messages, daily active members, joins and leaves (counts only), open bugs by source and
area. One axis per chart, a legend for two series (colors checked for contrast and colour blindness in both
themes), a hover title on every week and the numbers in a table.

Data: what the dashboard holds as tables (kanban, Team-only items, Team notes, decisions, roadmap progress,
contributors, weekly numbers), each exportable as CSV or JSON. CSV cells that a spreadsheet would run as a
formula get a leading quote.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 13:51:25 +01:00
Ludovic Marie e56aab72bb Merge pull request #17 from horizon-rust/feat/staff-team
Staff dashboards: the Team dashboard (kanban, roadmap Team layer, decisions, applications)
2026-10-30 13:45:39 +01:00
Ludovic MarieandClaude Opus 5.5 7dfc92c65d Staff dashboards: the Team dashboard (kanban, roadmap Team layer, decisions, applications)
/staff/team loads staff-team.js: the Team kanban (add, edit, move, delete) beside Kira's read-only work
board; the roadmap's Team-only items (add, edit, delete, "Publish…" gives the roadmap.toml entry for a pull
request) and Team notes on public items; the decisions log (record, edit with history, withdraw); and the
applications (staff-apps.js, shared with the Mod dashboard): GitHub facts first, blind ballots, recusal,
Ludovic's veto, approve, decline and take-back, the audit lines. #applications and #application-<id> open
the right tab, also when the dashboard is already open.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 13:45:22 +01:00
Ludovic Marie 14618a8d35 Merge pull request #16 from horizon-rust/feat/staff-apply
Staff applications: the /apply form and its privacy section
2026-10-30 13:40:13 +01:00
Ludovic MarieandClaude Opus 5.5 e7336565a3 Staff applications: the /apply form and its privacy section
/apply#<token> opens with the one-time link Kira DMs through /apply on Discord: it shows who applies and
for which role, renders Kira's questions and sends the answers back; the token leaves the address bar at
once. The page is noindex, no-store, no-referrer and out of robots and the sitemap. The privacy page says
what an application keeps and that it is reduced to the ID, role, outcome and date after 90 days.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 13:38:46 +01:00
Ludovic Marie a184c1cc0e Merge pull request #15 from horizon-rust/feat/staff-pages
Staff dashboards: /staff sign-in, password setup, sign-out; the API proxy to Kira
2026-10-30 13:38:03 +01:00
Ludovic MarieandClaude Opus 5.5 513bac6607 Staff dashboards: /staff sign-in, password setup and sign-out; the API proxy to Kira
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 13:36:27 +01:00
Ludovic Marie 4c4e290d90 Merge pull request #6 from horizon-rust/fix/links-after-wasm-mods
Docs: links for when WebAssembly code mods are gone (draft, waits for horizon#3371)
2026-10-30 01:09:45 +01:00
Ludovic Marie ec9dd8e40a Merge pull request #14 from horizon-rust/feat/parity-gaps-row
Home: "Player-visible gaps open" leads the at-a-glance list
2026-10-29 23:05:38 +01:00
Ludovic MarieandClaude Opus 5.5 ba50685242 Home: "Player-visible gaps open" leads the at-a-glance list
Reads the count from the README's "Player-visible gaps: N open" paragraph
(horizon-rust/horizon#3921); a README without it builds as before. The list
is built in build.mjs so its numbering follows.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 21:57:11 +01:00
Ludovic Marie 1ebb776e58 Merge pull request #13 from horizon-rust/docs/troubleshooting-owner-download
Troubleshooting: Play downloads 26.3 for an owner
2026-10-29 18:25:41 +01:00
Ludovic MarieandClaude Opus 5.5 1f21bc35fb Troubleshooting: Play downloads 26.3 for an owner
"Not prepared" told players to play 26.3 once in the official launcher. Since
horizon#3354 Play downloads it from Mojang for a signed-in owner.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 18:25:24 +01:00
Ludovic Marie 44b6414a40 Merge pull request #12 from horizon-rust/fix/own-copy-owner-download
Home: the launcher downloads 26.3 from Mojang for an owner
2026-10-29 18:24:40 +01:00
Ludovic MarieandClaude Opus 5.5 5b91b35891 Home: the launcher downloads 26.3 from Mojang for an owner
"Your own copy" still said to install Java Edition with the official launcher and
play 26.3 once. Since horizon#3354 (launcher 0.2.22), Play downloads 26.3 from
Mojang for a signed-in account that owns the game when nothing is installed.
bunchy7s on Discord.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 18:24:25 +01:00
Ludovic MarieandClaude Opus 5.5 208f0d119b Make a mod: hook points version 2 are in the current Nightly (#11)
Nightly 4baa571 has them (horizon#3435), so the pages stop saying they
aren't out.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-29 13:22:26 +01:00
Ludovic Marie 56719ee3c6 Merge pull request #10 from horizon-rust/docs/mods-pages-two-kinds
Docs: the players' Mods page and the overview pages for the two kinds
2026-10-29 11:09:30 +01:00
Ludovic Marie 5a6ab6e05f Merge pull request #9 from horizon-rust/docs/content-test-publish
Make a mod: content mods, testing and publishing for the two kinds
2026-10-29 11:09:21 +01:00
Ludovic Marie 4825fd51a1 Merge pull request #8 from horizon-rust/docs/make-a-native-mod
Make a mod: native mods (setup, the bundle, hook points)
2026-10-29 11:09:10 +01:00
Ludovic MarieandClaude Opus 5.5 80b071aa8a Merge docs/mods-pages-two-kinds into fix/links-after-wasm-mods
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 11:08:16 +01:00
Ludovic MarieandClaude Opus 5.5 5ee9042b54 Merge docs/content-test-publish into docs/mods-pages-two-kinds
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 11:08:05 +01:00
Ludovic MarieandClaude Opus 5.5 cbb148c695 Merge docs/make-a-native-mod into docs/content-test-publish
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 11:08:01 +01:00
Ludovic MarieandClaude Opus 5.5 9c9b8b9a3e Make a mod: hook points version 2 are on main, not in a Nightly yet
The current Nightly (6f8c7a0) doesn't contain them; the pages promised
them for the next one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 11:07:50 +01:00
Ludovic MarieandClaude Opus 5.5 e4d0c434b2 Docs: drop the Mod API pages from the navigation, with WebAssembly code mods
horizon#3371 removes docs/api/mods.md and docs/api/mods-reference.md; the
site's pages stopped linking them in the Make a mod rewrite (#8, #9, #10).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 11:05:16 +01:00
Ludovic MarieandClaude Opus 5.5 86f8e831bd Mods: list native mods, and the form takes .hnmod (#7)
The registry's index has seven native mods (kind native-mod), Horizon's
Zoom, FPS Counter, Keystrokes and Minimap among them, and the site left
them out: it showed only the kinds it knew. They are now a kind of their
own in the list and its filter. Their page says they are code the launcher
compiles, with no sandbox, names the Horizon commit each version was made
on instead of the raw API string, and gives native-build as the way to
build one by hand. The submit form takes a .hnmod and picks the kind from
it, as the registry's service already accepts them.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-29 10:57:33 +01:00
Ludovic MarieandClaude Opus 5.5 4e80b1dc05 Docs: the players' Mods page and the overview pages for the two kinds
Mods and data packs explains content and native mods, and how a native mod
is installed, built (the notice, the warning, the Native mods instance) and
set up in Options > Mods. The APIs, How Horizon is built, Modpacks and the
docs index stop calling mods sandboxed WebAssembly, and no page links the
Mod API pages that go with it any more.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 10:54:35 +01:00
Ludovic MarieandClaude Opus 5.5 44f2a68815 Make a mod: content mods, testing and publishing for the two kinds
Content mods get their manifest on their own page and lose the WebAssembly
parts (the SDK example, mod.wasm, code beside content). Testing covers a
native mod's unit tests, native.py check (also on the newest Nightly), a
build to play and the registry's check; publishing adds native.py package,
the .hnmod and how a native mod is reviewed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 10:53:26 +01:00
Ludovic MarieandClaude Opus 5.5 108aa6a8d5 Make a mod: native mods (setup, the bundle, hook points)
The first three pages of "Make a mod" described WebAssembly mods, which are
going away. They now describe the two kinds that stay, then native mods:
horizon-mixins bundles on Horizon's hook points, checked with horizon-mods'
native.py, built by the launcher (native-build, the notice and the warning),
with settings pages under Options > Mods. The worked example, Playtime, is a
native mod that compiles into the current Nightly.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 10:49:40 +01:00
Ludovic MarieandClaude Opus 5.5 d14d84f068 Releases and install docs: Horizon ships only the Nightly (#5)
The game's releases are Nightlies since 2026-10-28: list the current
nightly and the last week's nightly-<date> above every vX.Y.Z, read a
Nightly's title as its version, give its journal entry the build's id
(its tag moves), and say in docs/install.md that the launcher plays the
Nightly for everyone.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-28 22:15:32 +01:00
Ludovic MarieandClaude Opus 5.5 274c95a1a1 Sponsor link in the top bar, the phone menu and the footer (#4)
Ludovic: a Sponsor button on the site, to his GitHub Sponsors.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-28 14:27:43 +01:00
Ludovic MarieandClaude Opus 5.5 329365b24d Site: say what 100% parity covers instead of "Matches vanilla" (#3)
Players read "Matches vanilla 100%" as "no bugs left" while they report
differences daily. The tile, the headline and each subsystem now say they
pass the harnesses that compare them, and the table links the open reports.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-28 13:10:27 +01:00
Ludovic Marie 1c66e104f3 Merge pull request #2 from horizon-rust/legal/mod-policy-privacy
Mod policy page, who made each project, privacy: registry and Kira
2026-10-28 00:51:02 +01:00
Ludovic MarieandClaude Opus 5.5 56ef27ebbd Mod policy page, who made each project, and the registry and Kira in the privacy page
- /mods/policy shows the registry's MOD-POLICY.md, with the takedown form and the private contact;
- every project page says who made it: Horizon for official projects (author Horizon, source in horizon-rust),
  otherwise its authors, who own it and answer for it, not made or endorsed by the Horizon project;
- the list page says a listing is not an endorsement; the submit form's required box accepts the policy;
- privacy: the registry's sign-in cookie, and what Kira keeps on Discord (and that questions to her go to the
  Claude API).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 00:50:51 +01:00
Ludovic Marie 588dd6e2b3 Merge pull request #1 from horizon-rust/links-1
Point links to the horizon-rust organisation
2026-10-27 21:19:46 +01:00