ultimate-jekyll-manager 1.7.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -1
- package/CLAUDE.md +36 -15
- package/README.md +4 -2
- package/TODO-AUTH-TESTING.md +1 -1
- package/dist/assets/themes/newsflash/README.md +58 -0
- package/dist/assets/themes/newsflash/_config.scss +138 -0
- package/dist/assets/themes/newsflash/_theme.js +27 -0
- package/dist/assets/themes/newsflash/_theme.scss +37 -0
- package/dist/assets/themes/newsflash/css/base/_mixins.scss +50 -0
- package/dist/assets/themes/newsflash/css/base/_root.scss +134 -0
- package/dist/assets/themes/newsflash/css/base/_typography.scss +49 -0
- package/dist/assets/themes/newsflash/css/base/_utilities.scss +58 -0
- package/dist/assets/themes/newsflash/css/components/_badges.scss +65 -0
- package/dist/assets/themes/newsflash/css/components/_buttons.scss +139 -0
- package/dist/assets/themes/newsflash/css/components/_cards.scss +52 -0
- package/dist/assets/themes/newsflash/css/components/_editorial.scss +182 -0
- package/dist/assets/themes/newsflash/css/components/_forms.scss +75 -0
- package/dist/assets/themes/newsflash/css/components/_infinite-scroll.scss +102 -0
- package/dist/assets/themes/newsflash/css/components/_panels.scss +91 -0
- package/dist/assets/themes/newsflash/css/components/_ticker.scss +70 -0
- package/dist/assets/themes/newsflash/css/layout/_general.scss +264 -0
- package/dist/assets/themes/newsflash/css/layout/_navigation.scss +164 -0
- package/dist/assets/themes/newsflash/js/initialize-tooltips.js +20 -0
- package/dist/assets/themes/newsflash/js/masthead-scroll.js +29 -0
- package/dist/assets/themes/newsflash/pages/404/index.scss +27 -0
- package/dist/assets/themes/newsflash/pages/about/index.scss +70 -0
- package/dist/assets/themes/newsflash/pages/blog/index.scss +17 -0
- package/dist/assets/themes/newsflash/pages/blog/post.js +29 -0
- package/dist/assets/themes/newsflash/pages/blog/post.scss +164 -0
- package/dist/assets/themes/newsflash/pages/index.scss +159 -0
- package/dist/assets/themes/newsflash/pages/pricing/index.scss +194 -0
- package/dist/assets/themes/newsflash/pages/test/libraries/layers/index.js +9 -0
- package/dist/assets/themes/newsflash/pages/test/libraries/layers/index.scss +7 -0
- package/dist/commands/blogify.js +6 -3
- package/dist/commands/test.js +34 -5
- package/dist/defaults/CLAUDE.md +17 -4
- package/dist/defaults/dist/_includes/core/pricing/resolve-plan.html +59 -0
- package/dist/defaults/dist/_includes/themes/classy/frontend/sections/footer.html +20 -3
- package/dist/defaults/dist/_layouts/themes/classy/admin/core/minimal-viewport-locked.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/admin/core/minimal.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html +5 -40
- package/dist/defaults/dist/_layouts/themes/neobrutalism/frontend/pages/pricing.html +33 -34
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/core/base.html +61 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/404.html +86 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/about.html +353 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/categories/category.html +105 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/categories/index.html +93 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/index.html +373 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/post.html +289 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/tags/index.html +90 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/tags/tag.html +107 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/contact.html +340 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/index.html +522 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/pricing.html +485 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/team/index.html +207 -0
- package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/team/member.html +134 -0
- package/dist/defaults/test/README.md +4 -0
- package/dist/gulp/tasks/jekyll.js +4 -2
- package/dist/test/runner.js +50 -3
- package/dist/test/suites/build/attach-log-file.test.js +102 -0
- package/dist/test/suites/build/theme-contract.test.js +173 -0
- package/dist/test/utils/extended-mode-warning.js +13 -0
- package/dist/utils/attach-log-file.js +70 -43
- package/docs/appearance.md +1 -0
- package/docs/assets.md +9 -0
- package/docs/audit.md +78 -7
- package/docs/build-system.md +57 -0
- package/docs/common-mistakes.md +15 -0
- package/docs/{project-structure.md → directory-structure.md} +1 -1
- package/docs/environment-detection.md +1 -1
- package/docs/javascript-libraries.md +38 -1
- package/docs/layouts-and-pages.md +146 -0
- package/docs/local-development.md +1 -8
- package/docs/logging.md +30 -0
- package/docs/migration.md +131 -0
- package/docs/no-inline-scripts.md +304 -0
- package/docs/purgecss.md +164 -0
- package/docs/seo.md +131 -4
- package/docs/templating.md +23 -0
- package/docs/test-boot-layer.md +1 -1
- package/docs/test-framework.md +56 -8
- package/docs/themes.md +254 -13
- package/logs/test.log +111 -0
- package/package.json +9 -8
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,70 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
14
14
|
- `Fixed` for any bug fixes.
|
|
15
15
|
- `Security` in case of vulnerabilities.
|
|
16
16
|
|
|
17
|
+
---
|
|
18
|
+
## [1.8.1] - 2026-06-11
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **`docs/audit.md` rewritten as the full-audit check catalog (`/omega:ujm audit`).** The two-stage site audit became an ID'd catalog: mirrored universal checks (U-01..U-14 — tests at every layer, XSS, secrets, config canon, doc parity, dead code, dep health, …), UJM-specific checks (UJM-01..UJM-10 — inline-script ban, theme-prefixed classes, content writing rules, SEO meta, purge safelist, reads-vs-writes, page-module pattern, images, a11y), and framework-repo checks (F-01..F-04 — sister parity, defaults sync, docs completeness, green framework suite), with scope auto-detect (consumer vs framework via package.json), a persisted findings report (`.temp/audit/claude-audit.md`), a severity-ordered TodoWrite fix loop, and the `npx mgr audit` automated stage absorbed from the old doc. Wired to the `omega:ujm` router's Audit process; `docs/audit.md` is mirrored across BEM/BXM/EM. CLAUDE.md's docs index updated to match.
|
|
23
|
+
- **package.json `keywords` corrected** — replaced the stale template list (`Autoprefixer`, `imagemin` — not used; `Browsersync` — true but noise) with accurate, discovery-oriented ones (`jekyll`, `static-site`, `static-site-generator`, `website`, `seo`, `gulp`, `sass`, `webpack`, `postcss`). npm-listing metadata only; no behavior change. Mirrored across BEM/BXM/EM.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
## [1.8.0] - 2026-06-11
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **`docs/migration.md` + expanded `docs/audit.md` + dashboard-pages pattern (action-skill consolidation).** The standalone `UJM:migrate`/`UJM:audit`/`UJM:new-page`/`UJM:new-site` skills were deleted and folded into `omega:ujm` as process checklists; their framework facts landed in the repo: new `docs/migration.md` (full old-UJ→UJM migration incl. `_legacy/` flow + config re-mapping, `_config.yml` quick-fix key schema, revert-posts procedure), `docs/audit.md` expanded to the full two-stage workflow (AI content pass → `npx mgr audit` fix loop), and `docs/layouts-and-pages.md` gained the dashboard list/detail/edit page pattern (separate pages, `?id=` redirects, breadcrumbs).
|
|
31
|
+
- **Dev-process guidance relaxed: only `npm start` is off-limits.** The "NEVER run" rule in CLAUDE.md + `src/defaults/CLAUDE.md` now prohibits only the long-running dev server (instruct the user to start it if it isn't running; read `logs/*.log`, never tail the process) — `npx mgr test` and `npm run build` are fine to run.
|
|
32
|
+
- **Skills-as-routers migration — `docs/no-inline-scripts.md` + `docs/purgecss.md` (new), plus `seo.md` / `layouts-and-pages.md` / `javascript-libraries.md` / `assets.md` extensions.** Framework facts migrated from the `omega:ujm` skill into the repo so they version-match the installed package: `no-inline-scripts.md` carries the full hard-rule playbook (where scripts move, Liquid `data-*`/`<template>`/conditional bridges, window-global callbacks, step-by-step migration, verification grep); `purgecss.md` carries the safelist playbook (two locations, RegExp anchoring, `variables: false` gotcha, per-file processing, current UJM safelist, category guide); `seo.md` retitled "SEO & Content" and gains the content writing rules (action-verb H1s, sentence case, headline/accent structure, frontmatter SEO, superheadline rules) + Services and Solutions page strategies + alternatives content guidelines; `layouts-and-pages.md` gains default-page customization rules (.md vs .html, page exclusions), the per-page customization-levels table (homepage/pricing/about/contact/download incl. hero display modes, pricing feature comments, testimonial/FAQ guidelines), and the custom-page creation checklist; `javascript-libraries.md` gains the reads-vs-writes rule (Firestore SDK for dashboard reads, Cloud Functions for writes) + Firestore read examples; `assets.md` gains the account-dropdown item field reference. The `data-wm-bind` deep reference moved to `web-manager/docs/bindings.md` (the module that owns the feature). All indexed in CLAUDE.md; the skill is now a thin router (pointers + hard rules + process checklists).
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **Router skill renamed `UJM:patterns` → `omega:ujm`** — all framework skills now live under the `omega:` namespace (`omega:em`/`omega:bxm`/`omega:ujm`/`omega:bem` + the `omega:main` hub). CLAUDE.md's Recommended skills section updated.
|
|
37
|
+
- **newsflash homepage post slots are strictly deduplicated.** Each section consumes its own slice of `site.posts` so no story repeats down the page: hero = post 1, top stories = 2–4, "the latest" feed = 5–9, most-read rail = 10–14, "more to chew on" = 15–17 (only the ticker repeats the latest — it's chrome, not content). Sections disappear gracefully when the site doesn't have enough posts to fill their slice.
|
|
38
|
+
- **Dev builds raise `--limit_posts` from 15 to 18** so a fully-populated newsflash front page (17 distinct posts) is visible during development (`--all-posts` still disables the cap entirely).
|
|
39
|
+
- **Footer appearance picker is now icon-only.** The toggle button in classy's and newsflash's footers shows just the mode icon (`data-appearance-icon` spans) — the `data-appearance-current` text label was removed from the button (the mode words remain in the dropdown items). Pure HTML change; the framework `data-appearance-*` logic is untouched. Docs updated in [docs/themes.md](docs/themes.md#the-appearance-picker-is-required-in-every-footer) + [docs/appearance.md](docs/appearance.md).
|
|
40
|
+
- **newsflash homepage desk cards link to their category pages.** Each desk card is now a story-card link (`href` per item, falling back to the slugified title → `/blog/categories/<slug>`) with a "Read the desk" affordance.
|
|
41
|
+
- **newsflash testimonials moved from the homepage to the about page.** The "From our readers" quote-card section (universal `testimonials` key) now lives on about between the principles and the team CTA; the `.quote-card` styles moved from the homepage page CSS to the about page CSS.
|
|
42
|
+
- **newsflash nav + footer include forks deleted — chrome now inherits from classy.** The nav fork was a verbatim copy of classy's (the fallback regenerates an identical file); the footer's editorial look (oversized serif wordmark, hidden avatar, 24em description measure, panel-color repaints of the `.link-muted`/`.text-body` utilities, weight-800 volt column heads) was ported into the theme's `_general.scss` footer rules, so classy's inherited markup renders the same ink-slab design in both modes.
|
|
43
|
+
- **Classy footer language icon is now theme-adaptive.** The language dropdown button's hardcoded multicolor inline SVG (fixed fills that ignored `currentColor` and clashed on dark surfaces like newsflash's ink-slab footer) is replaced with `{% uj_icon "language" %}`, which inherits the button's color in every theme and mode.
|
|
44
|
+
- **`docs/project-structure.md` renamed `docs/directory-structure.md`** (H1 `# Project Structure` → `# Directory Structure`) for cross-framework doc-file parity — BEM names the same concept `docs/directory-structure.md`, and mirrored docs must match down to the file name. All references updated (`CLAUDE.md`, historical CHANGELOG links). Also normalized `docs/test-boot-layer.md`'s H1 to `# Test Framework — Boot Layer` (matches BXM; EM normalized likewise).
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **Docs parity — new `docs/build-system.md`, `docs/templating.md`, `docs/logging.md`, `docs/common-mistakes.md`.** `build-system.md` makes CLAUDE.md's existing pipeline-reference link real (was a dead link) — gulp task list, config flow, build modes, pure helpers; `templating.md` graduates from "(planned)" — node-powertools bracket conventions + Liquid coexistence; `logging.md` is now the SSOT for the log-file tee (extracted from local-development.md, which keeps a pointer — mirrors EM/BXM); `common-mistakes.md` extracts the canonical anti-pattern list into the repo (BEM already had one). All indexed in CLAUDE.md → Documentation.
|
|
49
|
+
- **Test coverage convention (docs).** New mirrored "Test coverage" sections in `CLAUDE.md`, `docs/test-framework.md`, `src/defaults/CLAUDE.md`, and `src/defaults/test/README.md` — every feature ships with tests at every layer it has a surface in (logic `build`/`page`, UI `page`, end-to-end `boot`); a layer is skipped only when the feature genuinely has no surface there. Mirrored across EM/BXM/BEM.
|
|
50
|
+
- **New `newsflash` theme — editorial news site.** Paper + ink + vermilion design language with volt highlights: Fraunces serif headlines over Schibsted Grotesk, a live news-ticker marquee above the sticky blurred masthead, framed editorial images, hard-offset "lift" pill buttons, film-grain overlay, and first-class dark mode (deep warm near-black paper, cream ink). Ships custom layouts for base (fonts + ticker), homepage (cover-story hero + top-story tiles + "the latest" editorial post feed with sticky most-read/newsletter rails + numbered rundown playbook + "more to chew on" story tiles + dark big-read CTA band), blog index (lead-story splash + editorial tiles), blog post (reading-progress bar, drop cap, serif crossheads, pullquotes, author card), blog category archives (desk directory with stroked story-count numerals + per-desk fronts), blog tag archives (topics wall + per-topic fronts), pricing (membership tiers with "Editor's pick" + flash-sale promo banner), about (newsroom timeline), contact ("contact the desk" + tips line), team ("the masthead" byline cards + ink-slab charter + newsroom principles), team member (reporter profile with beat facts strip), and a 404 "correction notice". Functional pages (download, feedback, updates, auth, account) intentionally inherit classy markup restyled. Select with `theme.id: "newsflash"`. See [docs/themes.md](docs/themes.md).
|
|
51
|
+
- **Theme-authoring convention: genre-native frontmatter defaults.** A theme's layout frontmatter defaults are part of its identity and must be written for the theme's genre (newsflash ships news copy + news-purposed `rundown`/`desks` homepage sections), never copied from classy's SaaS demo data. Universal section keys (`hero`, `cta`, `stats`, `faqs`, `pricing.plans`, …) stay shared so consumer overrides survive theme swaps. Documented in [docs/themes.md](docs/themes.md#frontmatter-defaults-are-part-of-the-themes-identity) + the Path A authoring checklist.
|
|
52
|
+
- **Appearance picker in every footer.** Classy's footer now ships the appearance (light/dark/system) dropdown next to the language dropdown — a pure drop-in block driven by the framework's `data-appearance-*` attributes. Every theme inherits it via the footer fallback; themes with custom footers (newsflash) include it themselves. Documented as required footer furniture in [docs/themes.md](docs/themes.md) + [docs/appearance.md](docs/appearance.md).
|
|
53
|
+
- **Theme-authoring convention: inherit classy's nav + footer chrome, restyle via CSS.** Themes do NOT fork the chrome includes — `copyFallbackThemeFiles()` supplies classy's nav/footer (with paths rewritten into the theme's namespace) and the chrome's identity comes from theme CSS (newsflash's serif masthead + editorial ink-slab footer are pure `css/layout/` restyles of classy's markup). Fork an include only when the structure genuinely diverges — a re-skin fork is a copy that silently drifts (newsflash's nav fork had diverged from classy by nothing but a comment, and the icon-only picker fix had to be applied twice). Documented in [docs/themes.md](docs/themes.md) + the Path A authoring checklist.
|
|
54
|
+
- **Theme-contract build test.** New `mgr:build/theme-contract` suite turns the docs/themes.md conventions into executable assertions, globbing every shipped theme (`_template` included) so a new theme is covered the moment it lands: entry files + `$avatar-sizes` + shared bootstrap-overrides import, `[ site.theme.id ]` bracket parents (swappability), no theme-prefixed classes in markup, no inline `<script>` bodies, the pricing JS-contract markers, `blog-post-content` in post layouts, and page-asset files matching a layout-declared `asset_path` shape (wrong shape = silent bundle skip). It caught neobrutalism's missing promo banner + `.card-title` on its first run.
|
|
55
|
+
- **Shared plan-pricing include — `core/pricing/resolve-plan.html`.** The plan price-resolution Liquid (product lookup from `site.web_manager.payment.products`, frontmatter-over-config monthly/annual precedence, per-unit math) was copy-pasted across all three themes' pricing layouts; it's now a single shared "logic include" (Jekyll includes share caller scope) that every theme calls per plan and renders the assigned variables from. Also guards the per-unit `divided_by` against nil/zero unit values, which previously crashed the build when the per-unit feature value couldn't resolve.
|
|
56
|
+
- **Theme-authoring convention: develop in ONE appearance mode, ship with BOTH.** Build against a primary mode (the consumer's `theme.appearance` default), then validate light AND dark before declaring the theme done — including a live click-through of the footer appearance picker. Documented in [docs/themes.md](docs/themes.md) authoring conventions + validation checklist.
|
|
57
|
+
- **Theme-authoring gotchas documented:** theme page bundles re-emit Bootstrap after the main bundle (use doubled selectors — `:root:root`, `[data-bs-theme="dark"][data-bs-theme="dark"]`, `.btn.btn`), and `.bg-body-*`/`.text-body-*` utilities paint from the `--bs-*-rgb` companion variables, which must be remapped alongside the hex vars. See [docs/themes.md](docs/themes.md).
|
|
58
|
+
- **`npx mgr blogify --count=<n>`.** The blogify command now accepts a post count (default 12, matching the old hardcoded behavior) — e.g. `--count=18` fills every deduplicated post slot on the newsflash homepage. Documented in README + the CLAUDE.md CLI table.
|
|
59
|
+
- **`npx mgr test` tees output to `logs/test.log`.** All test-runner output is now duplicated (ANSI-stripped) to `<projectRoot>/logs/test.log`, truncated fresh on each run, via the existing `attach-log-file` util (skipped on CI through `isServer()`) — mirrors EM's and BEM's `test.log` pattern. Grep the file after a run instead of scrolling terminal scrollback.
|
|
60
|
+
- **`TEST_EXTENDED_MODE` — extended test mode (`--extended`).** `npx mgr test --extended` (or `TEST_EXTENDED_MODE=true npx mgr test`) opts in tests that hit REAL external services (network fetches, Firebase via web-manager, live APIs); off by default so `npx mgr test` stays fast and offline-safe. The signal is the unprefixed `TEST_EXTENDED_MODE` env var — the SAME name across BEM/BXM/UJM/EM (cross-framework parity) — and once set it propagates to every spawned child (the Jekyll build, the boot HTTP server / Puppeteer browsers) via inherited `process.env`. A warning prints (and is teed to `logs/test.log`) when on. Gate live tests on `process.env.TEST_EXTENDED_MODE`. New `src/test/utils/extended-mode-warning.js` is the SSOT for the warning copy. Documented in [docs/test-framework.md](docs/test-framework.md#extended-mode-test_extended_mode) + the env-vars table.
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- **Test command standardizes on `TEST_EXTENDED_MODE`, replacing `--integration` / `UJ_TEST_INTEGRATION`** (no backwards compat — the old flag/env are gone). Mirrors the canonical unprefixed `TEST_EXTENDED_MODE` shared across BEM/BXM/EM.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- **`attach-log-file` no longer truncates `logs/test.log` mid-run.** The tee state is now wrapped in a `createTee()` factory (independent, stackable instances) with the process-wide singleton built on top. A later `attach()` captures the CURRENT `process.stdout.write` (which may already be an outer tee) and restores that exact reference on `detach()`, so stacked tees fan out and unwind in LIFO order. The new build-layer `attach-log-file` test uses its OWN `createTee()` instance, so exercising attach/detach no longer detaches the live singleton tee that's capturing the actual run (which previously cut `logs/test.log` to ~9 lines). UJM's name-based signature (`attachLogFile('test')`) and synchronous `detach()` are preserved. Mirrors EM's `createTee()` refactor.
|
|
69
|
+
|
|
70
|
+
- **neobrutalism pricing page now satisfies the full framework JS contract.** Same two gaps newsflash had: the flash-sale promo banner block (`#pricing-promo-banner` + badge/text/countdown/code ids, shipped `hidden`) was missing entirely, and plan names lacked the `.card-title` class the pricing JS reads for analytics. Both caught by the new theme-contract test on its first run.
|
|
71
|
+
- **Classy admin minimal layouts use bracket parents.** `admin/core/minimal.html` + `minimal-viewport-locked.html` hardcoded `layout: themes/classy/backend/...` instead of the `themes/[ site.theme.id ]/...` convention (the fallback's path rewrite masked it for non-classy themes). Normalized to brackets; now enforced by the theme-contract test.
|
|
72
|
+
- **newsflash nav + dropdown hover text is readable again.** The hover fill (ink pill) left the label ink-on-ink: the shared nav/account includes put Bootstrap's `.text-body` utility (`!important`) on every link and dropdown item, which beat the theme's hover `color`. The hover/active colors now carry `!important`, and dropdown-item child spans with text utilities flip to `inherit` on hover (fixes the blacked-out account-dropdown rows too).
|
|
73
|
+
- **newsflash dropdown item pills no longer press edge-to-edge against the panel.** Bootstrap's re-emitted `.dropdown-menu` rule (`--bs-dropdown-padding-x: 0`) was stripping the theme's panel inset on pages with page CSS — the highlighted pill touched the panel edges. The theme's dropdown rule now uses the doubled selector (`.dropdown-menu.dropdown-menu`), the established page-bundle-gotcha pattern.
|
|
74
|
+
- **newsflash headings no longer go thin on pages with page CSS.** Bootstrap's re-emitted `.display-*` / `.lead` rules (stock weights 300) were clobbering the theme's main-bundle typography on every page that ships a page bundle (post + about read spindly; contact — no page bundle — looked right). Type metrics now ship as Bootstrap variables in the config `@forward with (...)` block (`$display-font-weight: 550`, `$display-line-height: 1.04`, `$lead-font-weight: 400`, `$headings-line-height: 1.1`, `$line-height-base: 1.55`) so every Bootstrap copy compiles them natively. Documented as an extension of the page-bundle gotcha in [docs/themes.md](docs/themes.md).
|
|
75
|
+
- **newsflash post hero image fills its frame.** Two stacked causes: `uj_post` image-tags render as `<picture><img>`, so the img's percentage height resolved against the auto-height picture wrapper (the base `.art-frame` now makes `picture` fill the frame), and the framework's generic `.blog-post-image { max-height: 480px }` capped the image inside the 21/10 frame (the article-hero rule now lifts it with `max-height: none`).
|
|
76
|
+
- **Footer brand description no longer disappears when its data value liquifies to empty.** Both classy's and newsflash's footers resolve the brand blurb via `data.logo.description | default: site.brand.description`, but `default:` only sees the RAW string — a footer.json value like `'{{ site.meta.description }}'` with no `meta.description` set passed the default check and then liquified to nothing, hiding the description even when `brand.description` was set. The footers now re-check after liquification and fall back to `site.brand.description`.
|
|
77
|
+
- **newsflash dark mode no longer stomps consumer brand colors.** The dark-mode `--bs-primary`/`--bs-link-color` remaps were hardcoded to the brightened vermilion, so a consumer's `$primary` override (via `main.scss` `with (...)`) held in light mode but snapped back to vermilion in dark. The remap now derives from the compile-time `$primary` (stock vermilion keeps its hand-tuned brightening; other brand colors get a generic white-mix lift). Documented as a theme-authoring gotcha in [docs/themes.md](docs/themes.md#derive-dark-mode-brand-remaps-from-primary-gotcha).
|
|
78
|
+
- **newsflash pricing page now satisfies the full framework JS contract.** Added the flash-sale promo banner (`#pricing-promo-banner` + badge/text/countdown/code ids, shipped `hidden` — the framework pricing JS reveals it, fills the rotating sale name + countdown, and offsets the masthead) and the `.card-title` class on plan names (read for add-to-cart analytics). The pricing JS contract — billing radios, `.amount`/`.billing-info`/`.price-per-unit` data attributes, `button[data-plan-id]`, plan-name selector, promo banner ids — is now documented as a required cross-theme contract in [docs/themes.md](docs/themes.md#the-pricing-page-has-a-js-contract-too).
|
|
79
|
+
- **`npx mgr test <target>` now correctly scopes by source.** The positional test target was previously ignored — every run executed all suites regardless of the argument. It now selects which test FILES run: `project:` runs project tests only, `mgr:` / `ujm:` / `framework:` run framework tests only (`mgr:` is the universal cross-framework alias, equivalent to the UJM-specific `ujm:` / `framework:`), and a bare path (no prefix) matches both sources. The `--filter=<substring>` flag stays orthogonal — it matches test NAMES within the already-selected files and composes with the target. See [docs/test-framework.md](docs/test-framework.md#filtering-tests).
|
|
80
|
+
|
|
17
81
|
---
|
|
18
82
|
## [1.7.2] - 2026-06-09
|
|
19
83
|
|
|
@@ -21,6 +85,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
21
85
|
|
|
22
86
|
- **Push notification subscribe on payment confirmation CTA click** — hooks `subscribe()` onto CTA button clicks on the payment confirmation page. Requires a user gesture for the browser permission prompt, so uses `{ once: true }` click listeners.
|
|
23
87
|
|
|
88
|
+
### Fixed
|
|
89
|
+
|
|
90
|
+
- **FormManager spinner layout in icon-only buttons** — `_showSpinner()` no longer adds `me-2` margin when `submittingText` is empty. Previously, the unnecessary right margin squished the spinner off-center in small round buttons (e.g. chat send).
|
|
91
|
+
|
|
24
92
|
---
|
|
25
93
|
## [1.7.1] - 2026-06-09
|
|
26
94
|
|
|
@@ -358,7 +426,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
358
426
|
|
|
359
427
|
### Added
|
|
360
428
|
|
|
361
|
-
- **`docs/<topic>.md` deep references** — 17 new files referenced by the v1.2.0 CLAUDE.md reorg that hadn't been committed yet: `ads.md`, `analytics.md`, `appearance.md`, `assets.md`, `audit.md`, `css.md`, `icons.md`, `images.md`, `javascript-libraries.md`, `jekyll-plugin.md`, `layouts-and-pages.md`, `lazy-loading.md`, `local-development.md`, `page-loading.md`, `
|
|
429
|
+
- **`docs/<topic>.md` deep references** — 17 new files referenced by the v1.2.0 CLAUDE.md reorg that hadn't been committed yet: `ads.md`, `analytics.md`, `appearance.md`, `assets.md`, `audit.md`, `css.md`, `icons.md`, `images.md`, `javascript-libraries.md`, `jekyll-plugin.md`, `layouts-and-pages.md`, `lazy-loading.md`, `local-development.md`, `page-loading.md`, `directory-structure.md`, `seo.md`, `xss-prevention.md`. Restores parity with the cross-links already shipped in [CLAUDE.md](CLAUDE.md).
|
|
362
430
|
- **`src/defaults/docs/README.md`, `src/defaults/test/README.md`, `src/defaults/CHANGELOG.md`** — consumer-project scaffolding files distributed via the `defaults` gulp task.
|
|
363
431
|
|
|
364
432
|
---
|
package/CLAUDE.md
CHANGED
|
@@ -8,7 +8,7 @@ Ultimate Jekyll Manager (UJM) is a comprehensive framework for building modern J
|
|
|
8
8
|
|
|
9
9
|
- One-line bootstrap per context (build / frontend / service-worker)
|
|
10
10
|
- Multi-stage gulp pipeline (15 tasks: defaults / distribute / webpack / sass / imagemin / jekyll / jsonToHtml / preprocess / audit / translation / minifyHtml / serve / setup / developmentRebuild)
|
|
11
|
-
- Default Jekyll layouts + themes (`classy` + `neobrutalism` shipped; new themes inherit classy's layouts via the build-time fallback — see [docs/themes.md](docs/themes.md))
|
|
11
|
+
- Default Jekyll layouts + themes (`classy` + `neobrutalism` + `newsflash` shipped; new themes inherit classy's layouts AND nav/footer chrome via the build-time fallback — restyle chrome via theme CSS, fork an include only on real structural divergence — ship **genre-native frontmatter defaults**, and must validate **both appearance modes**; conventions are enforced by the build-layer **theme-contract test** — see [docs/themes.md](docs/themes.md))
|
|
12
12
|
- Frontend ES-module Manager with dynamic per-page module loading
|
|
13
13
|
- Service worker with Firebase Messaging + cache management
|
|
14
14
|
- A built-in **three-layer test framework** (build / page / boot)
|
|
@@ -22,7 +22,7 @@ The only things that ARE safe to run inside UJM itself:
|
|
|
22
22
|
|
|
23
23
|
## Recommended skills
|
|
24
24
|
|
|
25
|
-
- **`
|
|
25
|
+
- **`omega:ujm`** — router skill. Auto-loads on UJM-specific keywords (`_config.yml`, `theme.id`, `uj_icon`, `page.resolved`, `npx mgr setup`, etc.) and points back to this CLAUDE.md + `docs/` (the SSOT), carrying only Claude-workflow hard rules and process checklists.
|
|
26
26
|
- **`js:patterns`** — JavaScript/Node.js conventions: file structure, JSDoc, defensive coding (`?.` usage), template literals, `package.json` conventions. Auto-loads when creating new `.js` files or touching JS module structure.
|
|
27
27
|
|
|
28
28
|
## 🚨 READ WEB-MANAGER TOO
|
|
@@ -43,16 +43,19 @@ The only things that ARE safe to run inside UJM itself:
|
|
|
43
43
|
4. `npm run build` — production build (`UJ_BUILD_MODE=true`)
|
|
44
44
|
5. `npm run deploy` — build + `npu sync --message='Deploy'`
|
|
45
45
|
6. `npm test` (or `npx mgr test`) — runs framework + project test suites
|
|
46
|
-
- `npx mgr test pages/home` — run a specific test by path (relative to `test
|
|
46
|
+
- `npx mgr test pages/home` — run a specific test by path (relative to `test/`, matches both sources)
|
|
47
|
+
- `npx mgr test project:` — run ONLY consumer project tests (`project:custom-test` to match a path)
|
|
48
|
+
- `npx mgr test mgr:` — run ONLY framework tests (`ujm:` / `framework:` are equivalent UJM aliases)
|
|
47
49
|
- `npx mgr test ujm:pages/home` — run only framework tests matching a path
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
+
- The `--filter=<substring>` flag matches test NAMES within the selected files (composes with the target); `--layer=build|page|boot` narrows to one layer
|
|
51
|
+
- Output is teed (ANSI-stripped) to `<projectRoot>/logs/test.log`, truncated fresh each run (skipped on CI) — `cat logs/test.log` instead of scrolling scrollback
|
|
52
|
+
- `--extended` (or `TEST_EXTENDED_MODE=true`) opts in tests that hit real external services — off by default, unprefixed name shared across BEM/BXM/UJM/EM, propagates to spawned envs (Jekyll/boot server); see [docs/test-framework.md](docs/test-framework.md#extended-mode-test_extended_mode)
|
|
50
53
|
|
|
51
54
|
### For Framework Development (This Repository)
|
|
52
55
|
|
|
53
56
|
1. `npm install` — install UJM's own deps
|
|
54
57
|
2. `npm start` (≡ `npm run prepare:watch`) — copies `src/` → `dist/` on file change
|
|
55
|
-
3. Test in
|
|
58
|
+
3. Test in the **designated test consumer** — `../ultimate-jekyll-website` is UJM's consumer for validating framework changes end-to-end (exercise any consumer-level flow there freely: builds, tests, runtime). From inside it, run `npx mgr install dev` to swap UJM to this local repo — required whenever you edit the framework source and want the consumer to pick up the changes (the consumer otherwise keeps its installed `node_modules/ultimate-jekyll-manager`). Reverse with `npx mgr install live`.
|
|
56
59
|
4. `npm test` — runs UJM's own 60 test suites
|
|
57
60
|
|
|
58
61
|
## Architecture
|
|
@@ -96,7 +99,7 @@ UJM uses node-powertools' `template()` with two bracket conventions:
|
|
|
96
99
|
- `{ x }` (default) — used wherever `template()` is called without `brackets:` (e.g. defaults.js Gemfile templating)
|
|
97
100
|
- `[ x ]` — used by distribute.js theme fallback and [template-transform.js](src/gulp/tasks/utils/template-transform.js) (for `.html/.md/.liquid/.json`)
|
|
98
101
|
|
|
99
|
-
Jekyll's Liquid `{{ }}` is processed by Jekyll itself, NOT by node-powertools — those placeholders pass through node-powertools untouched. See [docs/templating.md](docs/templating.md)
|
|
102
|
+
Jekyll's Liquid `{{ }}` is processed by Jekyll itself, NOT by node-powertools — those placeholders pass through node-powertools untouched. See [docs/templating.md](docs/templating.md).
|
|
100
103
|
|
|
101
104
|
### Frontend Manager (`src/index.js`)
|
|
102
105
|
|
|
@@ -135,6 +138,10 @@ Cache name is `${brand.id}-${cache_breaker}` from `UJ_BUILD_JSON.config`. See [d
|
|
|
135
138
|
|
|
136
139
|
Same `{ layer, description, run(ctx) }` contract as EM/BXM. JSON-line reporter protocol uses `__UJM_TEST__` marker. See [docs/test-framework.md](docs/test-framework.md) + [docs/test-boot-layer.md](docs/test-boot-layer.md).
|
|
137
140
|
|
|
141
|
+
### Test coverage
|
|
142
|
+
|
|
143
|
+
Every feature ships with tests at EVERY layer it has a surface in — logic (`build`, or `page` for frontend module logic), UI (`page` — real events on the real DOM), and end-to-end (`boot`). Skip a layer ONLY when the feature genuinely has no surface there (a pure build utility has no UI; a CSS-only tweak has no logic). "The logic test already covers it" is NOT a reason to skip the UI test — logic tests prove the logic, UI tests prove the wiring, boot tests prove the built site. See [docs/test-framework.md](docs/test-framework.md).
|
|
144
|
+
|
|
138
145
|
## CLI
|
|
139
146
|
|
|
140
147
|
`npx mgr <command>` (aliases `uj`, `ujm`, `ultimate-jekyll`):
|
|
@@ -152,15 +159,22 @@ Same `{ layer, description, run(ctx) }` contract as EM/BXM. JSON-line reporter p
|
|
|
152
159
|
| `minify-html` | minify HTML (preserves JSON-LD + inline scripts + IE conditional comments) |
|
|
153
160
|
| `optimize` | AI-optimize pages via OpenAI |
|
|
154
161
|
| `migrate` | migrate consumer project layout (legacy → current) |
|
|
155
|
-
| `blogify` | generate test blog posts from Unsplash |
|
|
162
|
+
| `blogify` | generate test blog posts from Unsplash (`--count=<n>`, default 12) |
|
|
156
163
|
| `cloudflare-purge` | purge Cloudflare cache |
|
|
157
164
|
| `test` | run framework + project test suites (three layers) |
|
|
158
165
|
|
|
159
166
|
Note: `-t` short alias belongs to `translation`. The `test` command uses `--test` flag + `test` positional only. See [docs/cli.md](docs/cli.md) (planned).
|
|
160
167
|
|
|
168
|
+
## Dependency Resolution
|
|
169
|
+
|
|
170
|
+
- **Consumer code can `import`/`require()` any UJM dependency** — webpack's `resolve.modules` includes the framework's own `node_modules/`. Consumer projects do NOT need to `npm install firebase`, `web-manager`, or any other UJM transitive dep. If a dep doesn't resolve, the fix is in UJM's webpack config — not the consumer's `package.json`.
|
|
171
|
+
- **web-manager owns Firebase.** Consumer code NEVER imports Firebase directly (`import firebase from 'firebase/app'`). Use `import webManager from 'web-manager'` → `webManager.auth()`, `webManager.firestore()`. Same rule in EM and BXM.
|
|
172
|
+
- **`Manager.require(name)`** resolves from UJM's module context at runtime (static + prototype). Use in gulp tasks or unbundled code (e.g. test fixtures). Webpack `resolve.modules` handles the bundled case.
|
|
173
|
+
|
|
161
174
|
## Development Workflow
|
|
162
175
|
|
|
163
|
-
- **🚫 NEVER run `npm start`
|
|
176
|
+
- **🚫 NEVER run `npm start` in a consumer project** — the user runs the dev server; running it again kills theirs. Assume it's already running; if it isn't, **instruct the user to run it** rather than running it yourself. Instead, **check `logs/dev.log`** after editing files to confirm the watcher recompiled successfully (`Reloading Browsers...` = success; `errored` = fix the error) — never tail/attach to the process. If editing multiple files, check the log once after the last edit. A change that breaks the build is not a completed change. Running `npx mgr test` is fine.
|
|
177
|
+
- **Live-test UI changes via CDP.** After code changes compile, use the `chrome-devtools` MCP tools (screenshots, click, evaluate JS, console logs) to verify the change works in the running browser. This is the primary way to confirm UI changes — type-checking and test suites verify code correctness, not feature correctness. See `~/.claude/mcp-server/servers/chrome-devtools/CLAUDE.md`.
|
|
164
178
|
|
|
165
179
|
## File Conventions
|
|
166
180
|
|
|
@@ -195,26 +209,32 @@ Deep references live in `docs/`. Treat docs as a first-class deliverable. **When
|
|
|
195
209
|
- [docs/test-boot-layer.md](docs/test-boot-layer.md) — boot layer deep-dive (_site/ discovery, HTTP server, fixture vs consumer)
|
|
196
210
|
- [docs/environment-detection.md](docs/environment-detection.md) — `isTesting`/`isDevelopment`/`isProduction`/`getVersion`
|
|
197
211
|
- [docs/jekyll-plugin.md](docs/jekyll-plugin.md) — UJ Powertools gem: filters, tags, page variables (`page.resolved`, `uj_icon`, `uj_hash`, `iftruthy`, etc.)
|
|
198
|
-
- [docs/audit.md](docs/audit.md) —
|
|
212
|
+
- [docs/audit.md](docs/audit.md) — full-audit check catalog (U-xx universal / UJM-xx / F-xx IDs with severity + scope), protocol + fix loop, `npx mgr audit` automated stage
|
|
213
|
+
- [docs/migration.md](docs/migration.md) — full migration (old UJ → latest UJM base), `_config.yml` quick-fix schema, revert-posts procedure
|
|
199
214
|
|
|
200
215
|
### Project & dev environment
|
|
201
216
|
|
|
202
|
-
- [docs/
|
|
203
|
-
- [docs/
|
|
217
|
+
- [docs/directory-structure.md](docs/directory-structure.md) — UJM repo layout and consuming-project layout
|
|
218
|
+
- [docs/build-system.md](docs/build-system.md) — gulp pipeline (15 tasks), config flow, build modes, pure helpers
|
|
219
|
+
- [docs/templating.md](docs/templating.md) — node-powertools bracket conventions, Liquid coexistence
|
|
220
|
+
- [docs/local-development.md](docs/local-development.md) — browsersync URL, Firebase emulator connect, PurgeCSS safelist
|
|
221
|
+
- [docs/logging.md](docs/logging.md) — `dev.log` / `build.log` / `test.log` tee, CI skip
|
|
222
|
+
- [docs/common-mistakes.md](docs/common-mistakes.md) — the canonical "don't do this" list
|
|
204
223
|
- [docs/assets.md](docs/assets.md) — UJM vs consumer file layout, section config (nav/footer/account), frontmatter-driven page customization, webpack aliases, page module pattern
|
|
205
224
|
|
|
206
225
|
### Pages, layouts, content
|
|
207
226
|
|
|
208
227
|
- [docs/animation-studio.md](docs/animation-studio.md) — Animation Studio admin page: clip registration via `window.STUDIO_CLIPS`, helpers (`animate`, `el`, `flowClip`, `cardClip`, `chatClip`), resolution picker, recording, aspect ratio modes
|
|
209
228
|
- [docs/themes.md](docs/themes.md) — theme system: selection + resolution (SCSS loadPaths, `__theme__`, classy layout fallback), shared vs per-theme layers, authoring a theme inside UJM OR in a consumer project, live validation
|
|
210
|
-
- [docs/layouts-and-pages.md](docs/layouts-and-pages.md) — page types, layout chain, `asset_path` frontmatter
|
|
229
|
+
- [docs/layouts-and-pages.md](docs/layouts-and-pages.md) — page types, layout chain, `asset_path` frontmatter, default-page customization rules + per-page levels, dashboard list/detail/edit pattern, custom page creation
|
|
211
230
|
- [docs/images.md](docs/images.md) — `@post/` shortcut for blog post images, BEM admin/post image handling, imagemin pipeline + source-size constraints + `UJ_IMAGEMIN_REWRITE_SOURCES` cleanup flag
|
|
212
231
|
- [docs/icons.md](docs/icons.md) — Font Awesome conventions, `{% uj_icon %}` vs prerendered icons in JS, size reference, country flag SVGs (`assets/icons/flags/modern-square/`)
|
|
213
|
-
- [docs/seo.md](docs/seo.md) — Alternatives collection (competitor comparison pages)
|
|
232
|
+
- [docs/seo.md](docs/seo.md) — content writing rules (headlines, sentence case, accents), Services/Solutions page strategies, Alternatives collection (competitor comparison pages), Schema/JSON-LD (`SoftwareApplication`, `FAQPage`)
|
|
214
233
|
|
|
215
234
|
### Frontend behavior
|
|
216
235
|
|
|
217
236
|
- [docs/css.md](docs/css.md) — section padding rule, theme-adaptive classes, cards in colored sections, `<html>` data attributes
|
|
237
|
+
- [docs/purgecss.md](docs/purgecss.md) — PurgeCSS safelist playbook: two safelist locations, RegExp anchoring, gotchas (`variables: false`, per-file processing), current UJM safelist
|
|
218
238
|
- [docs/appearance.md](docs/appearance.md) — dark/light/system mode switching: JS API, HTML attributes
|
|
219
239
|
- [docs/page-loading.md](docs/page-loading.md) — page-loading protection, `.btn-action`, layered form-protection strategy
|
|
220
240
|
- [docs/lazy-loading.md](docs/lazy-loading.md) — `data-lazy="@type value"` syntax and supported types
|
|
@@ -222,7 +242,8 @@ Deep references live in `docs/`. Treat docs as a first-class deliverable. **When
|
|
|
222
242
|
|
|
223
243
|
### JS libraries & security
|
|
224
244
|
|
|
225
|
-
- [docs/javascript-libraries.md](docs/javascript-libraries.md) — WebManager singleton + UJM libs at `src/assets/js/libs/` (prerendered icons, authorizedFetch, usage bindings, payment-config, FormManager)
|
|
245
|
+
- [docs/javascript-libraries.md](docs/javascript-libraries.md) — WebManager singleton + UJM libs at `src/assets/js/libs/` (prerendered icons, authorizedFetch, usage bindings, payment-config, FormManager), reads-vs-writes rule (Firestore SDK for reads, Cloud Functions for writes)
|
|
246
|
+
- [docs/no-inline-scripts.md](docs/no-inline-scripts.md) — HARD RULE: no inline `<script>` bodies; full migration playbook incl. Liquid `data-*`/`<template>` bridges
|
|
226
247
|
- [docs/xss-prevention.md](docs/xss-prevention.md) — zero-trust DOM injection rules, `escapeHTML`, postMessage origin checks, redirect validation
|
|
227
248
|
|
|
228
249
|
### Analytics
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* **SEO Optimized**: Ultimate Jekyll is fully SEO optimized.
|
|
29
29
|
* **Blazingly Fast**: Ultimate Jekyll is blazingly fast.
|
|
30
30
|
* **NPM & Gulp**: Ultimate Jekyll is fueled by an intuitive incorporation of npm and gulp.
|
|
31
|
-
* **Themes**: Pick a shipped theme with `theme.id` (`classy` or `
|
|
31
|
+
* **Themes**: Pick a shipped theme with `theme.id` (`classy`, `neobrutalism`, or `newsflash` — an editorial news-site theme), or author your own. New themes inherit all default page layouts automatically and only restyle/override what differs. See [docs/themes.md](docs/themes.md).
|
|
32
32
|
* **Built-in test framework**: three layers (`build` / `page` / `boot`) — plain Node, headless Chromium tab, headless Chromium against real `_site/` with SW registration verification.
|
|
33
33
|
|
|
34
34
|
## 🚀 Getting started
|
|
@@ -48,6 +48,7 @@ npx mgr test # all layers
|
|
|
48
48
|
npx mgr test --layer build # plain Node, fast
|
|
49
49
|
npx mgr test --layer page # headless Chromium tab against harness HTML
|
|
50
50
|
npx mgr test --layer boot # headless Chromium against built _site/
|
|
51
|
+
npx mgr test --extended # also run tests that hit real external services (off by default)
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
Test files use Jest-compatible matchers:
|
|
@@ -183,9 +184,10 @@ npm run prepare:watch
|
|
|
183
184
|
```
|
|
184
185
|
|
|
185
186
|
### Run the `blogify` task:
|
|
186
|
-
Create
|
|
187
|
+
Create test blog posts in the `_posts` directory with the `blogify` task (default 12; pass `--count=<n>` for more — e.g. 18 fills every post slot on the newsflash homepage). This is useful for testing and development purposes.
|
|
187
188
|
```bash
|
|
188
189
|
npx mgr blogify
|
|
190
|
+
npx mgr blogify --count=18
|
|
189
191
|
```
|
|
190
192
|
|
|
191
193
|
## Page Frontmatter
|
package/TODO-AUTH-TESTING.md
CHANGED
|
@@ -162,4 +162,4 @@ The test harness should stay vanilla Mocha + JSDOM + fixture HTML files.
|
|
|
162
162
|
- All 6 test files above written and green
|
|
163
163
|
- `npm test` in UJM runs them as part of the standard suite
|
|
164
164
|
- The v1.3.1 bug (consent guard ordering) is caught by `auth-guard-ordering.test.js` — verify by reverting the v1.3.2 fix in a branch and watching the test fail
|
|
165
|
-
- Documented in `docs/
|
|
165
|
+
- Documented in `docs/test-framework.md` so contributors know to add auth tests when touching auth code
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Newsflash Theme
|
|
2
|
+
|
|
3
|
+
An editorial news theme: warm paper surfaces, ink text and hairline frames,
|
|
4
|
+
vermilion accents with volt highlights, optical-sized serif headlines
|
|
5
|
+
(Fraunces) over a clean grotesk (Schibsted Grotesk). Signature elements: the
|
|
6
|
+
live news ticker above the masthead, framed editorial images, kickers,
|
|
7
|
+
section rules, drop caps, and pill controls that lift off small hard shadows.
|
|
8
|
+
|
|
9
|
+
## Select the theme
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
# src/_config.yml (consuming project)
|
|
13
|
+
theme:
|
|
14
|
+
id: "newsflash"
|
|
15
|
+
target: "frontend"
|
|
16
|
+
appearance: "light" # or "dark" / "system" — dark mode is first-class
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Customize tokens
|
|
20
|
+
|
|
21
|
+
Every variable in `_config.scss` is `!default` — override any of them in your
|
|
22
|
+
project BEFORE the theme import:
|
|
23
|
+
|
|
24
|
+
```scss
|
|
25
|
+
// src/assets/css/main.scss (consuming project)
|
|
26
|
+
@use 'ultimate-jekyll-manager' with (
|
|
27
|
+
$primary: #0E7C3A, // swap vermilion for forest green
|
|
28
|
+
$nf-volt: #FFD966, // warmer highlighter
|
|
29
|
+
$nf-radius: 12px, // tighter frames
|
|
30
|
+
$nf-font-display: ('Lora', serif), // different serif voice
|
|
31
|
+
);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Runtime tokens live in `css/base/_root.scss` as `--nf-*` CSS custom
|
|
35
|
+
properties; dark mode is a single `[data-bs-theme="dark"]` remap block.
|
|
36
|
+
|
|
37
|
+
## What ships custom
|
|
38
|
+
|
|
39
|
+
- **Layouts** (`_layouts/themes/newsflash/`): base (ticker + fonts), homepage,
|
|
40
|
+
blog index, blog post, pricing, about, contact, 404. Everything else
|
|
41
|
+
inherits Classy markup restyled by this theme's CSS.
|
|
42
|
+
- **Chrome** (`_includes/themes/newsflash/frontend/sections/`): the serif
|
|
43
|
+
masthead nav + the editorial ink-slab footer (volt column heads, language +
|
|
44
|
+
appearance pickers in the bottom rail). Same `nav.json`/`footer.json` data
|
|
45
|
+
contract as classy.
|
|
46
|
+
- **Page assets** (`pages/`): homepage rails/big-read band, blog index splash,
|
|
47
|
+
blog post reading-progress + drop cap, pricing/about/404 accents.
|
|
48
|
+
- **Behaviors** (`js/`): masthead scroll shadow, Bootstrap tooltips. The
|
|
49
|
+
ticker and marquees are pure CSS.
|
|
50
|
+
|
|
51
|
+
## Conventions
|
|
52
|
+
|
|
53
|
+
- Markup uses standard Bootstrap classes + universal semantic names
|
|
54
|
+
(`.kicker`, `.ticker`, `.section-head`, `.art-frame`) — never `nf-*`
|
|
55
|
+
prefixes. `nf-*` survives only on SCSS internals (`$nf-*`, `--nf-*`,
|
|
56
|
+
mixins).
|
|
57
|
+
- Fonts load via the `theme.head.content` block in
|
|
58
|
+
`_layouts/themes/newsflash/frontend/core/base.html`, never SCSS `@import`.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Newsflash Theme Configuration
|
|
2
|
+
// ALL customizable variables are defined here with !default.
|
|
3
|
+
// Consuming projects override any of these BEFORE the theme is imported.
|
|
4
|
+
//
|
|
5
|
+
// Design language: warm paper surfaces; ink text + hairline ink frames;
|
|
6
|
+
// vermilion accents with volt highlights; serif display type over a clean
|
|
7
|
+
// grotesk; pill controls sitting on small hard offset shadows that "lift"
|
|
8
|
+
// on hover. An editorial newsroom — modern front page, not a brochure.
|
|
9
|
+
|
|
10
|
+
// ============================================
|
|
11
|
+
// Bootstrap Color Overrides
|
|
12
|
+
// ============================================
|
|
13
|
+
// Editorial ink-and-accent palette mapped onto Bootstrap's semantic colors.
|
|
14
|
+
$primary: #F03612 !default; // vermilion — the signature accent
|
|
15
|
+
$secondary: #5C544A !default; // ink-soft — muted secondary actions
|
|
16
|
+
$success: #2E7D4F !default; // editorial green
|
|
17
|
+
$info: #2742F5 !default; // electric blue
|
|
18
|
+
$warning: #D9F24E !default; // volt — highlighter yellow-green
|
|
19
|
+
$danger: #C81E1E !default; // deep red (distinct from vermilion)
|
|
20
|
+
$light: #F7F2E7 !default; // paper
|
|
21
|
+
$dark: #171310 !default; // ink
|
|
22
|
+
|
|
23
|
+
// ============================================
|
|
24
|
+
// Paper & Ink (the structural neutrals)
|
|
25
|
+
// ============================================
|
|
26
|
+
// "Paper" = the page surface. "Ink" = text, frames, and hard shadows.
|
|
27
|
+
$nf-paper: #F7F2E7 !default; // body background (light mode)
|
|
28
|
+
$nf-paper-2: #EFE8D8 !default; // wells / alt surfaces (light mode)
|
|
29
|
+
$nf-ink: #171310 !default; // text + frames (light mode)
|
|
30
|
+
$nf-ink-soft: #5C544A !default; // deks, metas, muted text (light mode)
|
|
31
|
+
|
|
32
|
+
// Dark mode counterparts — deep warm near-black paper, cream ink.
|
|
33
|
+
$nf-paper-dark: #181210 !default;
|
|
34
|
+
$nf-paper-2-dark: #221A14 !default;
|
|
35
|
+
$nf-ink-dark: #F2E8D9 !default;
|
|
36
|
+
$nf-ink-soft-dark: #A8998A !default;
|
|
37
|
+
|
|
38
|
+
// ============================================
|
|
39
|
+
// Accent Palette
|
|
40
|
+
// ============================================
|
|
41
|
+
$nf-vermilion: #F03612 !default;
|
|
42
|
+
$nf-vermilion-dark-mode: #FF4A26 !default; // brightened for contrast on dark paper
|
|
43
|
+
$nf-blue: #2742F5 !default;
|
|
44
|
+
$nf-blue-dark-mode: #5B72FF !default;
|
|
45
|
+
$nf-volt: #D9F24E !default; // stays vibrant in both modes
|
|
46
|
+
$nf-volt-ink: #171310 !default; // readable text on volt
|
|
47
|
+
|
|
48
|
+
// Ink panels (footer, ticker, big-read band) — dark slabs in BOTH modes.
|
|
49
|
+
$nf-panel-bg: #171310 !default;
|
|
50
|
+
$nf-panel-color: #F7F2E7 !default;
|
|
51
|
+
$nf-panel-bg-dark: #0E0B09 !default; // deeper than dark paper so it still reads as a slab
|
|
52
|
+
$nf-panel-color-dark: #F2E8D9 !default;
|
|
53
|
+
|
|
54
|
+
// ============================================
|
|
55
|
+
// Borders — hairline ink frames
|
|
56
|
+
// ============================================
|
|
57
|
+
$nf-border-width: 1.5px !default;
|
|
58
|
+
$nf-radius: 18px !default; // frames, cards, panels
|
|
59
|
+
$nf-radius-sm: 12px !default; // small frames, inputs
|
|
60
|
+
|
|
61
|
+
// ============================================
|
|
62
|
+
// Shadows — small hard offsets (controls) + soft pop (frames)
|
|
63
|
+
// ============================================
|
|
64
|
+
// Controls rest on a 3px hard ink shadow and LIFT on hover (shadow grows to
|
|
65
|
+
// 6px while the element translates up-left). Frames use a soft "pop" blur.
|
|
66
|
+
$nf-shadow-offset: 3px !default;
|
|
67
|
+
$nf-shadow-offset-hover: 6px !default;
|
|
68
|
+
$nf-shadow-pop: 0 18px 40px -18px rgba(23, 19, 16, .35) !default;
|
|
69
|
+
|
|
70
|
+
// ============================================
|
|
71
|
+
// Typography
|
|
72
|
+
// ============================================
|
|
73
|
+
// Fraunces (optical-sized serif) for display; Schibsted Grotesk for body/UI.
|
|
74
|
+
$font-family-sans-serif: 'Schibsted Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !default;
|
|
75
|
+
$nf-font-display: 'Fraunces', Georgia, 'Times New Roman', serif !default;
|
|
76
|
+
|
|
77
|
+
$headings-font-weight: 600 !default;
|
|
78
|
+
$nf-heading-letter-spacing: -0.02em !default;
|
|
79
|
+
$font-weight-bold: 700 !default;
|
|
80
|
+
|
|
81
|
+
// ============================================
|
|
82
|
+
// Motion — smooth editorial easing
|
|
83
|
+
// ============================================
|
|
84
|
+
$nf-transition: all 0.2s cubic-bezier(0.22, 1, 0.36, 1) !default;
|
|
85
|
+
|
|
86
|
+
// ============================================
|
|
87
|
+
// Component Sizing
|
|
88
|
+
// ============================================
|
|
89
|
+
// Avatar sizes map (matches Classy so shared layouts/includes render correctly)
|
|
90
|
+
$avatar-sizes: (
|
|
91
|
+
null: 3rem,
|
|
92
|
+
2xs: 0.5rem,
|
|
93
|
+
xs: 1.5rem,
|
|
94
|
+
sm: 2rem,
|
|
95
|
+
md: 2.5rem,
|
|
96
|
+
lg: 3.5rem,
|
|
97
|
+
xl: 5rem,
|
|
98
|
+
2xl: 7.5rem,
|
|
99
|
+
3xl: 10rem,
|
|
100
|
+
4xl: 12.5rem,
|
|
101
|
+
5xl: 15rem
|
|
102
|
+
) !default;
|
|
103
|
+
|
|
104
|
+
// ============================================
|
|
105
|
+
// Forward Bootstrap with our configuration
|
|
106
|
+
// ============================================
|
|
107
|
+
@forward '../bootstrap/scss/bootstrap.scss' with (
|
|
108
|
+
$primary: $primary,
|
|
109
|
+
$secondary: $secondary,
|
|
110
|
+
$success: $success,
|
|
111
|
+
$info: $info,
|
|
112
|
+
$warning: $warning,
|
|
113
|
+
$danger: $danger,
|
|
114
|
+
$light: $light,
|
|
115
|
+
$dark: $dark,
|
|
116
|
+
$font-family-sans-serif: $font-family-sans-serif,
|
|
117
|
+
$headings-font-family: $nf-font-display,
|
|
118
|
+
$headings-font-weight: $headings-font-weight,
|
|
119
|
+
$font-weight-bold: $font-weight-bold,
|
|
120
|
+
// Type metrics MUST live in Bootstrap vars (not element rules in the main
|
|
121
|
+
// bundle): page bundles re-emit Bootstrap AFTER main, so Bootstrap's own
|
|
122
|
+
// .display-*/.lead/body rules would win there with the stock 300 weights.
|
|
123
|
+
$headings-line-height: 1.1,
|
|
124
|
+
$display-font-family: $nf-font-display,
|
|
125
|
+
$display-font-weight: 550,
|
|
126
|
+
$display-line-height: 1.04,
|
|
127
|
+
$lead-font-weight: 400,
|
|
128
|
+
$line-height-base: 1.55,
|
|
129
|
+
// Hairline ink borders everywhere; editorial radii (controls go pill in
|
|
130
|
+
// component SCSS — cards/frames keep these).
|
|
131
|
+
$border-width: $nf-border-width,
|
|
132
|
+
$border-radius: $nf-radius-sm,
|
|
133
|
+
$border-radius-sm: 8px,
|
|
134
|
+
$border-radius-lg: $nf-radius,
|
|
135
|
+
$border-radius-xl: 24px,
|
|
136
|
+
$enable-shadows: false,
|
|
137
|
+
$enable-negative-margins: true
|
|
138
|
+
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Newsflash Theme — JS entry point
|
|
2
|
+
// Loaded at runtime via webpack's __theme__ alias (import('__theme__/_theme.js')).
|
|
3
|
+
// Exposes Bootstrap globally and wires up theme behaviors on DOM ready.
|
|
4
|
+
import bootstrap from '__main_assets__/themes/bootstrap/js/index.umd.js';
|
|
5
|
+
import { ready as domReady } from 'web-manager/modules/dom.js';
|
|
6
|
+
|
|
7
|
+
// Make Bootstrap available globally (used by UJM utilities + components)
|
|
8
|
+
window.bootstrap = bootstrap;
|
|
9
|
+
|
|
10
|
+
/* @dev-only:start */
|
|
11
|
+
{
|
|
12
|
+
console.log('Newsflash theme loaded successfully (assets/themes/newsflash/_theme.js)');
|
|
13
|
+
}
|
|
14
|
+
/* @dev-only:end */
|
|
15
|
+
|
|
16
|
+
// Theme behaviors
|
|
17
|
+
import setupMastheadScroll from './js/masthead-scroll.js';
|
|
18
|
+
import initializeTooltips from './js/initialize-tooltips.js';
|
|
19
|
+
|
|
20
|
+
// Initialize when DOM is ready
|
|
21
|
+
domReady().then(() => {
|
|
22
|
+
// Newsflash behaviors
|
|
23
|
+
setupMastheadScroll();
|
|
24
|
+
|
|
25
|
+
// Generic Bootstrap initializations
|
|
26
|
+
initializeTooltips();
|
|
27
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Newsflash Theme — SCSS entry point
|
|
2
|
+
// Forwards config (so consuming projects can override vars), loads Bootstrap
|
|
3
|
+
// via config, then layers the editorial system on top. Import order matters:
|
|
4
|
+
// config → mixins → root vars → base → layout → components → bootstrap overrides.
|
|
5
|
+
|
|
6
|
+
// Forward theme configuration (allows consuming project to override)
|
|
7
|
+
@forward 'config';
|
|
8
|
+
@use 'config' as *;
|
|
9
|
+
|
|
10
|
+
// Mixins must be available to every partial below.
|
|
11
|
+
// @import (not @use) so the mixins land in the global scope the @imports share.
|
|
12
|
+
@import 'css/base/mixins';
|
|
13
|
+
|
|
14
|
+
// CSS custom properties (light/dark bridge)
|
|
15
|
+
@import 'css/base/root';
|
|
16
|
+
|
|
17
|
+
// Base styles
|
|
18
|
+
@import 'css/base/typography';
|
|
19
|
+
@import 'css/base/utilities';
|
|
20
|
+
|
|
21
|
+
// Layout styles
|
|
22
|
+
@import 'css/layout/general';
|
|
23
|
+
@import 'css/layout/navigation';
|
|
24
|
+
|
|
25
|
+
// Component styles
|
|
26
|
+
@import 'css/components/buttons';
|
|
27
|
+
@import 'css/components/cards';
|
|
28
|
+
@import 'css/components/forms';
|
|
29
|
+
@import 'css/components/badges';
|
|
30
|
+
@import 'css/components/ticker';
|
|
31
|
+
@import 'css/components/editorial';
|
|
32
|
+
@import 'css/components/panels';
|
|
33
|
+
@import 'css/components/infinite-scroll';
|
|
34
|
+
|
|
35
|
+
// Universal Bootstrap overrides (shared across all UJ themes).
|
|
36
|
+
// Must come AFTER Bootstrap is loaded via config to use @extend.
|
|
37
|
+
@import '../bootstrap/overrides';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Newsflash Theme — Mixins
|
|
2
|
+
// The shared building blocks of the editorial look. Components @include these
|
|
3
|
+
// so the frame/shadow/lift system lives in ONE place (SSOT) rather than being
|
|
4
|
+
// copy-pasted across buttons, cards, inputs, etc.
|
|
5
|
+
|
|
6
|
+
// Hairline frame in the current ink color.
|
|
7
|
+
@mixin nf-border($width: var(--nf-border-width)) {
|
|
8
|
+
border: $width solid var(--nf-border-color);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Small hard offset shadow (no blur) — the resting state of controls.
|
|
12
|
+
@mixin nf-shadow-hard() {
|
|
13
|
+
box-shadow: var(--nf-shadow-hard);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Soft "pop" shadow — depth for frames and panels (hero art, signup rail).
|
|
17
|
+
@mixin nf-shadow-pop() {
|
|
18
|
+
box-shadow: var(--nf-shadow-pop);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// The signature interaction: the element rests on a small hard shadow, then
|
|
22
|
+
// LIFTS up-left on hover (shadow grows beneath it) and presses flush on
|
|
23
|
+
// active. Pure transform + shadow — no color shift.
|
|
24
|
+
@mixin nf-lift() {
|
|
25
|
+
transition: $nf-transition;
|
|
26
|
+
|
|
27
|
+
&:hover {
|
|
28
|
+
transform: translate(-2px, -2px);
|
|
29
|
+
box-shadow: var(--nf-shadow-hard-hover);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&:active {
|
|
33
|
+
transform: translate(0, 0);
|
|
34
|
+
box-shadow: 1px 1px 0 var(--nf-shadow-color);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Headline hover underline — an accent rule that grows from the left under
|
|
39
|
+
// the text (the editorial "this is a link" affordance on serif headlines).
|
|
40
|
+
@mixin nf-underline-grow($color: var(--bs-primary), $thickness: 2px) {
|
|
41
|
+
background-image: linear-gradient($color, $color);
|
|
42
|
+
background-repeat: no-repeat;
|
|
43
|
+
background-size: 0% $thickness;
|
|
44
|
+
background-position: 0 96%;
|
|
45
|
+
transition: background-size 0.35s cubic-bezier(0.22, 1, 0.36, 1);
|
|
46
|
+
|
|
47
|
+
&:hover {
|
|
48
|
+
background-size: 100% $thickness;
|
|
49
|
+
}
|
|
50
|
+
}
|