Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
2782f97
fix(#129): accept var() with a fallback in template colour results
WJDDesigns Sep 5, 2026
7e35822
fix(#129): accept var() with a fallback in template colour results
WJDDesigns Sep 5, 2026
daeafbc
feat(strategy): Ultra Dashboard, a community dashboard built from are…
WJDDesigns Sep 6, 2026
3b65a0d
docs: release notes and version for 3.10.0-beta4
WJDDesigns Sep 6, 2026
c77b9ab
feat(strategy): preview images for the Ultra Dashboard tile in the Ne…
WJDDesigns Sep 6, 2026
82396d0
feat(strategy): varied per-room composition and a style picker in the…
WJDDesigns Sep 6, 2026
344e934
Merge remote feat/esm-multi-file-phase1 before 3.10.0-beta4 release.
WJDDesigns Sep 6, 2026
bbbcca6
Release 3.10.0-beta4
WJDDesigns Sep 6, 2026
8adc669
feat(themes): theme engine core, built-in themes, HA theme passthroug…
WJDDesigns Sep 6, 2026
46ae8dc
feat(themes): theme picker in Card Settings, Hub Themes tab with libr…
WJDDesigns Sep 6, 2026
62543fb
feat(plugin): ultra_theme CPT and ultra-card/v1/themes catalog + auth…
WJDDesigns Sep 6, 2026
14d704a
feat(themes): community theme catalog client — catalog/author service…
WJDDesigns Sep 6, 2026
41a0b1d
feat(themes): import an installed HA theme into a local Ultra theme; …
WJDDesigns Sep 6, 2026
fb431ec
fix(themes): Monochrome actually desaturates the whole card via new g…
WJDDesigns Sep 6, 2026
91a75cc
feat(themes): Green Terminal built-in; color_filter token for tinted …
WJDDesigns Sep 6, 2026
6dbb788
feat(themes): Liquid Glass built-in (Apple-style refractive glass)
WJDDesigns Sep 6, 2026
a0f3545
feat(themes): Hillary built-in (Nancy Meyers palette, Ralph Lauren ta…
WJDDesigns Sep 6, 2026
b9c7c7b
themes: derive companion HA colours so pinned palettes stay readable
WJDDesigns Sep 6, 2026
20b436e
themes: Hillary uses the Michiana Mahjong Club palette
WJDDesigns Sep 6, 2026
1a6492d
themes: add Moose built-in (all browns)
WJDDesigns Sep 6, 2026
5210b8e
themes: Metallic and Beach built-ins; allow inline SVG artwork in the…
WJDDesigns Sep 6, 2026
5813b01
themes: add Vapor built-in (vaporwave)
WJDDesigns Sep 6, 2026
4021830
themes: remove Classic and Soft; Material follows Material Design 3
WJDDesigns Sep 6, 2026
7860fe9
themes: drop classic/soft compatibility aliases
WJDDesigns Sep 6, 2026
02c03b7
themes: add Gummy built-in; per-card --uc-card-hue
WJDDesigns Sep 6, 2026
c9f7b33
themes: add Wood built-in (procedural walnut grain)
WJDDesigns Sep 6, 2026
e11afb9
themes: seed --uc-card-hue from the whole layout
WJDDesigns Sep 6, 2026
c6d07bc
themes: module-internal radii scale with the theme card radius
WJDDesigns Sep 6, 2026
2e39afd
themes: nested radii step down concentrically from the card radius
WJDDesigns Sep 6, 2026
f9a2929
themes: real materials for Gummy and Metallic
WJDDesigns Sep 6, 2026
95c629b
themes: Gummy gloss is seeded per card, hues dealt so neighbours neve…
WJDDesigns Sep 6, 2026
a37fc8e
themes: Gummy drops its border
WJDDesigns Sep 6, 2026
b3900ac
themes: Metallic is a chrome bezel around a black recessed panel
WJDDesigns Sep 6, 2026
926d4fc
themes: Vapor frames vary per card
WJDDesigns Sep 6, 2026
f0dd873
themes: Beach scatters seeded finds along the sand
WJDDesigns Sep 6, 2026
b02d730
themes: Hillary tucks seeded hydrangeas into corners
WJDDesigns Sep 6, 2026
5951425
themes: Wood is a wall of varnished mahogany planks with maple controls
WJDDesigns Sep 6, 2026
18f5a59
themes: add Neumorphic Light and Neumorphic Dark built-ins
WJDDesigns Sep 6, 2026
91be0c8
themes: pane tokens so a theme owns every inner layer
WJDDesigns Sep 6, 2026
9a881fc
Themes may paint the Lovelace view behind their cards
WJDDesigns Sep 6, 2026
95c0028
Liquid Glass v2: clear lensing glass on the iOS 26 blue wallpaper
WJDDesigns Sep 6, 2026
54dce78
Liquid Glass v3: real refraction at the bezel (SVG displacement backd…
WJDDesigns Sep 6, 2026
6acd141
Liquid Glass v4: lens wallpaper after Apple's, dark ink
WJDDesigns Sep 6, 2026
32206cf
Liquid Glass v5: see-through
WJDDesigns Sep 6, 2026
98cd7f3
themes: Material follows the M3 baseline with an expressive-shapes wa…
WJDDesigns Sep 6, 2026
178f1dd
plugin: v1.3.23 — scan page/pane background artwork server-side; repa…
WJDDesigns Sep 7, 2026
6a56319
themes: Hub Themes / My Themes split with Default & Community section…
WJDDesigns Sep 7, 2026
8fcb470
themes: builder audit — card chrome derived from tokens, image/SVG wa…
WJDDesigns Sep 7, 2026
2afb99b
docs: plan for unifying bar/button/slider surface styles with the the…
WJDDesigns Sep 7, 2026
30b73f8
themes: surface recipes — one vocabulary for button/popup/spinbox/bar…
WJDDesigns Sep 7, 2026
5041a3a
themes: panes everywhere + cleanup — pane recipe folded into --uc-pan…
WJDDesigns Sep 7, 2026
c17a501
theme builder: tint follows the accent (Terminal in any colour), Rese…
WJDDesigns Sep 7, 2026
03b018a
theme builder: native checkbox for tb-check so the host theme's skin …
WJDDesigns Sep 7, 2026
2bb11d2
theme builder: Surprise me generates a coherent random theme (contras…
WJDDesigns Sep 7, 2026
8fd95ee
themes gallery: rebuild /themes/ as the Presets page twin (hero searc…
WJDDesigns Sep 7, 2026
2352008
themes gallery: list the built-in (Default) themes on ultracard.io. C…
WJDDesigns Sep 7, 2026
f9a61b4
themes gallery: pin the sort select's box so host theme <select> rule…
WJDDesigns Sep 7, 2026
53568a8
Release 3.10.0-beta5
WJDDesigns Sep 7, 2026
30af4e7
fix(tests): navigation service skips its deferred MutationObservers w…
WJDDesigns Sep 7, 2026
23a84f2
plugin 1.3.37: built-in themes ship inside the plugin (data/builtin-t…
WJDDesigns Sep 7, 2026
8b590e6
feat(themes): wire Light and Button Input button_style into Theme Engine
cursoragent Sep 7, 2026
befd7b3
test(themes): tighten module style coverage gate
cursoragent Sep 7, 2026
de80378
feat(themes): announce data-uc-role=pane on pane-styled module surfaces
cursoragent Sep 7, 2026
c3d1a0f
feat(themes): complete pane-role adoption for popup and entity wrappers
cursoragent Sep 7, 2026
9dfba71
feat(themes): adopt pane tokens on alarm, solar, light, vacuum, timer…
cursoragent Sep 7, 2026
d018525
feat(themes): adopt pane tokens on vampire, toggle, alert, calendar
cursoragent Sep 8, 2026
0cbf4c0
feat(themes): adopt pane tokens on map, external-card, scroll-row, lu…
cursoragent Sep 8, 2026
0e385ce
feat(themes): pane-token residuals for screensaver, status, area, app…
cursoragent Sep 8, 2026
46477b6
feat(themes): pane-fallback remaining live color-mix and solid surfaces
cursoragent Sep 8, 2026
8773b99
feat(themes): complete pane coverage for remaining module surfaces
cursoragent Sep 8, 2026
856cb6e
Release 3.10.0-beta6
cursoragent Sep 8, 2026
f884f75
theme builder preview: brightness label over the bar fill mirrors the…
WJDDesigns Sep 8, 2026
e041a53
plugin 1.3.38: repackage with the preview bar-label fix
WJDDesigns Sep 8, 2026
7cae912
themes: Beach shell no longer clipped at the dome (viewBox gave the a…
WJDDesigns Sep 8, 2026
9704eb3
themes: Metallic is a brushed-aluminium plate with spun-metal control…
WJDDesigns Sep 8, 2026
f3bed67
Metallic: panes are spun aluminium like the controls, a shade lighter…
WJDDesigns Sep 8, 2026
90421f8
test: Metallic pane recipe is metallic now
WJDDesigns Sep 8, 2026
908fd9d
Metallic: the plate is the darker alloy; panes carry the same brushin…
WJDDesigns Sep 8, 2026
509ef09
Metallic: spun aluminium all the way down; the plate and panes take t…
WJDDesigns Sep 8, 2026
7251f45
Metallic: module backdrops drawn with HA's secondary/primary backgrou…
WJDDesigns Sep 8, 2026
15506f4
editor: Design tab overhaul — single responsive-aware update path, sh…
WJDDesigns Sep 8, 2026
03498af
Merge tag v3.10.0-beta6 (Theme Engine pane coverage) into feat/esm-mu…
WJDDesigns Sep 8, 2026
d957020
Release 3.10.0-beta7
WJDDesigns Sep 8, 2026
fdcc6ce
Release 3.10.0-beta8
WJDDesigns Sep 8, 2026
56a3beb
Release 3.10.0-beta9
WJDDesigns Sep 8, 2026
d8e1016
release: only the tag workflow creates GitHub releases, as a draft pu…
WJDDesigns Sep 8, 2026
3c8f106
fix: let Button height:100% fill fixed Stack Overlay layers
WJDDesigns Sep 8, 2026
1305122
fix: entity chip list dropped the picked entity on newer HA frontends
cursoragent Sep 8, 2026
e60c4fe
checkpoint before checking out feat/esm-multi-file-phase1
WJDDesigns Sep 8, 2026
e4bbf82
feat: Boiler and Train Departures Pro modules
WJDDesigns Sep 8, 2026
974c626
train: head-on bogie and receding track, legible LED train
WJDDesigns Sep 8, 2026
29b5f10
train: track is a perspective plane, near edge toward the viewer
WJDDesigns Sep 9, 2026
26f3b47
train: sleepers roll toward the wheels; drop the bogie bar
WJDDesigns Sep 9, 2026
4328f9a
test: refresh button surface goldens after the Stack Overlay height fix
WJDDesigns Sep 9, 2026
d15a3d3
Release 3.10.0-beta10
WJDDesigns Sep 9, 2026
632e895
chore: fold leftover PRs into the working branch
WJDDesigns Sep 9, 2026
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
17 changes: 17 additions & 0 deletions .cursor/environment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "Ultra Card",
"install": "bash .cursor/install.sh",
"terminals": [
{
"name": "demo-server",
"command": "python3 -m http.server 8765 --bind 0.0.0.0",
"description": "Static server for the standalone card demo. Open http://localhost:8765/website/_local-preview.html?p=modules-page-embed.html (also template-mode-page-embed.html and presets-page-embed.html). Run 'npm run build:demo' to refresh dist-demo/ultra-card-demo.js after changing source."
}
],
"ports": [
{
"name": "demo server",
"port": 8765
}
]
}
23 changes: 23 additions & 0 deletions .cursor/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
#
# Cloud Agent install script for Ultra Card.
# Idempotent: safe to run repeatedly against cached state.
set -euo pipefail

# package.json pins "engines.node": ">=24.15.0" and CI runs on Node 24
# (jsdom 30 used by the test suite requires it). The base image ships an older
# Node, so install the required version with nvm and make it the login default.
NODE_VERSION="24.15.0"

export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
# shellcheck disable=SC1091
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

nvm install "$NODE_VERSION"
nvm alias default "$NODE_VERSION"
nvm use "$NODE_VERSION"

echo "Using Node $(node --version) / npm $(npm --version)"

# Reproducible install from the committed lockfile.
npm ci
52 changes: 39 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,20 @@ jobs:
cat release_notes.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Releases created below with the default GITHUB_TOKEN do NOT fire the
# `release: published` event (GitHub suppresses events from GITHUB_TOKEN
# to prevent workflow loops), so announce-release.yml never runs for
# tag-push releases. Record whether the release already exists so we can
# dispatch the announcement manually only when this workflow creates it.
# A release must never be visible to HACS without its assets. With
# content_in_root=false HACS looks for ultra-card.js among the release
# assets; when the release exists but the upload has not happened yet it
# falls back to the repo root, where ultra-card.js is committed but the
# uc-*.js chunks are gitignored. Users then get a new entry file with no
# chunks: no editor, modules stuck loading, and a permanent "Ultra Card
# was updated, reload" toast (3.10.0-beta8 and the first minutes of
# beta9). So: create the release as a DRAFT, attach every asset, and only
# then publish. HACS ignores drafts. `scripts/release.js` no longer
# creates the release itself for the same reason.
#
# Record whether a release already existed (e.g. created by hand) so the
# Discord announcement is only dispatched for releases this workflow
# publishes; a hand-made publish already fired `release: published`.
- name: Check if release already exists
id: existing_release
env:
Expand All @@ -134,15 +143,16 @@ jobs:
echo "exists=false" >> $GITHUB_OUTPUT
fi

- name: Create GitHub Release
- name: Create draft release and upload assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: What's New in ${{ steps.version.outputs.VERSION }}
draft: false
draft: true
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
generate_release_notes: false
body: ${{ steps.release_notes.outputs.RELEASE_NOTES }}
fail_on_unmatched_files: true
# Every asset listed here is downloaded flat into each user's
# www/community/Ultra-Card/ by HACS (content_in_root=false ->
# release mode). Ship only files the browser needs; no zip.
Expand All @@ -154,13 +164,29 @@ jobs:
uc-*.js
uc-*.js.LICENSE.txt

# Belt and braces: refuse to publish unless the entry file and at least
# one chunk are actually attached. A draft that fails here stays a draft
# (invisible to HACS) and can be inspected on the Releases page.
- name: Verify release assets before publishing
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ASSETS=$(gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" --json assets -q '.assets[].name')
echo "$ASSETS"
echo "$ASSETS" | grep -qx 'ultra-card.js' || { echo "::error::ultra-card.js is not attached to the release"; exit 1; }
echo "$ASSETS" | grep -q '^uc-.*\.js$' || { echo "::error::no uc-*.js chunks attached to the release"; exit 1; }
echo "Attached assets: $(echo "$ASSETS" | wc -l)"

- name: Publish release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release edit "${{ github.ref_name }}" --repo "${{ github.repository }}" --draft=false

# `announce-release.yml` is the single source of truth for the Discord
# announcement. When the release was created by the local release script
# (user credentials), the `release: published` event fires and announces
# on its own; this workflow only updates that release, so we must NOT
# dispatch here or Discord would get a duplicate. When the release is
# created by THIS workflow (plain tag push), GITHUB_TOKEN suppresses the
# event, so we dispatch the announcement manually.
# announcement. Publishing with GITHUB_TOKEN does not fire the
# `release: published` event (GitHub suppresses events from GITHUB_TOKEN
# to prevent workflow loops), so dispatch it manually. Skip when the
# release pre-existed: that publish already announced itself.
- name: Announce release to Discord
if: steps.existing_release.outputs.exists == 'false'
env:
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ yarn-error.log*
.idea

# Cursor IDE
.cursor/
.cursor/*
# Track the Cloud Agent dev environment config
!.cursor/environment.json
!.cursor/install.sh

# Planning and implementation documents
*_PLAN.md
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ https://github.com/user-attachments/assets/e9f28eee-e587-4bc0-ad0b-cea53a3fa5a6

**Visual editor** - Every setting lives in the UI. No YAML required.

**Ultra Dashboard** - A complete dashboard from your areas in one click (Settings → Dashboards → Add dashboard → Community dashboards). Pick a style, take control, and every card opens in the visual editor. [Read more](docs/ultra-dashboard.md).

**94 modules** - Layouts, gauges, graphs, controls, media, and more. Drag-and-drop columns with nesting so you can build the layout you want.

**Template Mode** - Jinja2 templates that change how a module looks as your entities change. Free for everyone.
Expand Down
Loading
Loading