From 40d67d97867200ba0a2e57d2e2b25a81b10002b1 Mon Sep 17 00:00:00 2001 From: Cyborg Viktor <307551610+vpetersson-bot@users.noreply.github.com> Date: Wed, 5 Aug 2026 18:44:56 +0000 Subject: [PATCH] Correct the deploy docs and drop the remaining em dashes Two doc/copy cleanups, no behaviour change. CLAUDE.md and README.md both claimed a push to master deploys to Pages. It does not: deploy-pages.yml triggers on a CalVer tag (or a manual workflow_dispatch), so master on its own ships nothing. Both now say so. Also removes the remaining em dashes (27 across CLAUDE.md, README.md, the two TS entry points, tailwind.css, build.js and sync-fonts.js), rewriting each to a colon, semicolon, comma or parenthetical as the sentence needs rather than swapping the character blindly. The manifest and meta description were already done in #14. typecheck, lint, test (28 pass) and build all clean. --- CLAUDE.md | 26 ++++++++++++++------------ README.md | 16 +++++++++------- assets/static/js/main.ts | 4 ++-- assets/static/js/timer.ts | 4 ++-- assets/static/styles/tailwind.css | 14 +++++++------- build.js | 2 +- sync-fonts.js | 2 +- 7 files changed, 36 insertions(+), 32 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8304abd..ea1830b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,14 +12,14 @@ settings apps). There is **no server**; the clock ticks entirely in the browser. Like Opening Hours, this is a **settings** app: the target isn't baked in, it arrives in the launch URL's query string (`?title=…&target=…&tz=…&message=…`). -**Direction is automatic** — a future target counts down, a past one counts up; +**Direction is automatic**: a future target counts down, a past one counts up; there is no mode setting. Single self-ticking page (a `setTimeout` loop aligned to the wall-clock second); the player reloads on its own schedule. ## Stack & conventions - **Bun** for everything (package manager, bundler, test runner). Use `bun` / - `bunx` — never npm/npx. + `bunx`, never npm/npx. - **TypeScript**, strict. All browser JS is authored as `.ts` and bundled by Bun. - **Tailwind CSS v4**, CSS-first: tokens live in `@theme` in `assets/static/styles/tailwind.css`; compiled by `@tailwindcss/cli` at build. @@ -32,7 +32,7 @@ to the wall-clock second); the player reloads on its own schedule. bun install # deps; vendored fonts come from @fontsource via sync-fonts bun run dev # build + serve dist/ locally bun run build # assemble dist/ (see below) -bun test # bun:test — date math + manifest validation +bun test # bun:test for date math + manifest validation bun run typecheck # tsc --noEmit bun run lint # biome lint --error-on-warnings ``` @@ -42,17 +42,17 @@ bun run lint # biome lint --error-on-warnings Web root is served from the site root (custom domain), so assets are referenced absolutely as `/static/...`. -- `index.html` — the page shell. Ships a worked example inline (New Year) so the +- `index.html`: the page shell. Ships a worked example inline (New Year) so the screen is never blank pre-JS or in the store preview. Asset URLs carry `?v=__ASSET_VERSION__`, replaced at build. -- `assets/static/js/timer.ts` — **pure, exported, unit-tested** helpers and types +- `assets/static/js/timer.ts`: **pure, exported, unit-tested** helpers and types (`parseTarget`, `tzOffsetMs`, `computeState`, `splitDuration`, `pad2`). This is where the date/time-zone math lives; keep it framework-free and side-effect-free. -- `assets/static/js/main.ts` — the browser **entry**. Reads the query string, +- `assets/static/js/main.ts`: the browser **entry**. Reads the query string, resolves the target once, and ticks the four units + direction + target line + message on a second-aligned loop. Keep it **export-free** and free of top-level `await`. -- `.well-known/signage-app.json` — the app-store manifest (settings schema + +- `.well-known/signage-app.json`: the app-store manifest (settings schema + launch template). `test/manifest.test.ts` validates it. `build.js` builds into `dist/` **without mutating sources**: vendor fonts → copy @@ -69,9 +69,9 @@ minify the TS → stamp a sha256 content hash into `?v=` URLs → write `CNAME` two-pass `tzOffsetMs` (via `Intl` tz data) that stays correct across DST. `tzOffsetMs` uses `Intl.DateTimeFormat` with an explicit `timeZone`, so results -don't depend on the host's local zone — the unit tests assert exact UTC instants. +don't depend on the host's local zone; the unit tests assert exact UTC instants. -## Design — "Countdown" +## Design: "Countdown" Big tabular Bricolage Grotesque numerals over a graphite ground with one mint accent; four labelled units on a row (wrapping to 2×2 when narrow), the title @@ -93,6 +93,8 @@ reduced-motion gating beyond the one-off entrance. ## Deploy -Push to **`master`** → `.github/workflows/deploy-pages.yml` builds and publishes -to Pages. PRs run `ci.yml` (typecheck + lint + test + build). Action versions are -SHA-pinned. +Deploys are **tag-driven**: pushing a CalVer tag (`YYYY.M.PATCH`, e.g. +`2026.8.0`) runs `.github/workflows/deploy-pages.yml`, which builds and publishes +to Pages; it also accepts `workflow_dispatch`. Pushing to `master` on its own +does **not** deploy. PRs run `ci.yml` (typecheck + lint + test + build). Action +versions are SHA-pinned. diff --git a/README.md b/README.md index aaf1520..a791d13 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Screenly Timer App A full-screen **countdown / count-up** timer for digital signage. It ticks the -days, hours, minutes and seconds to a target instant — then keeps going and +days, hours, minutes and seconds to a target instant, then keeps going and counts **up** the elapsed time once the target passes. The same screen handles a launch countdown *and* a "days since" board. Big tabular Bricolage Grotesque numerals over a graphite ground with a single mint accent. @@ -12,7 +12,7 @@ Live: **https://timer.srly.io** Part of the Screenly signage family alongside the [quotes](../quotes), [opening-hours](../opening-hours) and [world-clock](../world-clock) apps. Like -Quotes, this is a fully **static** site hosted on **GitHub Pages** — there's no +Quotes, this is a fully **static** site hosted on **GitHub Pages**; there's no server; the clock ticks entirely in the browser. Like Opening Hours it takes **settings**: the target arrives in the launch URL's query string, so one deployment times any event. @@ -33,7 +33,7 @@ https://timer.srly.io/?title=Product+Launch&target=2026-12-31T23:59:59&tz=Europe | `message` | Optional line shown once the target is reached (during count-up), e.g. `Happy New Year!`. | Opened with no parameters (e.g. the store preview), it counts down to a worked -example so the screen is never blank. There's no data to refresh — it's a single +example so the screen is never blank. There's no data to refresh; it's a single self-ticking page. ## Direction is automatic @@ -67,7 +67,7 @@ Requires [Bun](https://bun.sh). Never npm/npx. bun install # deps; vendored fonts come from @fontsource via sync-fonts bun run dev # build + serve dist/ locally bun run build # assemble dist/ for GitHub Pages -bun test # bun:test — date math + manifest validation +bun test # bun:test for date math + manifest validation bun run typecheck bun run lint ``` @@ -80,9 +80,11 @@ bun run lint write `CNAME` (`timer.srly.io`). `dist/` is gitignored and is the artifact GitHub Pages publishes. -Push to **`master`** and `.github/workflows/deploy-pages.yml` builds and deploys -to Pages. Pull requests run `ci.yml` (typecheck + lint + test + build). Action -versions are SHA-pinned. +Deploys are **tag-driven**: pushing a CalVer tag (`YYYY.M.PATCH`, e.g. +`2026.8.0`) runs `.github/workflows/deploy-pages.yml`, which builds and deploys +to Pages; it also accepts `workflow_dispatch`. Pushing to **`master`** on its own +does **not** deploy. Pull requests run `ci.yml` (typecheck + lint + test + +build). Action versions are SHA-pinned. ## Licence diff --git a/assets/static/js/main.ts b/assets/static/js/main.ts index 380586d..06eeff4 100644 --- a/assets/static/js/main.ts +++ b/assets/static/js/main.ts @@ -61,7 +61,7 @@ const targetLabel = targetMs === null ? '' : formatTarget(targetMs, tz) document.title = title === 'Countdown' ? 'Timer' : `${title} | Timer` -// Paint one frame from the current clock. Returns nothing — it's called on a +// Paint one frame from the current clock. Returns nothing; it's called on a // timer. When the target can't be parsed we show a dashed placeholder and stop. const paint = (): void => { if (targetMs === null) { @@ -97,7 +97,7 @@ const render = (): void => { setLine('target-line', 'Set a target date to start the timer.') } else { // Report once per load whether this timer is counting down to a future - // target or up from a past one — the page reloads periodically, so each + // target or up from a past one; the page reloads periodically, so each // load re-reports the current mode. const { direction } = computeState(targetMs, Date.now()) track('timer_direction', { direction: direction === 'down' ? 'countdown' : 'countup' }) diff --git a/assets/static/js/timer.ts b/assets/static/js/timer.ts index bdcbe36..52aa9a1 100644 --- a/assets/static/js/timer.ts +++ b/assets/static/js/timer.ts @@ -2,7 +2,7 @@ // they can be unit-tested with `bun:test`; main.ts is the (untestable, no-exports) // browser entry that wires these into the DOM and ticks the clock. // -// The app takes no dataset — a single timer is described entirely by the launch +// The app takes no dataset; a single timer is described entirely by the launch // URL's query string (see .well-known/signage-app.json): a target instant, plus // an optional title, time zone, and message. Direction is automatic: a future // target counts down; once it passes (or a past target) it counts up the elapsed @@ -44,7 +44,7 @@ export const computeState = (targetMs: number, nowMs: number): TimerState => { } } -// The offset, in ms, of a named IANA time zone at a given instant — i.e. how far +// The offset, in ms, of a named IANA time zone at a given instant, i.e. how far // that zone's wall-clock is ahead of UTC (e.g. +3600000 for CET in winter). Uses // the Intl tz database, which is always available, so results don't depend on the // host's local zone. Returns 0 for an unknown/empty zone (treated as UTC). diff --git a/assets/static/styles/tailwind.css b/assets/static/styles/tailwind.css index fc90930..331b900 100644 --- a/assets/static/styles/tailwind.css +++ b/assets/static/styles/tailwind.css @@ -1,24 +1,24 @@ /* ========================================================================= - Screenly Timer App — "Countdown" - Big ticking days / hours / minutes / seconds counting down to — or up from — + Screenly Timer App: "Countdown" + Big ticking days / hours / minutes / seconds counting down to, or up from, a target instant, set in a tabular Bricolage Grotesque over a graphite ground with a single mint accent. The clock is the hero: four labelled numerals on a row, an event title above and the target date below. Tuned for unattended - signage — legible at distance, no interaction, both orientations. The seconds + signage: legible at distance, no interaction, both orientations. The seconds flip is the only motion, so there's nothing to gate for reduced-motion. ========================================================================= */ @import 'tailwindcss'; /* 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 + 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-mint, font-display…). +/* Design tokens; also generate utilities (bg-ink, text-mint, font-display…). --font-sans (Hanken Grotesk) comes from the kit preset; --font-display is overridden to Bricolage Grotesque, this app's grotesque display face. */ @theme { @@ -187,9 +187,9 @@ } /* ========================================================================= - Degraded mode — old/weak signage players (html.legacy set by the shared gate). + Degraded mode: old/weak signage players (html.legacy set by the shared gate). The generic kill-switch (drops animation/transition/will-change) now comes from the kit's preset, imported above. The clock ticks in JS and the only CSS motion - is the one-off .timer entrance, which the kill-switch already disables — there's + is the one-off .timer entrance, which the kill-switch already disables, so there's no animated resting state to hold, so this app needs no extra html.legacy rule. ========================================================================= */ diff --git a/build.js b/build.js index e3c90c0..7033a2b 100644 --- a/build.js +++ b/build.js @@ -1,7 +1,7 @@ #!/usr/bin/env bun /* global Bun */ // Builds the static site into ./dist for GitHub Pages. Like the Quotes and -// Opening Hours apps this is a plain static bundle — no server. The timer has no +// Opening Hours apps this is a plain static bundle, no server. The timer has no // dataset: the title and target arrive entirely in the launch URL's query string // (see the manifest at .well-known/signage-app.json), and the clock ticks live in // the browser. Steps: diff --git a/sync-fonts.js b/sync-fonts.js index 0362a9e..12e9260 100644 --- a/sync-fonts.js +++ b/sync-fonts.js @@ -1,6 +1,6 @@ #!/usr/bin/env bun // 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 +// and copy logic all live in @screenly-labs/signage-kit; this just names the // families the "Countdown" design uses (Bricolage Grotesque display + Hanken // Grotesk for the labels and target line).