From 44d013c1bcca5187c143e9d599a68c957bff43b8 Mon Sep 17 00:00:00 2001 From: Viktor Petersson Date: Mon, 13 Jul 2026 19:31:05 +0000 Subject: [PATCH 1/2] Adopt signage-kit 2026.7.2 shared chrome; fix badge-hide selector bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopt the @screenly-labs/signage-kit shared chrome, matching the pattern already merged in the sibling Worker apps: - Fonts: rewrite sync-fonts.ts to the one-line kit wrapper, syncFonts(['bricolage-grotesque','hanken-grotesk','space-mono']); drop the local FONTS manifest and the @fontsource* deps. - build.ts: prepend the kit's styles/fonts.css + styles/brand.css to the app's raw main.css before processCss (a raw-CSS Worker can't resolve a bare @import), keeping includeDegraded. - main.css: delete the local @font-face blocks (now supplied by the kit's fonts.css). - package.json: repoint the kit to #2026.7.2, remove @fontsource* deps. Standardize the footer badge AND fix a real bug: the badge markup used class="rail__brand" (inline in the .rail masthead) while removeScreenlyBranding targeted .brand — so it NEVER hid on Screenly players. Standardize to the kit's fixed corner badge: rename the anchor's class rail__brand -> brand (href/rel/ aria/img unchanged), delete the local .rail__brand rules (the kit's prepended brand.css provides the fixed .brand), and replace the pasted-in local removeScreenlyBranding with the shared import from @screenly-labs/signage-kit/branding. The badge now actually hides on players. Co-Authored-By: Claude Opus 4.8 (1M context) --- assets/static/js/main.ts | 13 +++------ assets/static/styles/main.css | 55 +++-------------------------------- build.ts | 11 ++++++- bun.lock | 13 +++++---- package.json | 5 +--- src/components/App.tsx | 2 +- sync-fonts.ts | 42 +++++--------------------- 7 files changed, 35 insertions(+), 106 deletions(-) diff --git a/assets/static/js/main.ts b/assets/static/js/main.ts index 4d1fc3f..bb462a8 100644 --- a/assets/static/js/main.ts +++ b/assets/static/js/main.ts @@ -2,6 +2,10 @@ // degraded mode (shared across all apps). Must stay first so the shim is in // place before any render. import '@screenly-labs/signage-kit/polyfills' +// On a Screenly player the viewer is already a customer, so the promotional +// Screenly badge (.brand) is removed; every other browser keeps it. Shared with +// every signage app via the kit. +import { removeScreenlyBranding } from '@screenly-labs/signage-kit/branding' import qrcode from 'qrcode-generator' import { hostLabel, largestFit, relativeTime } from './render' // The wire contract is defined once in the worker's parser. `import type` is @@ -411,15 +415,6 @@ interface FeedResponse { stage?.style.setProperty('--rotate-ms', `${rotateMs}ms`) } - // On a Screenly player the viewer is already a Screenly customer, so the - // promotional Screenly badge is removed. The 'screenly-viewer' token in the - // user agent marks these devices; every other browser keeps the badge. - const removeScreenlyBranding = (): void => { - if (navigator.userAgent.includes('screenly-viewer')) { - document.querySelector('.brand')?.remove() - } - } - const init = (): void => { removeScreenlyBranding() readConfig() diff --git a/assets/static/styles/main.css b/assets/static/styles/main.css index aaa6d54..a02dd30 100644 --- a/assets/static/styles/main.css +++ b/assets/static/styles/main.css @@ -10,43 +10,10 @@ orientations; the per-item fit is finished in main.ts. ========================================================================= */ -@font-face { - font-family: "Bricolage Grotesque"; - font-weight: 200 800; - font-style: normal; - font-optical-sizing: auto; - font-display: swap; - src: url("/static/fonts/bricolage-grotesque-latin-standard-normal.woff2") format("woff2"); - unicode-range: - U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -@font-face { - font-family: "Hanken Grotesk"; - font-weight: 100 900; - font-style: normal; - font-display: swap; - src: url("/static/fonts/hanken-grotesk-latin-wght-normal.woff2") format("woff2"); - unicode-range: - U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -@font-face { - font-family: "Space Mono"; - font-weight: 400; - font-style: normal; - font-display: swap; - src: url("/static/fonts/space-mono-latin-400-normal.woff2") format("woff2"); - unicode-range: - U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} -@font-face { - font-family: "Space Mono"; - font-weight: 700; - font-style: normal; - font-display: swap; - src: url("/static/fonts/space-mono-latin-700-normal.woff2") format("woff2"); - unicode-range: - U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} +/* Webfonts (@font-face) and the standardized footer badge (.brand) come from + @screenly-labs/signage-kit — build.ts prepends styles/fonts.css + styles/brand.css + to this file before down-leveling. This file keeps the app's own tokens, reset, + fluid root, and "The Wire" component styles. */ :root { --font-display: "Bricolage Grotesque", "Hanken Grotesk", system-ui, sans-serif; @@ -154,20 +121,6 @@ body { font-weight: 700; white-space: nowrap; } -.rail__brand { - flex: none; - display: flex; - align-items: center; - padding-inline-start: clamp(0.7rem, 2vmin, 1.6rem); - margin-inline-start: clamp(0.7rem, 2vmin, 1.6rem); - border-inline-start: 1px solid var(--hairline); - opacity: 0.85; -} -.rail__brand img { - block-size: clamp(0.7rem, 1vmin + 0.5rem, 1.4rem); - inline-size: auto; - display: block; -} /* Transmission line: a track on the rail's bottom edge that fills amber over each rotation interval (set in motion below). */ .rail__line { diff --git a/build.ts b/build.ts index 547d5dc..19e4f70 100644 --- a/build.ts +++ b/build.ts @@ -16,12 +16,21 @@ // CSS step (used by `bun run dev`, which only needs the JS bundle, so the // working-tree CSS stays unminified for editing). +import { readFileSync } from 'node:fs' import { Glob } from 'bun' import { bundleJs, processCss } from '@screenly-labs/signage-kit/build' import { run as syncFonts } from './sync-fonts' const clientOnly = process.argv.includes('--client') +// Shared chrome CSS from @screenly-labs/signage-kit — the canonical @font-face +// set and the standardized fixed footer badge. Prepended to this app's raw +// main.css at build time (a raw-CSS Worker can't resolve a bare `@import`), so +// the shared rules land before the app's, which override where they overlap. +const sharedCss = ['fonts.css', 'brand.css'] + .map((f) => readFileSync(Bun.resolveSync(`@screenly-labs/signage-kit/styles/${f}`, import.meta.dir), 'utf8')) + .join('\n') + // Vendor the Bun-managed webfonts into ./assets first. await syncFonts() @@ -47,7 +56,7 @@ console.log('✓ JS: assets/static/js/main.js (iife, es2017)') if (!clientOnly) { for await (const path of new Glob('assets/static/styles/*.css').scan('.')) { try { - const code = await processCss(await Bun.file(path).text(), { + const code = await processCss(`${sharedCss}\n${await Bun.file(path).text()}`, { includeDegraded: true, filename: path }) diff --git a/bun.lock b/bun.lock index dbdc82e..7cce354 100644 --- a/bun.lock +++ b/bun.lock @@ -5,10 +5,7 @@ "": { "name": "screenly-rss-reader", "dependencies": { - "@fontsource-variable/bricolage-grotesque": "^5.2.10", - "@fontsource-variable/hanken-grotesk": "^5.2.8", - "@fontsource/space-mono": "^5.2.9", - "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.0", + "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.2", "hono": "^4.12.27", "qrcode-generator": "^2.0.4", }, @@ -118,8 +115,14 @@ "@fontsource-variable/bricolage-grotesque": ["@fontsource-variable/bricolage-grotesque@5.2.10", "", {}, "sha512-5EDsCqgGpKVcJWE4sg9ydli+t5WM97mISYw5lla/Ev4z71FwXh1oN0YUU8xjkRW9+wBCGD9R+ntAvI8G4bUFJg=="], + "@fontsource-variable/fraunces": ["@fontsource-variable/fraunces@5.2.9", "", {}, "sha512-Y6IjunlN9Ni723np+GIgAaKzCDBrPRrqNi01TZxHs5wtHYROWFM9W6yiT+/gGwSjWIRD18oX17kD/BRWekc/Lw=="], + "@fontsource-variable/hanken-grotesk": ["@fontsource-variable/hanken-grotesk@5.2.8", "", {}, "sha512-K7hu09ZKReBc7EifRLeM4K94NZBrxFEg0nGcISmVwlFQOJo4EmYkLXTWEwr5JcNW4z2hr5zy8vLS2sxC8JDmrQ=="], + "@fontsource-variable/jetbrains-mono": ["@fontsource-variable/jetbrains-mono@5.2.8", "", {}, "sha512-WBA9elru6Jdp5df2mES55wuOO0WIrn3kpXnI4+W2ek5u3ZgLS9XS4gmIlcQhiZOWEKl95meYdvK7xI+ETLCq/Q=="], + + "@fontsource-variable/newsreader": ["@fontsource-variable/newsreader@5.2.10", "", {}, "sha512-MdI2iRwrqWpMOU/2aV2BgfZ4dJNlj/XlYaY8Zb7t87mWqHskYW0XiUANkt1cyOCiEfW2VQ0bQ5vZgGPp6B2B4w=="], + "@fontsource/space-mono": ["@fontsource/space-mono@5.2.9", "", {}, "sha512-b61faFOHEISQ/pD25G+cfGY9o/WW6lRv6hBQQfpWvEJ4y1V+S4gmth95EVyBE2VL3qDYHeVQ8nBzrplzdXTDDg=="], "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], @@ -184,7 +187,7 @@ "@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="], - "@screenly-labs/signage-kit": ["@screenly-labs/signage-kit@github:Screenly-Labs/signage-kit#eb470fb", { "peerDependencies": { "@csstools/postcss-cascade-layers": "^6", "browserslist": "^4", "esbuild": "^0.28", "lightningcss": "^1.32", "postcss": "^8" }, "optionalPeers": ["@csstools/postcss-cascade-layers", "postcss"] }, "Screenly-Labs-signage-kit-eb470fb", "sha512-acuAb2R/77crUjgnT9GFVlNdpgUTzvK5OLRRsZsZ30dZcJ7ThH/f8al2janEIJWC1JoyqTiarJ2x1uAH6In86A=="], + "@screenly-labs/signage-kit": ["@screenly-labs/signage-kit@github:Screenly-Labs/signage-kit#b7f3d44", { "dependencies": { "@fontsource-variable/bricolage-grotesque": "^5.2.10", "@fontsource-variable/fraunces": "^5.2.9", "@fontsource-variable/hanken-grotesk": "^5.2.8", "@fontsource-variable/jetbrains-mono": "^5.2.8", "@fontsource-variable/newsreader": "^5.2.10", "@fontsource/space-mono": "^5.2.9" }, "peerDependencies": { "@csstools/postcss-cascade-layers": "^6", "browserslist": "^4", "esbuild": "^0.28", "lightningcss": "^1.32", "postcss": "^8" }, "optionalPeers": ["@csstools/postcss-cascade-layers", "postcss"] }, "Screenly-Labs-signage-kit-b7f3d44", "sha512-42YdnSCPpYpTyMucl1T+FGv3HQeyzz2UDEvYoLdP4EMVAD1m0U1G8WN2hgTE4vFVs3w8hGcqFisWBjkEc26rFA=="], "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], diff --git a/package.json b/package.json index f0d7e96..69646cc 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,7 @@ }, "license": "AGPL-3.0-only", "dependencies": { - "@fontsource-variable/bricolage-grotesque": "^5.2.10", - "@fontsource-variable/hanken-grotesk": "^5.2.8", - "@fontsource/space-mono": "^5.2.9", - "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.0", + "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.2", "hono": "^4.12.27", "qrcode-generator": "^2.0.4" }, diff --git a/src/components/App.tsx b/src/components/App.tsx index 654c04b..8a125cf 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -30,7 +30,7 @@ const App = ({ env, feedId, feedTitle, v }: AppProps) => {