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
42 changes: 4 additions & 38 deletions assets/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@ body {
}

.masthead,
.grid,
.brand {
.grid {
position: relative;
z-index: 2;
}
Expand Down Expand Up @@ -201,39 +200,8 @@ body {
text-shadow: 0 1px 3px rgb(0 0 0 / 0.55);
}

/* =========================================================================
Brand footer — quiet Screenly lockup in the corner
========================================================================= */
.brand {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 0.7em;
padding-block-start: clamp(0.4rem, 1.2vmin, 0.9rem);
border-block-start: 1px solid var(--hairline);
}

.brand-by {
font-size: max(10px, 0.6rem);
text-transform: uppercase;
letter-spacing: 0.22em;
color: var(--ink-dim);
text-shadow: 0 1px 3px rgb(0 0 0 / 0.55);
}

.brand-logo {
block-size: max(14px, 0.95rem);
inline-size: auto;
filter: drop-shadow(0 0.05em 0.4em rgb(0 0 0 / 0.45));
}

.brand-url {
font-size: max(10px, 0.6rem);
text-transform: uppercase;
letter-spacing: 0.22em;
color: var(--ink-dim);
text-shadow: 0 1px 3px rgb(0 0 0 / 0.55);
}
/* The footer Screenly badge is the kit's standardized fixed corner .brand
(prepended from styles/brand.css); no app-specific badge rules needed. */

/* =========================================================================
Grid of city cards
Expand Down Expand Up @@ -464,9 +432,7 @@ body {
/* Very small displays (Pi touch 480x800 / 800x480): tighten the masthead so
the grid keeps the most room. */
@media (max-height: 500px), (max-width: 540px) {
.masthead-meta,
.brand-by,
.brand-url {
.masthead-meta {
display: none;
}
}
Expand Down
13 changes: 12 additions & 1 deletion build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,23 @@
// site works unchanged whether it is served from a domain root or from a
// project subpath like https://<org>.github.io/world-clock/.

import { readFileSync } from 'node:fs'
import { cp, mkdir, rm } from 'node:fs/promises'
import { bundleJs, injectGate, processCss } from '@screenly-labs/signage-kit/build'
import { run as syncFonts } from './sync-fonts.ts'

const DIST = 'dist'

// The standardized fixed footer badge from @screenly-labs/signage-kit, prepended
// to this app's main.css. Only brand.css (not the kit's fonts.css): this app uses
// RELATIVE asset paths (../fonts/...) for Pages-subpath portability, while the
// kit's fonts.css hard-codes /static/fonts/, so this app keeps its own relative
// @font-face and only shares the path-agnostic badge rules.
const brandCss = readFileSync(
Bun.resolveSync('@screenly-labs/signage-kit/styles/brand.css', import.meta.dir),
'utf8'
)

// Vendor the Bun-managed webfonts into ./assets/fonts before copying them on.
await syncFonts()

Expand All @@ -34,7 +45,7 @@ try {
console.log(`✓ JS: ${DIST}/main.js`)

try {
const css = await processCss(await Bun.file('assets/styles/main.css').text(), {
const css = await processCss(`${brandCss}\n${await Bun.file('assets/styles/main.css').text()}`, {
includeDegraded: true,
filename: 'assets/styles/main.css'
})
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.

20 changes: 9 additions & 11 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,15 @@
<span class="masthead-meta" id="masthead-meta"></span>
</header>
<main class="grid" id="grid" aria-live="off"></main>
<footer class="brand">
<span class="brand-by">Powered by</span>
<img
class="brand-logo"
src="./images/screenly-logo.svg"
alt="Screenly"
width="1649"
height="371"
/>
<span class="brand-url">screenly.io</span>
</footer>
<a
class="brand"
href="https://www.screenly.io"
target="_blank"
rel="noopener noreferrer"
aria-label="Screenly - opens in a new tab"
>
<img src="./images/screenly-logo.svg" alt="Screenly" />
</a>
</div>
</body>
</html>
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,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
10 changes: 1 addition & 9 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// Side-effect import: installs the replaceChildren shim for the older-browser
// degraded mode (shared across all apps). Must stay first.
import '@screenly-labs/signage-kit/polyfills'
import { removeScreenlyBranding } from '@screenly-labs/signage-kit/branding'
import {
buildFormatters,
type ClockConfig,
Expand Down Expand Up @@ -166,15 +167,6 @@ const layoutGrid = (grid: HTMLElement, cards: ClockCard[]): void => {
}
}

// 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 start = (): void => {
removeScreenlyBranding()
const config = parseClocks(window.location.search)
Expand Down
39 changes: 6 additions & 33 deletions sync-fonts.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,13 @@
#!/usr/bin/env bun
// Copies the self-hosted webfont files out of the Bun-managed @fontsource
// packages into ./assets/fonts, where the build picks them up and ships them to
// ./fonts in the static site. Bun owns the font versions (package.json); this
// step vendors the exact files we serve ourselves — no CDN.
//
// Fonts: Fraunces (display serif, "standard" axis = opsz + wght, normal +
// italic) for the time; Hanken Grotesk for metadata.
// Vendor this app's webfonts into ./assets/fonts. The files, versions, and copy
// logic all live in @screenly-labs/signage-kit — this just names the families
// the board uses (Fraunces time digits + Hanken Grotesk chrome) and the dest
// dir (this app keeps a relative ../fonts/ layout, not /static/fonts).

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/fonts'
import { syncFonts } from '@screenly-labs/signage-kit/sync-fonts'

export const run = async (): Promise<void> => {
let count = 0
export const run = (): Promise<number> => syncFonts(['fraunces', 'hanken-grotesk'], 'assets/fonts')

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.ts`.
if (import.meta.main) {
await run()
}
Loading