44 KiB
Add fastfetch Server Observations to forecast
Session ID: ses_2a6ff7d92ffeCeb6Vd6u0fTEpn Created: 4/4/2026, 10:58:18 AM Updated: 4/4/2026, 5:01:21 PM
User
Can you help fix this error with the Server Observations display? It is not showing text now: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'initialCounts') at ServerObservations.baseCountChange (serverobservations.mjs:132:81) at ServerObservations.screenIndexChange (serverobservations.mjs:109:8) at ServerObservations.updateScreenFromBaseCount (weatherdisplay.mjs:322:9) at ServerObservations.navNext (weatherdisplay.mjs:378:8) at ServerObservations.showCanvas (weatherdisplay.mjs:217:47) at loadDisplay (navigation.mjs:283:32) at displayNavMessage (navigation.mjs:204:44) at Radar.sendNavDisplayMessage (weatherdisplay.mjs:449:3) at Radar.updateScreenFromBaseCount (weatherdisplay.mjs:286:9) at Radar.navNext (weatherdisplay.mjs:378:8)Understand this error serverobservations.mjs:132 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'initialCounts') at ServerObservations.baseCountChange (serverobservations.mjs:132:81) at ServerObservations.screenIndexChange (serverobservations.mjs:109:8) at ServerObservations.updateScreenFromBaseCount (weatherdisplay.mjs:322:9) at ServerObservations.navPrev (weatherdisplay.mjs:399:8) at ServerObservations.showCanvas (weatherdisplay.mjs:218:46) at loadDisplay (navigation.mjs:282:32) at displayNavMessage (navigation.mjs:203:48) at CurrentWeather.sendNavDisplayMessage (weatherdisplay.mjs:449:3) at CurrentWeather.navPrev (weatherdisplay.mjs:394:10) at navTo (navigation.mjs:240:64)
Assistant
I’m tracing the Server Observations lifecycle to see why scrollTiming is undefined when navigation enters the display.
Tool: read
Tool: read
Tool: read
Assistant
Yes. I understand the failure now.
Root cause
ServerObservations added screenIndexChange(), but in WeatherDisplay.updateScreenFromBaseCount() that changes the render path:
if (this.screenIndexChange) {
this.screenIndexChange(this.screenIndex);
} else {
await this.drawCanvas();
}
So for Server Observations:
drawCanvas()is skipped during navigation.server-outputnever gets populatedsetTiming()never runsthis.scrollTimingstaysundefinedbaseCountChange()crashes onthis.scrollTiming.initialCounts
That exactly matches your stack trace.
Why Hazards works
Hazards also defines screenIndexChange(), but it compensates by overriding showCanvas():
showCanvas() {
this.drawCanvas();
super.showCanvas();
}
So its content and scrollTiming exist before scrolling starts.
What needs to change
-
Make Server Observations follow the Hazards pattern:
- override
showCanvas() - call
this.drawCanvas()beforesuper.showCanvas()
- override
-
Guard
baseCountChange()so it no-ops ifthis.scrollTimingis not ready yet -
Optionally initialize a safe default in the constructor:
this.scrollTiming = { initialCounts: 0, pixelsPerCount: 0 }
Expected fix shape
showCanvas() {
this.drawCanvas();
super.showCanvas();
}
and:
baseCountChange(count) {
if (!this.scrollTiming) return;
...
}
Why the body is blank
Because drawCanvas() is not being called at the point the display becomes active.
Plan
- Update
serverobservations.mjsto overrideshowCanvas()like Hazards - Add a defensive guard in
baseCountChange() - Rebuild and verify the text renders and scrolls
If you want, I can implement that fix next.
User
Sure. You may proceed with this fix
Assistant
I’m patching the Server Observations lifecycle to render before navigation starts and to safely skip scrolling until timing is ready.
Tool: apply_patch
Assistant
I’ve applied the lifecycle fix. Next I’m rebuilding to verify there are no runtime or lint issues.
Tool: bash
Tool: bash
Assistant
Fixed.
What changed
In server/scripts/modules/serverobservations.mjs I:
- Added a safe default for
this.scrollTiming - Overrode
showCanvas()sodrawCanvas()runs before navigation starts - Added a guard in
baseCountChange()so it exits if timing is not ready
Why it failed
screenIndexChange() caused WeatherDisplay to skip drawCanvas() during navigation. That meant:
.server-outputwas never renderedsetTiming()never ranthis.scrollTimingstayed undefined- scrolling crashed on
initialCounts
Result
The Server Observations display should now:
- render its text again
- initialize scroll timing before use
- scroll without throwing the
initialCountserror
npm run lint and npm run build both pass.
User
The text is visible again, but it does not scroll or show the full output, if we can't scroll could we split it up into multiple screens?
Assistant
I’m checking how existing multi-screen displays paginate so I can recommend the cleanest approach for Server Observations.
Tool: read
Tool: read
Tool: read
Assistant
Yes. Splitting into multiple screens is the cleaner fallback here.
What I found
The current scroll approach is fighting the display lifecycle a bit:
ServerObservationsredraws inshowCanvas()- scrolling depends on
baseCountChange()timing state - this module is really closer to
Local ForecastthanHazards
Local Forecast is a better model here because it:
- renders text blocks
- paginates by container height
- uses normal display navigation instead of continuous scroll animation
- is easier to keep readable on a TV
Recommended plan
Use multi-screen pagination instead of scrolling.
Behavior
- Page 1:
OS,KERNEL,UPTIME,CPU - Page 2:
GPU,MEMORY,DISK - Or use 3-4 lines per page depending on fit
Implementation shape
-
Remove the scroll-specific logic from
serverobservations.mjscalculateScrollTimingscrollCachescrollTimingbaseCountChange()screenIndexChange()- custom
showCanvas()
-
Convert the parsed server lines into pages
- chunk the
infoLinesarray into groups - recommended: 4 lines per page
- chunk the
-
Render pages into a vertically stacked container
- same pattern as
localforecast.mjs - set
this.pageHeight = container.offsetHeight - set
this.timing.totalScreens = pageCount - set
this.timing.delay = new Array(pageCount).fill(1) - keep a readable
baseDelaylike7000or9000
- same pattern as
-
Update
drawCanvas()- move the stacked content with
style.top = -this.screenIndex * this.pageHeight
- move the stacked content with
Why this is better
- simpler than animated scrolling
- matches existing project patterns
- better readability for TV viewing
- easier to reason about and maintain
Recommendation
I’d implement:
- 4 lines per page
- 7 seconds per page
- centered text layout preserved
That would likely produce:
- Page 1:
OS,KERNEL,UPTIME,CPU - Page 2:
GPU,MEMORY,DISK
If you want, when edit mode is available, I’ll switch Server Observations from scrolling to Local Forecast-style pagination.
User
Sounds good! You may proceed with this implementation
Assistant
I’m replacing the scroll-based behavior with Local Forecast-style pagination so the server info shows across multiple readable screens.
Tool: apply_patch
Assistant
I’ve switched the module logic to pagination. I’m adding the small layout rules needed so each page occupies the content area cleanly.
Tool: apply_patch
I’ve switched the logic to paging; now I’m updating the layout so each page actually moves and fills the box like Local Forecast.
Tool: apply_patch
Assistant
Tool: bash
Tool: bash
Assistant
Implemented.
What changed
server/scripts/modules/serverobservations.mjs
- Removed the scroll-timing approach
- Switched to Local Forecast-style pagination
- Splits server info into pages of 4 lines each
- Sets:
this.pageHeight = container.offsetHeightthis.timing.totalScreens = pages.lengththis.timing.delay = [1, 1, ...]
- Moves pages with
outputElem.style.top = -this.screenIndex * this.pageHeight
server/styles/scss/_server-observations.scss
- Added
position: relativeto.server-output - Added
.server-page { height: 250px; }so each page fills the display area correctly
Result
Server Observations should now:
- show all system info across multiple screens
- advance like other paginated displays
- avoid the broken scroll behavior entirely
npm run lint and npm run build both pass.
User
Still seems that some of the text gets cut off on the right borders, could we shrink the font a bit to handle this? better?
Assistant
Yes. Shrinking the font is the right next step.
What I’d change
In server/styles/scss/_server-observations.scss:
- Reduce
.server-outputfont size
- from
22pt - to
20ptfirst
- Tighten line height slightly
- from
36px - to
32pxor34px
- Optionally add a little inner horizontal padding
- so long lines don’t visually kiss the box edge
- something like
padding: 0 8px;on.server-outputor.server-page
Recommended first pass
I’d try this minimal adjustment:
.server-output {
font-size: 20pt;
line-height: 32px;
}
If that still clips, second pass:
.server-output {
font-size: 19pt;
line-height: 30px;
}
.server-page {
padding: 0 8px;
box-sizing: border-box;
}
Why this is the best approach
- minimal visual change
- keeps TV readability
- avoids reworking pagination logic
- likely fixes CPU and disk lines getting clipped on the right edge
If you want, once edit mode is available, I’d implement the 20pt / 32px version first.
User
Sure, you can proceed with these changes
Assistant
I’m making a small typography adjustment to the Server Observations slide and rebuilding so we can verify the fit improvement.
Tool: apply_patch
Assistant
The SCSS is updated. I’m rebuilding the CSS output used by the dev server now.
Tool: bash
Tool: bash
Assistant
Adjusted.
Changes
In server/styles/scss/_server-observations.scss:
font-size:22pt→20ptline-height:36px→32px- added page padding:
padding: 0 8pxbox-sizing: border-box
Result
This gives each page a bit more horizontal breathing room and should reduce right-edge clipping without changing the overall layout much.
npm run lint and npm run build both pass.
User
This is better, still seems that the long CPU and kernel names are being cut off though
Assistant
Yes. The remaining clipping is likely from a combination of:
white-space: nowrapon.server-line- centered text
- very long single-line values like
KERNELandCPU
That means even with a smaller font, those lines still have no way to wrap.
Best fix
Keep the page-based layout, but let long lines wrap cleanly.
Recommended changes
- Allow wrapping on
.server-line
- remove
white-space: nowrap - remove
text-overflow: ellipsis - use normal wrapping
- Keep the label/value readable
- likely reduce font one more step if needed:
19pt - slightly tighter line height if needed:
30px
- Give pages a little more inner width control
- keep the horizontal padding
- possibly increase to
10pxor12px
Why this is better than shrinking again
Just shrinking the font keeps the root problem:
- long strings still must fit on one line
Wrapping fixes the actual issue and should make:
Kernel: Linux 7.0.0-rc5-...CPU: 12th Gen Intel...
fit naturally over two lines when necessary.
Suggested plan
- Update
.server-lineto wrap instead of truncate - If needed, reduce font from
20ptto19pt - Recheck how many lines fit per page
- If wrapping increases page height too much, reduce
LINES_PER_PAGEfrom4to3
Recommendation
I’d try this order:
- enable wrapping first
- only then reduce font to
19ptif needed - if pages become too tall, reduce to 3 lines per page
If you want, once edit mode is available, I’d implement that exact sequence.
User
That sounds good, lets try enabling wrapping
Assistant
I’m updating the Server Observations text to wrap instead of truncating, then I’ll rebuild to verify the layout still works.
Tool: apply_patch
Assistant
The wrapping change is in. I’m rebuilding assets so the dev-served CSS picks it up.
Tool: bash
Tool: bash
Assistant
Updated.
Change made
In server/styles/scss/_server-observations.scss, .server-line now wraps instead of truncating:
- removed
white-space: nowrap - removed
text-overflow: ellipsis - added:
white-space: normaloverflow-wrap: anywhereword-break: break-word
Result
Long CPU and kernel lines should now wrap within the blue box instead of getting clipped on the right.
npm run lint and npm run build both pass.
User
Nice! Now the only issue is Server Observations is now overflowing out of the header, lets resize that to 20pt font for those screens
Assistant
Yes. The remaining issue sounds like the header title, not the body text.
What I’d change
Add a Server Observations-specific header override in _server-observations.scss:
.weather-display.server-observations,
.weather-display .server-observations {
.header .title.single {
font-size: 20pt;
}
}
More likely, since the header is on the root .weather-display element and not inside .main, the correct targeting should be against the display container id/class, for example:
#server-observations-html.weather-display .header .title.single {
font-size: 20pt;
}
Why
The shared header styles in _weather-display.scss set:
.weather-display .header .title { font-size: 24pt; }.weather-display .header .title.single { ... }
So if only Server Observations is overflowing in the header, the clean fix is a display-specific override for that title size, leaving other modules unchanged.
Likely implementation plan
- Add a display-specific header title override for Server Observations
- Set the title to
20pt - Rebuild CSS
- Verify the title stays inside the header while body text remains unchanged
One thing to confirm
Do you want only:
- the header title
Server Observationsreduced to20pt
Or also: 2. the body text reduced further as well
From your note, I believe you mean option 1 only.
User
Yes, lets do option 1 only
Assistant
I’m adding a Server Observations-specific header override so only that slide’s title drops to 20pt, then I’ll rebuild.
Tool: apply_patch
Assistant
The header override is in. I’m rebuilding the CSS used by the dev server now.
Tool: bash
Tool: bash
Assistant
Done.
Change made
Added a Server Observations-specific header override in server/styles/scss/_server-observations.scss:
#server-observations-html.weather-display {
.header .title.single {
font-size: 20pt;
}
}
Result
Only the Server Observations header title is reduced to 20pt. The body text styling is unchanged.
npm run lint and npm run build both pass.
User
Great! Can you come up with a git commit message for adding this Server Observations screen? You can write what was done between this commit in DEVLOG.md
Assistant
I’m checking recent commit style and current changes so I can draft a commit message and matching DEVLOG.md entry.
Tool: bash
Tool: bash
Tool: bash
Assistant
Proposed commit message:
add server observations display with fastfetch summary
Suggested DEVLOG.md entry:
## Server Observations
Added a new `Server Observations` forecast screen that blends Linux server telemetry into the WeatherStar rotation using `fastfetch`.
- added `/api/server-info` to run `fastfetch` and return a cleaned plain-text summary
- created a new `serverobservations` display module and EJS partial
- registered the new screen in the main display deck and script loading flow
- paginated the server info across multiple readable screens instead of trying to force a single page
- adjusted styling to better fit the blue content box and reduced the header title size for this screen
- updated navigation handling to safely work with sparse display arrays introduced by the new nav slot
- updated the frontend build so generated CSS is copied to the development-served stylesheet path as well
If you want, I can also draft a shorter conventional-style message, like:
add fastfetch-based server observations slide
User
Sounds good, you can write the DEVLOG.md entry now
Assistant
I’m adding the Server Observations summary to DEVLOG.md now.
Tool: glob
Tool: read
Assistant
DEVLOG.md doesn’t exist yet, so I’m creating it with the new entry.
Tool: apply_patch
Assistant
Added DEVLOG.md with the Server Observations entry.
User
How often does the fastfetch command get updated in the display?
Assistant
I’m checking the display refresh lifecycle so I can tell you exactly how often Server Observations reruns fastfetch.
Tool: grep
Tool: read
Tool: read
Assistant
Tool: read
Assistant
I’ve confirmed it uses the shared display auto-refresh interval unless overridden. I’m checking the default setting value so I can give you the exact cadence.
Tool: read
Assistant
fastfetch is currently refreshed on the same cadence as the app’s general data refresh setting: every 10 minutes by default.
Why
ServerObservations does not set its own refreshTime, so it inherits the base display auto-refresh behavior from WeatherDisplay:
WeatherDisplay.setAutoReload()uses:this.refreshTime ?? settings.refreshTime.value
settings.refreshTime.defaultValueis600_000600_000 ms = 10 minutes
Practical behavior
- The screen does not rerun
fastfetchevery time the slide appears - It reruns when the display data refresh cycle fires
- By default that is once every 10 minutes
- If the hidden refresh setting is changed, Server Observations will follow that value
Available refresh values in code:
30 seconds(testing)5 minutes10 minutesdefault15 minutes30 minutes
If you want, I can also outline how to make Server Observations refresh on its own cadence, like every 1 minute, without affecting the weather displays.
User
It's fine how it is thank you for exmplaining, was just curious. Could we also modify the WeatherStar4000+ v6.5.4 page that shows initially to include a link to the Server Observations display as well?
Assistant
I’m inspecting the initial landing page UI to see where the existing display links live and how to add Server Observations consistently.
Tool: grep
Tool: grep
Tool: read
Assistant
Yes. This is straightforward.
What I found
The initial page is the #loading block in views/index.ejs:
<div id="loading" width="640" height="480">
<div>
<div class="title">WeatherStar 4000+</div>
<div class="version">v<%- version %></div>
<div class="instructions">Enter your location above to continue</div>
</div>
</div>
So there is not currently a list of display links there. The only display-selection UI is farther down the page in:
Selected displays- generated dynamically into
#enabledDisplays
Best way to add it
The cleanest options are:
Option A
Add a short line under the existing instruction mentioning Server Observations, for example:
Enter your location above to continue. Server Observations is available in Selected displays.
This is minimal and consistent.
Option B
Add a second small helper line under the instruction:
Enter your location above to continueEnable Server Observations below to include Linux server info
This is probably the clearest.
Option C
Add an actual anchor link from the loading panel to the Selected displays section, like:
Enable Server Observations in Selected displays below
with a link to #enabledDisplays
That gives the user a direct jump target.
Recommendation
I’d use Option C:
- keeps the current intro screen intact
- clearly advertises the new feature
- gives a direct link to where it is enabled
Example copy:
<div class="instructions">Enter your location above to continue</div>
<div class="instructions">
<a href="#enabledDisplays">Enable Server Observations below to include Linux server info</a>
</div>
Small note
If we do this, we may also want to check whether the existing .instructions styling handles links well, or add a tiny style tweak so the link remains readable on the loading screen.
If you want, next I’d implement:
- a second line in the loading panel
- a link to
#enabledDisplays - minimal styling only if needed
User
I meant more so to put it on the screen that's shown first, not the location, the weather-display screen with all the links, we might have to shrink the font a bit
Assistant
I’m tracing the “weather-display screen with all the links” UI so I can identify the right place to add Server Observations without guessing.
Tool: read
Tool: read
Tool: read
Tool: read
Assistant
Yes, now I understand what you meant.
You’re referring to the progress screen shown first after location is entered, the one headed:
WeatherStar4000+ v...
and listing each display as clickable rows with status on the right.
What I found
That screen is built by:
views/partials/progress.ejsserver/scripts/modules/progress.mjsserver/styles/scss/_progress.scss
Each line on that screen is generated from every registered display in progress.mjs:
const lines = displays.map((display, index) => {
if (display.showOnProgress === false) return false;
...
fill = { name: display.name };
So whether a display appears there is controlled by:
display.showOnProgress
Why Server Observations is missing there
In server/scripts/modules/serverobservations.mjs, it currently sets:
this.showOnProgress = false;
That explicitly hides it from the progress screen list.
Clean plan
1. Make Server Observations appear on the progress screen
Change Server Observations so it no longer opts out of progress display.
That means either:
- remove
this.showOnProgress = false - or set it to
true
2. Keep the progress screen readable
The progress screen already uses:
font-size: 19ptline-height: 28px
That screen is tight vertically, so adding one more line may make it feel cramped depending on how many displays are enabled/shown.
3. If needed, slightly tighten the progress list
If adding Server Observations makes the list too crowded, the likely safe adjustment is in _progress.scss:
- reduce
font-sizefrom19ptto18pt - or reduce
line-heightslightly - or both, minimally
I would not change this unless the extra row visibly crowds the list.
Recommendation
Best implementation path:
- Let
Server Observationsappear on the progress screen - Check whether the existing progress layout still fits cleanly
- Only if needed, make a very small progress-screen typography reduction
Expected result
On the initial progress screen, you would get a clickable row like:
Server Observations ................................ Press Here
or its current status if not loaded.
If you want, once edit mode is available, I’d implement it in that order:
- enable it on progress
- test fit
- only then shrink the progress font if necessary
User
It's already pretty tightly packed with the current font and the 10 options shown, we will probably have to shrink the font
Assistant
Agreed. With 10 items already on the progress screen, adding Server Observations will almost certainly require a small typography reduction there.
What should change
1. Show Server Observations on the progress screen
In serverobservations.mjs:
- stop opting out with
this.showOnProgress = false
2. Slightly shrink the progress screen typography
In server/styles/scss/_progress.scss, likely:
font-size: 19pt→18ptline-height: 28px→26px
That should make room for one additional row without materially changing the look.
Why this is the right place
The progress screen rows are generated automatically from all registered displays, so once Server Observations is allowed in, the only likely layout issue is vertical density in:
.weather-display .progress.weather-display .progress .container
That’s exactly what _progress.scss controls.
Recommended implementation order
- Enable Server Observations on the progress screen
- Reduce progress screen font size to
18pt - Reduce progress line height to
26px - Rebuild and visually verify the list still fits cleanly
If 18pt is still too tight
Fallback:
font-size: 17pt- keep or slightly reduce line-height further
But I would start with 18pt / 26px.
If you want, once plan mode ends, I’d implement exactly that.
User
Sounds good, you can proceed with these changes
Assistant
I’m updating Server Observations to appear on the progress screen and tightening the progress-screen typography so the extra row fits cleanly.
Tool: apply_patch
Assistant
Server Observations is now included in the progress list. I’m shrinking the progress screen text slightly to make room for the extra item.
Tool: apply_patch
Assistant
The code changes are in. I’m rebuilding assets now so both the JS and dev-served CSS reflect the progress-screen update.
Tool: bash
Tool: bash
Assistant
Implemented.
Changes
server/scripts/modules/serverobservations.mjs
- removed the progress-screen opt-out so
Server Observationsnow appears in the initial progress display list
server/styles/scss/_progress.scss
- reduced progress screen font size from
19ptto18pt - reduced progress screen line height from
28pxto26px
Result
The initial WeatherStar progress screen should now include Server Observations, and the slightly smaller progress typography should help the extra row fit.
npm run lint and npm run build both pass.
User
Perfect! This works nicely, you may write about your progress during this commit in the DEVLOG.md file
Assistant
I’m updating DEVLOG.md to include the later refinements made during this Server Observations work.
Tool: read
Assistant
I’ve got the current entry. I’m expanding it to capture the pagination, fitting, and progress-screen work that landed afterward.
Tool: apply_patch
Assistant
Updated DEVLOG.md with the later progress:
- wrapping and sizing fixes for long server info lines
- adding Server Observations to the initial progress screen
- tightening progress-screen typography so the extra row fits
User
Great, can you also suggest a concise commit message like: Adds Server Observations to the startup screen
Assistant
Yes. A concise commit message in that style could be:
Adds Server Observations to the startup screen
A few slightly stronger alternatives:
Adds Server Observations display to startup screenAdds Server Observations screen and fastfetch summaryAdds Server Observations forecast displayAdds Server Observations to forecast rotation and startup screen
My recommendation:
Adds Server Observations to the startup screen
If you want, I can also suggest one that better covers the full scope of the change, not just the startup screen.
User
Great! That's good for this commit, now I have a new screen/ feature idea: Linux News: LWN. We can have a utility that fetches Headline and story BlurbListing from the HTML and shows it across a few screens. I think we may need 4 screens for all the news. FOr example we could just fetch this URL to check: https://lwn.net/
Assistant
I’m going to inspect the existing display patterns and the LWN page structure so I can propose a clean implementation plan for a Linux News: LWN screen.
Tool: read
Tool: read
Tool: webfetch
Assistant
Yes, this is feasible.
What I found
LWN’s homepage already exposes the content you want in a simple repeated pattern:
- headline
- category/byline/date line
- short blurb paragraph
- story link
So we would not need a browser or heavy parser. A server-side fetch plus HTML extraction should be enough.
Best fit with this codebase
The cleanest implementation is to follow the same pattern as Server Observations:
- Add a new server endpoint
- example:
/api/linux-news - fetch
https://lwn.net/ - parse the top N stories into structured JSON
- Add a new display module
- example:
linuxnews.mjs - fetch
/api/linux-news - render paginated pages
- use fixed pages instead of scrolling
- Add a new partial and SCSS
views/partials/linux-news.ejsserver/styles/scss/_linux-news.scss
- Register it in the deck
- add script include
- add display container in
views/index.ejs - give it a new nav slot after
Server Observations
Recommended content model
I’d keep it compact and TV-readable:
For each story:
- headline
- 1 shortened blurb
- optional category
Suggested page layout
Use 4 screens total, as you suggested:
- Screen 1: stories 1 and 2
- Screen 2: stories 3 and 4
- Screen 3: stories 5 and 6
- Screen 4: stories 7 and 8
That means:
- 2 stories per page
- each story gets a headline plus a trimmed blurb
This is much safer than trying to fit one story per screen with full blurbs.
Parsing strategy
Server-side parse from https://lwn.net/:
Extract per article:
- headline text from article heading
- href for link
- first paragraph blurb
- optional section like
[Kernel],[Security]
Normalize:
- strip extra whitespace
- remove subscription markers like
[$] - optionally trim blurbs to a max length
Expected implementation details
Backend
In index.mjs:
- add
/api/linux-news - fetch homepage HTML
- parse the first 8 items
- return:
{
"success": true,
"stories": [
{
"headline": "Ubuntu's GRUBby plans",
"section": "Distributions",
"blurb": "GNU GRUB 2 ...",
"url": "https://lwn.net/Articles/1065420/"
}
]
}
Frontend display
In linuxnews.mjs:
- chunk stories into 4 pages
- likely
baseDelayaround 8-10 seconds - use Local Forecast / Server Observations pagination style
Styling
Use a layout closer to Local Forecast than Server Observations:
- large readable headline
- smaller blurb text
- two stacked story blocks per page
- no scrolling if possible
Main tradeoffs
1. Homepage only vs article pages
Recommendation: homepage only
- enough content for headlines + blurbs
- much simpler
- less traffic
- more robust
2. Fixed 4 screens vs dynamic page count
Recommendation: fixed 4 screens
- matches your idea
- predictable timing
- easier to design
3. Full blurbs vs trimmed blurbs
Recommendation: trimmed blurbs
- TV readability
- keeps layout stable
Main risk
LWN markup could change over time, since this is HTML scraping rather than a formal API.
To reduce fragility, I’d keep the parser simple and tolerant:
- target article headings and following paragraphs
- skip entries that don’t match expected structure
- fall back to fewer stories if needed
Recommended plan
- Add
/api/linux-newsthat fetches and parseshttps://lwn.net/ - Return first 8 story summaries
- Build
Linux News: LWNdisplay module - Render 2 stories per page across 4 pages
- Style for TV readability with trimmed blurbs
- Add it to startup/progress list and rotation
Questions before implementation
- Should the screen title be
Linux NewsorLinux News: LWN? - Do you want to include the story section labels like
Kernel,Security,Development? - Should we exclude weekly-edition/meta posts and keep only regular news stories?
- Do you want this enabled by default like Server Observations, or opt-in?
User
- Lets do Linux News: LWN. 2. We don't need the story section labels. 3. No need to exclude any stories out of principle. 4. Lets enable it by default. You may proceed with this implementation
Assistant
I’m implementing the LWN screen end-to-end: backend fetch/parsing, a new paginated display, and deck/progress registration.
Tool: todowrite
Assistant
Tool: read
Tool: read
Tool: read
Assistant
I’ve got the integration points. Next I’m wiring the backend parser and the new paginated display files.
Tool: read
Assistant
Tool: apply_patch
Assistant
The LWN backend is in. I’m adding the new display module, partial, styles, and registration/build hooks next.
Tool: apply_patch
Assistant
The new display files are added. I’m wiring them into the deck, the production build bundle, and the stylesheet manifest now.
Tool: apply_patch
Assistant
The feature is wired in. I’m running lint/build and then I’ll spot-check the new endpoint output shape.
Tool: bash
Tool: bash
Assistant
Lint and build pass. I’m doing one quick API smoke test against /api/linux-news to confirm the parser is returning story data.
Tool: bash
Assistant
The smoke test hit the weather proxy, which usually means I hit an older running server instance rather than the updated one. I’m checking the startup log instead of guessing.
Tool: bash
Assistant
Tool: grep
Assistant
Tool: read
Assistant
Tool: read
Assistant
I verified the route ordering is correct. I’m rerunning the smoke test on an alternate port to avoid any stale dev server on 8080.
Tool: bash
Assistant
The parser works, but I found two polish issues in the returned data: LWN’s subscription marker is still in some headlines, and link extraction is too loose. I’m tightening that now.
Tool: apply_patch
Assistant
I tightened the parser. I’m re-running lint/build and a quick endpoint check on the alternate port.
Tool: bash
Tool: bash
Tool: bash
Assistant
The endpoint output is good. I’m making one final small parser tweak so article URLs prefer the story page instead of #Comments links.
Tool: apply_patch
Assistant
I’m re-running lint/build after that parser polish so the tree stays clean.
Tool: bash
Tool: bash
Assistant
Tool: todowrite
Assistant
Implemented Linux News: LWN.
What changed
Backend
Added /api/linux-news in index.mjs:
- fetches
https://lwn.net/ - parses the first 8 homepage stories
- extracts:
- headline
- trimmed blurb
- story URL
- returns JSON for the frontend display
Frontend display
Added server/scripts/modules/linuxnews.mjs:
- enabled by default
- title:
Linux News: LWN - paginates 8 stories into 4 screens
- shows 2 stories per page
- uses normal page-based navigation like the other multi-screen displays
Template and styles
Added:
views/partials/linux-news.ejsserver/styles/scss/_linux-news.scss
The layout is tuned for TV readability:
- yellow headlines
- smaller white blurbs
- two stacked stories per page
- boxed content area matching the rest of the app
Wiring
Updated:
views/index.ejsgulp/publish-frontend.mjsserver/styles/scss/ws.scss
So the new screen is:
- included in dev mode
- included in the production bundle
- included in the compiled stylesheet
- part of the display deck/progress screen automatically
Validation
npm run lintpassesnpm run buildpasses/api/linux-newsreturns parsed LWN stories successfully
If you want, next I can also add a DEVLOG.md entry for the LWN screen.
User
Hold on, we are having some issues, looks like we need to trim the story text a bit more, they're running too long in the 512x250 secreen section and on each subsequent LWN page more text gets layered over. This needs to be fixed
Assistant
I’m going to inspect the LWN display implementation and its CSS so I can pinpoint why text is overlapping and propose a precise fix plan.
Tool: read
Tool: read
Tool: read
Assistant
Yes. I understand the two actual problems now.
Root causes
1. Blurbs are too long for the available area
Right now trimBlurb() in index.mjs uses maxLength = 240, which is too generous for:
- a
512x250content box 2 stories per page- wrapped headlines + wrapped blurbs
So even if the text wraps correctly, each story block can become taller than half the page.
2. Each page has a fixed height, but each story block is unconstrained
In _linux-news.scss:
.news-pageis fixed at250px- but
.story,.headline, and.blurbhave no max-height constraints
That means when story 1 or story 2 grows too tall, it pushes beyond the page’s vertical budget. Since pages are stacked vertically in .news-output, the overflow from one page visually bleeds into the next page and looks like text layering.
Recommended fix
Backend
Trim blurbs more aggressively. Current:
maxLength = 240
Recommended:
- first pass:
140or150
That should materially reduce vertical growth.
Frontend layout
Constrain each story block so a page cannot visually overflow.
Recommended CSS changes:
- Make each page a two-row layout
- each page should reserve half the height for each story
- Give each story a fixed max height
- something like about half the page minus spacing
- Hide excess blurb text inside each story block
overflow: hidden
- Keep headlines and blurbs wrapped, but bounded
Best implementation plan
Option A: Keep 2 stories per page, trim more, and constrain block heights
This is the best first fix.
Changes:
- reduce
trimBlurb()from240to140-150 - make
.news-pagea vertical layout with two fixed-height story slots - add
overflow: hiddento.storyand likely.blurb
This should preserve your intended 4-screen design.
Option B: Fall back to 1 story per page
Only if Option A still feels cramped.
That would:
- improve readability
- but increase total screens from 4 to 8
Since you explicitly wanted 4 screens, I would not jump to this first.
Concrete change set I would make
In index.mjs
Change:
const trimBlurb = (text, maxLength = 240) => {
To something like:
const trimBlurb = (text, maxLength = 150) => {
In _linux-news.scss
Change page/story layout so each page is height-bounded:
-
.news-page- use flex column
- fixed height
250px
-
.story- fixed or calculated height for half-page
overflow: hidden
-
.blurboverflow: hidden
Example direction:
.news-page {
height: 250px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.story {
height: 116px;
overflow: hidden;
}
That is the key layering fix.
Recommendation
I recommend this exact sequence:
- reduce blurbs to
150chars - constrain each
.storyblock height - keep 2 stories per page
- rebuild and visually check
- only if still cramped, reduce blurbs further to
130
If you want, once edit mode is available again, I’d implement that exact fix.
User
Sounds good, you can proceed with this fix
Assistant
I’m tightening the LWN story content and constraining each page’s story slots so pages stop bleeding into each other.
Tool: todowrite
Assistant
Tool: apply_patch
Assistant
The backend blurbs are shortened. I’m now constraining the Linux News page layout so each page has two bounded story blocks.
Tool: apply_patch
Assistant
The page layout is bounded now. I’m rebuilding and linting to make sure the LWN fixes are clean.
Tool: bash
Tool: bash
Assistant
Tool: todowrite
Assistant
Fixed.
Changes made
index.mjs
- reduced LWN blurb trimming from
240chars to150
server/styles/scss/_linux-news.scss
- made each
.news-pagea fixed two-slot vertical layout - constrained each
.storyto116pxheight - added
overflow: hiddento both.storyand.blurb
Why this fixes it
- blurbs are shorter, so each story block is less likely to exceed half the page
- each page now has two bounded story regions instead of unconstrained content
- overflow from one page can no longer visually spill into the next page stack
Validation
npm run lintpassesnpm run buildpasses
If it still feels a little dense after you look at it, the next small tweak would be reducing blurbs again from 150 to about 130.
User
This is better, however top stories with these texts: "Brian "bex" Exelbierd has published a blog post exploring follow-up questions raised by the recent debate about the use of the LLM-based review tool." and "In early March, Dylan M. Taylor submitted a pull request to add a field to store a user's birth date in systemd's JSON user records. This was done to" were cut off when shown as the top-most stories on their respective screens. I think we need to double check to make sure those stories aren't getting cut off prematurely
Assistant
I’m checking the Linux News layout math against the shared display box sizing so I can explain exactly why the top story is being clipped and what to change.
Tool: read
Tool: read
Tool: read
Tool: read
Assistant
Yes. I see what’s happening.
What’s actually wrong
This is no longer the page-overlap bug.
Now it’s a content-budget mismatch inside each fixed story slot.
Current Linux News layout:
- each page is
250pxtall - each story gets
116px - headline is
18pt / 24px - blurb is
15pt / 18px
So a story with:
- a 2-line headline
- plus a 4-line blurb
will exceed 116px and get clipped by:
.story {
height: 116px;
overflow: hidden;
}
That means those top stories are being cut off exactly because the slot is too short for their wrapped headline + blurb combination.
Why those specific stories get cut off
The examples you gave have:
- long enough headlines to wrap
- long enough blurbs to take several lines
That combination is taller than the fixed per-story slot.
So the current trim length may still be too generous for the worst-case headline length.
Best fix plan
I would treat this like a fixed TV card layout and enforce a tighter story budget.
1. Shorten blurbs again
Current trim is 150.
Recommended next step:
- reduce to
120first
That gives much better odds of fitting after a 2-line headline.
2. Slightly tighten typography
Not dramatically, but enough to help:
- headline
18pt→17pt - headline line-height
24px→22px - blurb
15pt→14pt - blurb line-height
18px→16px
That gives back vertical room without making it hard to read.
3. Keep the fixed two-story page layout
I would not change page count yet. The 4-screen structure still makes sense.
Why I would not jump to 1 story per page yet
That would solve readability, but it changes the feature from:
- 4 pages / 8 stories
to:
- 8 pages / 8 stories
You originally wanted about 4 screens, so I’d preserve that first.
Recommended implementation order
- reduce LWN blurb trim from
150to120 - slightly reduce Linux News headline/blurb font sizes and line heights
- keep
2 stories per page - retest the previously clipped examples
Expected outcome
Those top-slot stories should stop truncating early because:
- blurbs will be shorter
- wrapped headline + blurb will fit within the existing
116pxstory slot more reliably
If you want, once edit mode is available again, I’d implement exactly that first-pass fix.