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
65 changes: 47 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,36 @@ Loader loses the CDP injection path it requires when Millennium runs normally.
> layer, normal Millennium and stock CSS Loader conflict over the external CDP
> mechanism, so CSS Loader does not function correctly in the first place.

## Version 1.0

Version 1.0 is the first stable release of the complete CSS Loader for
Millennium experience: the desktop manager, compatibility backend, direct
runtime publisher, and official Millennium companion.

Its defining advantage is fidelity. Existing CSS Loader themes remain in their
native format and are resolved by CSS Loader's own theme engine. The resulting
styles are delivered directly to Steam without flattening them into converted
Millennium bundles or rewriting valid CSS constructs.

### Main highlights

- Full CSS Loader configuration model: themes, profiles, dependencies, patch
controls, colors, generated variables, enable state, and cascade order.
- Direct CSS delivery that preserves inline SVG, data URLs, animations, local
assets, and advanced CSS exactly as authored.
- Desktop, Big Picture, Quick Access, Main Menu, notification, and popup target
routing through Millennium's supported in-process interfaces.
- Normal Millennium operation with no Steam `-dev` mode, external debugging
port, or `.cef-enable-remote-debugging` marker.
- Overlay behavior that keeps Fluenty, SpaceTheme, Pebble, or another selected
Millennium theme active underneath CSS Loader.
- Desktop management for installed themes, profiles, settings, store browsing,
downloads, updates, and the always-on Windows backend.
- Atomic runtime updates: the companion accepts new state only when its revision
and content hash match.
- Compatibility regression coverage for real-world themes, including nested
inline-SVG filters and `/themes_custom` images and fonts.

## How this resolves the conflict

CSS Loader for Millennium replaces the incompatible injection path while
Expand All @@ -36,7 +66,7 @@ colors, components, class translations, and activation order.
| Stock CSS Loader path | Millennium-compatible replacement |
| --- | --- |
| Creates `.cef-enable-remote-debugging` | Does not create or depend on the marker |
| Requires an externally reachable CDP port | Compiles the selected state into persistent CSS bundles |
| Requires an externally reachable CDP port | Publishes resolved injects to the Millennium companion |
| Needs Millennium's `-dev` mode to expose that port | Works with Millennium's normal runtime mode |
| Injects every Steam document through external CDP | Uses an in-process Millennium overlay plus its controlled per-plugin CDP proxy for isolated BrowserViews |

Expand All @@ -49,27 +79,27 @@ separate browser bridge.

Eliminating the delayed theming flash is an additional benefit of this design,
not the entire purpose of the project. The compatibility runtime persists the
last compiled configuration on disk, and its companion starts as part of
Millennium instead of waiting for a late external standalone injection pass.
latest resolved injection state on disk, and its companion starts as part of
Millennium instead of waiting for an external standalone CDP connection.

## Highlights

- Replaces CSS Loader's external CDP injection path with a Millennium-compatible
generated-theme runtime.
- Replaces CSS Loader's external CDP injection path with ordered, direct style
injection inside Millennium.
- Requires neither Millennium `-dev` mode nor `.cef-enable-remote-debugging`.
- Uses existing themes from `~/homebrew/themes`; no manual conversion required.
- Preserves profiles, dependencies, patch options, colors, CSS variables, local
images/fonts, class translations, and CSS cascade order.
- Defaults to overlay mode, keeping Fluenty, SpaceTheme, Pebble, or another
selected Millennium theme active beneath CSS Loader.
- Produces **CSS Loader (Standalone)** as an optional CSS Loader-only theme and
as the internal host for generated CSS and assets.
- Preserves each resolved inject as CSS text instead of flattening it into a
rewritten bundle.
- Bundles the backend and the separately maintained
[CSS Loader Companion for Millennium](https://github.com/DevsNate/CSSLoader-Companion-Millennium)
inside one desktop installer.
- Bootstraps a new `%USERPROFILE%\homebrew\themes` library automatically; Decky
or a pre-existing CSS Loader installation is not required.
- Reloads the generated theme when settings or watched CSS files change.
- Republishes direct runtime state when settings or watched CSS files change.
- Keeps Desktop, Big Picture, Quick Access, Main Menu, and notification targets
separate, matching CSS Loader's real document routing.

Expand All @@ -96,20 +126,19 @@ reference warning in [Compatibility verification](docs/verification.md).
1. Install Millennium and start Steam once so Millennium creates its config.
2. Download and install the latest MSI from this repository's Releases page.
3. Open **CSS Loader for Millennium**. First-run setup creates the theme library,
installs the backend and companion, and generates a valid empty overlay.
4. Leave your preferred Millennium theme selected. The generated **CSS Loader
(Standalone)** entry is optional and is only needed for CSS Loader-only mode.
installs the backend and companion, and publishes a valid empty state.
4. Leave your preferred Millennium theme selected; CSS Loader is layered over it.
5. Restart Steam once, then manage themes, profiles, and every patch option from
the desktop app.

The installer places the backend in the current user's Windows Startup folder,
copies and enables the companion in Steam, and creates
`%USERPROFILE%\homebrew\themes` when it does not exist. Your generated
configuration stays active at Steam startup even while the desktop app and
backend are closed.
`%USERPROFILE%\homebrew\themes` when it does not exist. The backend publishes
the app's resolved state and the companion applies it inside Steam.

The local `Steam\millennium\themes\CSS Loader` folder is generated uniquely for
each user. It is an asset host, not a separately published Marketplace theme.
each user. It is a runtime-state mailbox, not a separately published Marketplace
theme.
See [Clean installation](docs/clean-installation.md) for the complete first-run
contract and migration behavior.

Expand Down Expand Up @@ -144,7 +173,7 @@ available for `build:backend`, `build:plugin`, and `sync:desktop`.

| Path | Purpose |
| --- | --- |
| `runtime/backend` | CSS Loader compatibility logic and generated-theme compiler |
| `runtime/backend` | CSS Loader compatibility logic and direct-state publisher |
| `plugins/millennium` | Pinned [CSS Loader Companion for Millennium](https://github.com/DevsNate/CSSLoader-Companion-Millennium) submodule used for MSI builds |
| `apps/desktop` | Tauri theme manager and bundled installer |
| `tools/audit` | Reference capture, parity, and Steam class-map auditing |
Expand All @@ -168,8 +197,8 @@ runtime and desktop projects; see [Attribution and provenance](NOTICE.md).

| Repository | Purpose |
| --- | --- |
| [`CSSLoader-Millennium`](https://github.com/DevsNate/CSSLoader-Millennium) | Desktop app, CSS Loader-compatible backend, installer, compiler, and verification |
| [`CSSLoader-Companion-Millennium`](https://github.com/DevsNate/CSSLoader-Companion-Millennium) | Millennium Marketplace plugin that applies the generated output inside Steam |
| [`CSSLoader-Millennium`](https://github.com/DevsNate/CSSLoader-Millennium) | Desktop app, CSS Loader-compatible backend, installer, runtime publisher, and verification |
| [`CSSLoader-Companion-Millennium`](https://github.com/DevsNate/CSSLoader-Companion-Millennium) | Millennium Marketplace plugin that applies resolved CSS Loader injects inside Steam |

## License

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/package-lock.json

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

2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@css-loader-for-millennium/desktop",
"version": "0.2.0",
"version": "1.0.0",
"private": true,
"description": "Desktop theme manager and installer for CSS Loader on Millennium.",
"author": "Nate and contributors",
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src-tauri/Cargo.lock

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

2 changes: 1 addition & 1 deletion apps/desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "css-loader-for-millennium"
version = "0.2.0"
version = "1.0.0"
description = "Desktop theme manager and installer for CSS Loader on Millennium"
authors = ["Nate and contributors"]
license = "GPL-3.0-only"
Expand Down
51 changes: 27 additions & 24 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,47 @@ flowchart LR
T["Existing CSS Loader themes"] --> R["Python compatibility runtime"]
C["Profiles and patch settings"] --> R
M["Steam class translations"] --> R
R --> G["Generated CSS bundles and asset host"]
G --> P["Millennium overlay companion"]
R --> G["Ordered direct-injection state"]
G --> P["Millennium companion"]
P --> D["Desktop and Big Picture"]
P --> I["Quick Access, Main Menu, notifications"]
S["Selected Millennium theme"] --> D
S --> I
A["Desktop manager"] --> R
```

## Runtime compiler
## Runtime publisher

`runtime/backend` retains CSS Loader's manifest reader, dependency handling,
patch components, profiles, class translation, and theme-store integration. It
compiles enabled payloads in activation order, rewrites local asset URLs, and
writes a Millennium-served asset host whose optional selector entry is named
**CSS Loader (Standalone)**.
publishes every enabled payload in activation order without flattening bundles,
rewriting asset URLs, or parsing nested CSS constructs. File-backed injects are
read from their original source so legacy JavaScript-string escaping cannot
leak into the direct protocol.

The generated bundles are persisted on disk, so the desktop manager does not
need to be running when Steam starts. Overlay mode leaves the user's selected
Millennium theme untouched and layers the last compiled CSS Loader state over
it. Selecting **CSS Loader (Standalone)** remains available for a CSS
Loader-only presentation.
CSS Loader's existing `/themes_custom/...` contract is preserved. When Steam's
`themes_custom` path is not linked to the homebrew library, the publisher mirrors
active theme files there without modifying their CSS.

The publisher atomically writes `runtime-state.json` followed by a small
`build-report.json` revision. The companion accepts a state only when both
content hashes match. The user's selected Millennium theme remains untouched,
and CSS Loader's ordered style elements are layered over it.

## Millennium companion

The separately maintained
[CSS Loader Companion for Millennium](https://github.com/DevsNate/CSSLoader-Companion-Millennium),
pinned into this repository at `plugins/millennium` for release builds, is the
primary overlay runtime. It synchronizes Desktop
and Big Picture directly inside Steam, then reaches Quick Access, Main Menu,
and notification toasts through Millennium's per-plugin Chrome DevTools
Protocol proxy because those targets live in isolated BrowserViews.
primary runtime. It reconciles individual `<style>` elements in Desktop and Big
Picture, then does the same for Quick Access, Main Menu, and notification toasts
through Millennium's per-plugin Chrome DevTools Protocol proxy because those
targets live in isolated BrowserViews.

This is not an external CDP setup: the project does not open port 8080, require
Millennium `-dev` mode, or run a separate browser bridge. The generated theme
directory is a persistent content host; it does not need to be the active
Millennium theme.
directory is only a local runtime-state mailbox; it does not need to be the
active Millennium theme.

## Desktop manager

Expand All @@ -64,14 +68,13 @@ unrelated upstream backend.

On a clean machine, first launch is an idempotent bootstrap: it creates the
theme library, copies the backend, installs or migrates the companion, preserves
the selected Millennium theme, and then starts the compiler. The generated
Millennium theme folder is user-specific runtime output and is not published as
a theme repository.
the selected Millennium theme, and then starts the publisher. The local runtime
folder is user-specific output and is not published as a theme repository.

## Data flow and ordering

CSS Loader's cascade order is observable behavior. Toggling a component removes
its old payload and appends its replacement, so the compiler tracks activation
order rather than sorting by theme name or file path. Target bundles are kept
separate; Quick Access or Main Menu CSS is never folded into Big Picture merely
because all three are gamepad UI surfaces.
its old payload and appends its replacement, so the publisher tracks activation
order rather than sorting by theme name or file path. Each payload retains its
own target match; Quick Access or Main Menu CSS is never folded into Big Picture
merely because all three are gamepad UI surfaces.
27 changes: 15 additions & 12 deletions docs/clean-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ Opening the desktop app performs one idempotent setup operation:
3. Copy the bundled backend into the current user's Windows Startup folder.
4. Install **CSS Loader Companion** into Millennium's plugin directory.
5. Enable `css-loader-companion` while preserving the selected Millennium theme.
6. Start the backend, fetch CSS class translations, and generate a valid empty
overlay when no themes have been installed yet.
6. Start the backend, fetch CSS class translations, and publish a valid empty
direct runtime state when no themes have been installed yet.

The first empty theme library normally contains only:

Expand All @@ -29,22 +29,25 @@ The first empty theme library normally contains only:
The `STORE` configuration file is created when the user first saves a setting
or profile.

## Generated output
## Runtime output

The backend writes the user's current combination to:

```text
%STEAM%\millennium\themes\CSS Loader
```

This directory is a local asset host. Its bundles, copied images, fonts, build
report, and optional **CSS Loader (Standalone)** selector are generated from the
current user's themes and settings. It is deliberately not distributed as a
public Millennium theme.
This directory is a local mailbox containing `runtime-state.json`, a matching
build report, and a metadata-only `skin.json`. The state contains CSS Loader's
resolved, ordered injects without bundle conversion or asset rewriting. It is
deliberately not distributed as a public Millennium theme.

Regeneration removes bundles and copied theme assets that are no longer part of
the selected profile. The last valid build remains usable by the companion when
the desktop app and backend are closed.
Local images and fonts continue using CSS Loader's `/themes_custom/...` path.
The backend links that path to the homebrew library when possible and otherwise
mirrors active theme files into the existing custom directory.

Republishing atomically replaces the previous state. The companion only accepts
it when the state and report hashes match.

## Upgrade migration

Expand All @@ -55,12 +58,12 @@ Versions before 0.2.0 installed the plugin as `css-loader-runtime`. Setup now:
3. removes the old plugin directory after the new files are in place;
4. retains a one-time `config.json.css-loader-backup` beside Millennium's config.

All theme downloads, profiles, patch values, and generated configuration remain
All theme downloads, profiles, patch values, and runtime configuration remain
in the user's theme library.

## Companion-first installation

If a user installs CSS Loader Companion from Millennium before installing the
desktop app, the plugin waits safely and displays a link to the complete
installer. Opening the desktop app completes setup and creates the user-specific
generated output.
runtime state.
51 changes: 51 additions & 0 deletions docs/releases/v1.0.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# CSS Loader for Millennium 1.0.0

CSS Loader for Millennium 1.0 is the first stable release of the complete
Windows desktop application, CSS Loader-compatible backend, installer, and
Millennium companion integration.

## Highlights

- Runs existing CSS Loader themes without converting their manifests or option
models into a limited Millennium theme format.
- Preserves profiles, dependencies, multi-theme layering, patch values, color
pickers, sliders, checkboxes, generated CSS variables, and activation order.
- Publishes resolved styles as ordered direct injections rather than rewritten
bundles, preserving inline SVG, data URLs, animations, masks, filters, and
other advanced CSS.
- Applies themes across Desktop, Big Picture, Quick Access, Main Menu,
notifications, and popup documents.
- Works with Millennium's normal runtime: no Steam `-dev` mode, external CDP
port, or deprecated `.cef-enable-remote-debugging` marker.
- Layers CSS Loader over the user's selected Millennium theme instead of taking
ownership of the active-theme setting.
- Keeps `/themes_custom` images and fonts available by linking or mirroring
active theme assets without modifying their CSS.
- Provides the desktop theme manager, profile controls, store browsing,
downloads, updates, live settings, startup integration, and diagnostics in a
single installer.

## Why direct injection matters

Earlier preview builds compiled active themes into generated CSS bundles. That
approach could misinterpret valid nested CSS such as an SVG filter reference
inside a data URL. Version 1.0 removes that conversion boundary. The backend
uses CSS Loader's own parser and class translation, publishes each resolved
inject in cascade order, and lets the companion apply the exact CSS text.

## Advantages

- Existing theme libraries work without manual migration.
- Theme authors do not need a Millennium-specific manifest.
- Complex CSS is less likely to be altered by an intermediary compiler.
- The desktop app remains the single source of truth for store, configuration,
dependency, and profile behavior.
- The companion stays small and focused on applying state inside Steam.
- Matching state and revision hashes prevent partially published updates from
reaching the UI.

## Included artifacts

- Windows x64 MSI installer
- CSS Loader for Millennium backend executable
- Bundled CSS Loader Companion for Millennium 1.0.0
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "css-loader-for-millennium",
"version": "0.2.0",
"version": "1.0.0",
"private": true,
"description": "A CSS Loader overlay runtime and desktop manager for Millennium on Windows.",
"license": "GPL-3.0-only",
Expand Down
2 changes: 1 addition & 1 deletion plugins/millennium
4 changes: 2 additions & 2 deletions runtime/backend/build_millennium_theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@


def main() -> None:
parser = argparse.ArgumentParser(description="Build the CSS Loader for Millennium overlay from existing CSS Loader themes.")
parser = argparse.ArgumentParser(description="Publish direct CSS Loader state for the Millennium companion.")
parser.add_argument(
"--output",
type=Path,
default=default_millennium_theme_path(),
help="Destination for the generated Millennium CSS and asset host.",
help="Destination for the Millennium runtime state files.",
)
args = parser.parse_args()
report = asyncio.run(build_from_disk(args.output))
Expand Down
Loading