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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions assets/static/js/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Side-effect import: installs the replaceChildren shim for the older-browser
// degraded mode. Must stay first so the shim is in place before any render.
import '@screenly-labs/signage-kit/polyfills'
import { removeScreenlyBranding } from '@screenly-labs/signage-kit/branding'
import { isQuote, pickRandomIndex, type Quote } from './quotes'

// Shown if the quotes file can't be fetched or is empty, so the screen is never
Expand Down Expand Up @@ -40,15 +41,6 @@ const loadQuote = async (): Promise<Quote> => {
}
}

// 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()
loadQuote().then(render)
Expand Down
82 changes: 16 additions & 66 deletions assets/static/styles/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,34 @@
========================================================================= */

@import 'tailwindcss';
/* Shared base (brand tokens + fluid root + the degraded-mode kill-switch) from
@screenly-labs/signage-kit. The app's own @theme + component styles below layer
on top; the design identity stays here, per-app. */
/* Shared base (brand/font tokens + fluid root + the degraded-mode kill-switch),
the canonical @font-face set, the standardized footer badge, and the .stage
frame — all from @screenly-labs/signage-kit. The app's own @theme + component
styles below layer on top; the design identity stays here, per-app. */
@import '@screenly-labs/signage-kit/styles/preset.css';
@import '@screenly-labs/signage-kit/styles/fonts.css';
@import '@screenly-labs/signage-kit/styles/brand.css';
@import '@screenly-labs/signage-kit/styles/stage.css';

/* Design tokens — also generate utilities (bg-ink, text-gilt, font-display…). */
/* Design tokens — also generate utilities (bg-ink, text-gilt…). The font
families (--font-display: Fraunces, --font-sans: Hanken Grotesk) come from the
kit preset; override here only to diverge. */
@theme {
--color-ink: #16140f;
--color-paper: #f1ece0;
--color-paper-dim: #b7b0a0;
--color-watermark: #2a2519;
--color-gilt: #c9a24b;
--font-display: 'Fraunces', ui-serif, Georgia, 'Times New Roman', serif;
--font-sans: 'Hanken Grotesk', ui-sans-serif, system-ui, sans-serif;
}

/* Webfonts: self-hosted, vendored from Bun-managed @fontsource (sync-fonts.js).
Variable "standard" axis = optical-size + weight. */
@font-face {
font-family: 'Fraunces';
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url('/static/fonts/fraunces-latin-standard-normal.woff2') format('woff2');
}
@font-face {
font-family: 'Fraunces';
font-style: italic;
font-weight: 100 900;
font-display: swap;
src: url('/static/fonts/fraunces-latin-standard-italic.woff2') format('woff2');
}
@font-face {
font-family: 'Hanken Grotesk';
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url('/static/fonts/hanken-grotesk-latin-wght-normal.woff2') format('woff2');
}

@layer base {
/* One fluid root drives the whole scale; vw+vh keeps it orientation-neutral
so portrait and landscape resolve to the same type size. Children size in
rem, so the layout scales cleanly from 480px → 4K with no breakpoints. */
/* Tune the kit's fluid root (clamp of vw+vh) for this design; the clamp itself
lives in the preset. Children size in rem, so the layout scales cleanly from
480px → 4K, portrait and landscape, with no breakpoints. */
:root {
font-size: clamp(17px, 1.05vw + 1.05vh, 56px);
--root-min: 17px;
--root-gain: 1.05;
--root-max: 56px;
}

body {
Expand All @@ -68,16 +50,6 @@
}

@layer components {
.stage {
position: relative;
display: grid;
place-items: center;
min-height: 100vh; /* fallback for engines below the svh floor (~2018 players) */
min-height: 100svh;
padding: clamp(1.5rem, 6vmin, 4rem);
overflow: hidden;
}

.quote {
position: relative;
margin: 0;
Expand Down Expand Up @@ -146,28 +118,6 @@
text-transform: uppercase;
color: var(--color-gilt);
}

.brand {
position: fixed;
right: clamp(1rem, 3.2vmin, 2.4rem);
bottom: clamp(1rem, 3.2vmin, 2.4rem);
display: block;
opacity: 0.55;
transition: opacity 200ms ease;
border-radius: 4px;
outline-offset: 6px;
}

.brand:hover,
.brand:focus-visible {
opacity: 0.95;
}

.brand img {
display: block;
width: auto;
height: clamp(13px, 1.3rem, 26px);
}
}

@layer base {
Expand Down
14 changes: 10 additions & 4 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
},
"license": "AGPL-3.0-only",
"dependencies": {
"@fontsource-variable/fraunces": "^5.2.9",
"@fontsource-variable/hanken-grotesk": "^5.2.8",
"@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.0"
"@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.2"
},
"devDependencies": {
"@biomejs/biome": "^2.5.1",
Expand Down
39 changes: 5 additions & 34 deletions sync-fonts.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,12 @@
#!/usr/bin/env bun
/* global Bun */
// Copies the self-hosted webfont files out of the Bun-managed @fontsource
// packages and into ./assets/static/fonts, where they're shipped to /static/fonts/.
// Bun owns the font versions (package.json); this step vendors the exact files we
// serve ourselves — no CDN at runtime.
//
// Fonts: Fraunces (display serif, "standard" axis = opsz + wght, normal + italic)
// for the quote; Hanken Grotesk for the attribution byline.
// Vendor this app's webfonts into ./assets/static/fonts. The files, versions,
// and copy logic all live in @screenly-labs/signage-kit — this just names the
// families the "Reading room" design uses (Fraunces display + Hanken Grotesk).

const FONTS = [
'@fontsource-variable/fraunces/files/fraunces-latin-standard-normal.woff2',
'@fontsource-variable/fraunces/files/fraunces-latin-standard-italic.woff2',
'@fontsource-variable/hanken-grotesk/files/hanken-grotesk-latin-wght-normal.woff2'
]
const DEST_DIR = 'assets/static/fonts'
import { syncFonts } from '@screenly-labs/signage-kit/sync-fonts'

export const run = async () => {
let count = 0
export const run = () => syncFonts(['fraunces', 'hanken-grotesk'])

for (const rel of FONTS) {
const file = rel.split('/').pop()
const src = Bun.file(`node_modules/${rel}`)

if (!(await src.exists())) {
console.error(`✗ Missing ${file} — run \`bun install\` first.`)
process.exit(1)
}

await Bun.write(`${DEST_DIR}/${file}`, src)
console.log(`✓ Font: ${DEST_DIR}/${file}`)
count++
}

console.log(`Fonts synced — ${count} file(s) vendored from @fontsource.`)
}

// Allow running standalone: `bun run sync-fonts.js`
if (import.meta.main) {
await run()
}
Loading