This repo is archived. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
OctoLauncher/NEWS.md
T
OctoTeam 02bfea8f02
Build check / build (push) Has been cancelled
Initial commit
2026-05-07 19:31:21 -07:00

5.6 KiB

News feed

The launcher's News tab fetches ${MAIN_VITE_SERVER_URL}/news.json and renders the entries on the landing screen. The endpoint is dynamic: it mirrors the same forum posts the website's homepage shows in its "Recent forum posts" cards, so updating the forum updates the launcher.

Endpoint

GET ${MAIN_VITE_SERVER_URL}/news.json200 application/json

MAIN_VITE_SERVER_URL comes from main/.env at build time. With the current production setup that resolves to the public site origin (e.g. https://octowow.st/news.json).

The route is served by Laravel (routes/web.phpnews.json) and reads from App\Services\ForumFeedService, which fetches the configured phpBB Atom feed (FORUM_FEED_BASE_URL/FORUM_FEED_MODE/FORUM_FEED_FORUM_ID in config/customs.phpforum_feed). The same service backs the homepage's recent-forum-posts Livewire component, so what shows in the launcher is exactly what shows on the site.

No auth. The launcher times out after 8 seconds and validates the body against the schema below — malformed payloads surface as the "Couldn't reach the news feed" error state (with a Try again button).

Payload contract

{
  "items": [
    {
      "id": "2026-04-24-launch",        // required, stable, used as React key
      "title": "Welcome to the new client",  // required
      "date": "2026-04-24",             // required, anything Date.parse() accepts
      "body": "Multi-line\nbody text supported.",  // required, \n preserved
      "author": "example",               // optional
      "url": "https://example.com/changelog"  // optional, must be a full URL
    }
  ]
}

Source of truth for the schema: src/common/schemas.ts (NewsItemSchema, NewsFeedSchema). If you change the contract, update both ends.

Notes:

  • items is rendered in the order returned — sort newest-first on the server.
  • body is rendered as plain text with whitespace-pre-wrap. No HTML/markdown.
  • url, when present, becomes a "Read more" button that opens in the user's default browser via shell.openExternal. Skip it for inline-only posts.
  • id should never change for an existing post (stable React keys, future bookmarking/read-state).

Publishing

There is no static file to edit anymore. To change what the launcher shows, post on the forum (FORUM_FEED_BASE_URL, e.g. https://octowow.st/forum). The next launcher fetch picks it up subject to two cache layers:

  • forum_feed.cache_ttl (default 600 s, env FORUM_FEED_CACHE_TTL) — Laravel server-side cache of the parsed Atom feed.
  • Cache-Control: public, max-age=120 on the /news.json response — short edge cache so launcher launches in a burst don't all hit Laravel.

The launcher's react-query cache also holds for 5 minutes per session; users can hit the refresh icon in the News header to force a re-fetch (which still hits the two cache layers above).

Tuning what shows

  • Which forum / mode shows: set FORUM_FEED_MODE (topics_active | topics | news | forum) and, if forum, FORUM_FEED_FORUM_ID in the website container's environment.
  • How fresh: lower FORUM_FEED_CACHE_TTL for fresher news at the cost of more upstream forum fetches. Pair with the route's 120-second Cache-Control if you also want to relax the edge cache.
  • How many items: the route currently caps at 10; the homepage shows 3. Edit the recent(10) argument in routes/web.phpnews.json to change the launcher cap independently of the homepage.

Testing

Confirm Laravel is serving it:

curl -s ${MAIN_VITE_SERVER_URL}/news.json | jq .

Expected: a {"items": [...]} body. An empty items: [] means the forum feed is reachable but has nothing matching the configured mode (or the cache is still warm with an empty result — bust it by php artisan cache:clear inside the website container, or wait FORUM_FEED_CACHE_TTL seconds).

No items / errors:

  • {"items": []}FORUM_FEED_BASE_URL is unset, the feed returned non-2xx, the body wasn't parseable Atom XML, or the configured forum has no posts. Check the website container's storage/logs/laravel.log for ForumFeedService warnings.
  • Couldn't reach the news feed in the launcher — Laravel returned a 5xx (route exception, missing ForumFeedService binding) or the schema validator rejected the body. Check the launcher's main-process log at %APPDATA%\octo-launcher\logs\main.log for Malformed news feed.

End-to-end check in the launcher:

  1. Open the launcher (the News tab is the default view when no other tab is selected).
  2. Click the refresh icon in the News header.
  3. Entries should appear within ~1 second once Laravel + the forum cache are warm.

Failure modes the launcher already handles

Server response UI behaviour
200 with valid JSON Renders entries
200 with empty items: [] "No news yet — check back later."
200 with malformed JSON or missing required fields Error state + Try again. Reason logged in main-process logs (%APPDATA%\octo-launcher\logs\main.log).
404, 5xx, network unreachable, > 8s timeout Error state + Try again.

You don't need to ship a placeholder news.json to avoid 404s — the empty/error state is intentional.

Where the code lives