<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Playnite on Glass Ball in a Plastic World</title><link>/en/tags/playnite/</link><description>Recent content in Playnite on Glass Ball in a Plastic World</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><copyright>hugsyf</copyright><lastBuildDate>Fri, 31 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="/en/tags/playnite/index.xml" rel="self" type="application/rss+xml"/><item><title>From Dune to Dune Rev: Expanding a Playnite Theme</title><link>/en/post/26-07-31-dune-rev/</link><pubDate>Fri, 31 Jul 2026 00:00:00 +0000</pubDate><guid>/en/post/26-07-31-dune-rev/</guid><description>&lt;img src="/post/26-07-31-dune-rev/details-view.png" alt="Featured image of post From Dune to Dune Rev: Expanding a Playnite Theme" /&gt;&lt;p&gt;I have been using &lt;a class="link" href="https://playnite.link/" target="_blank" rel="noopener"&#10; &gt;Playnite&lt;/a&gt; to manage my game library. Among its Desktop themes,&#10;&lt;a class="link" href="https://github.com/sakasakiking/Dune" target="_blank" rel="noopener"&#10; &gt;Dune&lt;/a&gt; fits my taste especially well: spacious composition, rounded&#10;cards, clean visual hierarchy, and an unmistakable WinUI 3 / Fluent Design influence. Unfortunately, it is&#10;a relatively new theme, and its extension compatibility falls well short of more mature alternatives. Some&#10;extension pages rendered black text on black surfaces, while other extensions had nowhere to appear at all.&lt;/p&gt;&#10;&lt;p&gt;Over the course of a day, Codex and I gradually turned it into &lt;strong&gt;&lt;a class="link" href="https://github.com/hugsyf/dune-rev" target="_blank" rel="noopener"&#10; &gt;Dune Rev&lt;/a&gt;&lt;/strong&gt;: a personal fork maintained by me&#10;that preserves the original visual language while adding extension integration and much more control over the&#10;layout.&lt;/p&gt;&#10;&lt;figure&gt;&#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &lt;img src="/post/26-07-31-dune-rev/details-view.png"&#10; alt="Dune Rev Details View"&#10; width="1200em"&#10; &#10; &#10; &#10; &gt;&#10;&#10; &lt;figcaption&gt;Dune Rev's Details View; summary cards and extension content adapt to the available data&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;h2 id="the-starting-point-a-beautiful-theme-with-an-incomplete-ecosystem"&gt;The Starting Point: A Beautiful Theme with an Incomplete Ecosystem&#10;&lt;/h2&gt;&lt;p&gt;Dune originally advertised support for SuccessStory, HowLongToBeat, Extra Metadata Loader, and&#10;ScreenshotsVisualizer. That was a solid foundation, but my everyday setup uses far more extensions. As a&#10;reference, Mythic already offered mature integration for BackgroundChanger, DuplicateHider, GameActivity,&#10;Library Management, ThemeExtras, Steam news and reviews, ThemeModifier, and more.&lt;/p&gt;&#10;&lt;p&gt;The first visible problem was simply &amp;ldquo;the colors in extension settings are wrong.&amp;rdquo; Once I started inspecting&#10;the XAML, however, it became clear that adding a few brushes would not be enough. A Playnite theme does not&#10;only define appearance; it also hosts plugin controls and supplies resource dictionaries, visibility rules,&#10;and layout contracts. A missing resource key can make text unreadable. An incorrectly named&#10;&lt;code&gt;ContentControl&lt;/code&gt; can prevent an extension from injecting anything. Two views sharing one playback state can&#10;even produce a bug that appears only after switching back and forth between them.&lt;/p&gt;&#10;&lt;h2 id="making-extension-data-part-of-the-theme"&gt;Making Extension Data Part of the Theme&#10;&lt;/h2&gt;&lt;p&gt;I did not want to solve the problem by stacking every plugin panel at the bottom of the page. Extension data&#10;should look like a native part of Dune, so I reorganized the Details View summary area. Last played, total play&#10;time, completion status, achievements, activity, HowLongToBeat, and SystemChecker now share the same card&#10;language.&lt;/p&gt;&#10;&lt;p&gt;The cards follow a few rules:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;A card disappears when its extension is unavailable or the selected game has no corresponding data.&lt;/li&gt;&#10;&lt;li&gt;The remaining cards wrap automatically instead of leaving empty holes.&lt;/li&gt;&#10;&lt;li&gt;Cards that open an extension view have a hover animation to communicate that they are interactive.&lt;/li&gt;&#10;&lt;li&gt;The HowLongToBeat card shows only Main Story, avoiding a cramped row of Main, Main+, and 100% values.&lt;/li&gt;&#10;&lt;li&gt;Full charts, progress bars, and lists remain available in dedicated tabs below the summary.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Playnite Achievements turned out to be a special case. It already includes its own theme migration system, so&#10;adding another explicit &amp;ldquo;native&amp;rdquo; host actually duplicated or conflicted with the migrated controls. The final&#10;solution lets the extension continue handling migration while the theme supplies the colors and control&#10;resources it expects. It was a useful reminder that extension support does not always mean writing more code;&#10;first, you need to understand what the extension already does.&lt;/p&gt;&#10;&lt;p&gt;Dune Rev currently covers these major integrations:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Feature&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Extension&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Achievements&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SuccessStory and Playnite Achievements automatic migration&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Alternative backgrounds&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;BackgroundChanger&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Duplicate copies&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DuplicateHider&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Feature icons&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Library Management&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Favorites and completion status&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ThemeExtras&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Activity history&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;GameActivity&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Completion estimates&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HowLongToBeat&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Logos and videos&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Extra Metadata Loader&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Screenshots&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ScreenshotsVisualizer&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Steam news and online players&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Steam News and Players Viewer&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Steam reviews&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Review Viewer&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;System requirements&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SystemChecker&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Theme customization&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ThemeModifier&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="the-hard-part-was-state-not-visibility"&gt;The Hard Part Was State, Not Visibility&#10;&lt;/h2&gt;&lt;p&gt;Extra Metadata Loader&amp;rsquo;s logo and video integration produced some representative problems. An early build&#10;showed a game icon instead of its logo in Details View. After fixing the control host, video playback exposed a&#10;more subtle state bug: switch from Details View to Grid-Details View and back, and the hero area could no&#10;longer resume the video, even though playback in Grid View continued to work.&lt;/p&gt;&#10;&lt;p&gt;Both views were using the cached standard player, the same RadioButton group name, and the extension&amp;rsquo;s global&#10;&lt;code&gt;IsVideoPlaying&lt;/code&gt; state. The view changed, but the player host and state were not truly isolated. I ultimately&#10;gave each view an independently configured player instance and its own media-selection group, then bound its&#10;play button to that player&amp;rsquo;s state. This is a neat little WPF/XAML lesson: a control leaving the screen does not&#10;mean its state has disappeared, especially when an extension caches objects beyond the local name scope.&lt;/p&gt;&#10;&lt;h2 id="details-view-and-grid-details-view-are-not-the-same-layout"&gt;Details View and Grid-Details View Are Not the Same Layout&#10;&lt;/h2&gt;&lt;p&gt;Width was the other recurring problem. Details View is naturally a widescreen composition: summary cards and&#10;extension tabs on the left, with developers, publishers, ratings, and features on the right. Grid-Details View&#10;is usually a narrow sidebar beside the cover grid. Treating both as one horizontal layout either lets the&#10;information column consume all available space or crushes every card into a narrow strip.&lt;/p&gt;&#10;&lt;p&gt;The two views therefore ended up with independent dimensions and composition rules:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Details View defaults to a 1760 px maximum content width and a 480 px information column.&lt;/li&gt;&#10;&lt;li&gt;Grid View defaults to a 640 px details pane.&lt;/li&gt;&#10;&lt;li&gt;Summary cards wrap in Grid View, with the information panel placed below them.&lt;/li&gt;&#10;&lt;li&gt;Logo, card, extension-panel, button, and top-bar sizes can all be adjusted independently.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure&gt;&#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &#10; &lt;img src="/post/26-07-31-dune-rev/grid-details-view.png"&#10; alt="Dune Rev Grid Details View"&#10; width="1200em"&#10; &#10; &#10; &#10; &gt;&#10;&#10; &lt;figcaption&gt;Grid-Details View uses a purpose-built narrow-pane layout instead of compressing the widescreen page&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&lt;p&gt;These settings are exposed through ThemeModifier. Its theme-option format currently offers only one&#10;&lt;code&gt;Description&lt;/code&gt; string rather than localized names, so I used consistent &lt;code&gt;English / 简体中文&lt;/code&gt; labels and grouped&#10;them into Global Layout, Details View, Grid View, Extension Panels, and Grid Cover sections. The final result&#10;contains 26 audited options that are genuinely consumed by the theme, rather than sliders that appear in the&#10;settings page without affecting anything.&lt;/p&gt;&#10;&lt;h2 id="why-fluent-dim"&gt;Why Fluent Dim?&#10;&lt;/h2&gt;&lt;p&gt;Dune already warned that its dark mode could have problems. The deeper issue is that Playnite 10 does not&#10;provide extension-injected controls with one reliable, shared light/dark state. The theme&amp;rsquo;s own controls may&#10;switch correctly while a migrated or injected extension page does not. The result is often light text on a&#10;light background or black text on a dark one.&lt;/p&gt;&#10;&lt;p&gt;Instead of maintaining two palettes that would always be partially broken, I settled on a single&#10;&lt;strong&gt;Fluent Dim&lt;/strong&gt; palette. It is more comfortable at night than a conventional light theme without becoming a&#10;high-contrast pure-black theme. Dark blue-gray surfaces, softer white text, and translucent Fluent layers keep&#10;the appearance subdued. Giving up the mode switch buys much more consistent rendering across the main window,&#10;settings dialogs, and extension content.&lt;/p&gt;&#10;&lt;h2 id="turning-a-local-modification-into-a-publishable-fork"&gt;Turning a Local Modification into a Publishable Fork&#10;&lt;/h2&gt;&lt;p&gt;As the changes grew, it no longer made sense to treat the project as a local patch. I named it &lt;strong&gt;Dune Rev&lt;/strong&gt;,&#10;generated a new GUID, updated its theme identity, author, and repository links, and prepared a README,&#10;CHANGELOG, &lt;code&gt;.gitignore&lt;/code&gt;, licenses, and Playnite Add-on and Installer manifests.&lt;/p&gt;&#10;&lt;p&gt;The original project uses the MIT License, which permits forking and redistribution as long as the original&#10;copyright and license notice remain. Dune Rev retains sakasakiking&amp;rsquo;s copyright notice and adds my copyright for&#10;the modifications.&lt;/p&gt;&#10;&lt;p&gt;The release candidate also went through several layers of validation:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;XML parsing for every XAML file.&lt;/li&gt;&#10;&lt;li&gt;Resource-dictionary loading in the real order using Playnite&amp;rsquo;s 32-bit assemblies.&lt;/li&gt;&#10;&lt;li&gt;A Release build with no compilation errors.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;.pthm&lt;/code&gt; packaging with Playnite Toolbox followed by a package-content check.&lt;/li&gt;&#10;&lt;li&gt;Cross-checking ThemeModifier options, manifests, screenshots, and download URLs.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;The 1.0.0 package is now ready. The remaining release steps are to create a GitHub Release and submit the&#10;Add-on manifest to the official&#10;&lt;a class="link" href="https://github.com/JosefNemec/PlayniteAddonDatabase" target="_blank" rel="noopener"&#10; &gt;PlayniteAddonDatabase&lt;/a&gt;, which is how a theme enters&#10;Playnite&amp;rsquo;s built-in add-on browser.&lt;/p&gt;&#10;&lt;h2 id="conclusion"&gt;Conclusion&#10;&lt;/h2&gt;&lt;p&gt;This work began as an attempt to fix the colors on a few extension pages and ended as a complete review of the&#10;theme&amp;rsquo;s layouts, plugin data, state management, and release process. It also demonstrates an interesting part&#10;of Playnite theme development: XAML is not merely a skin. It is a user-interface protocol between the core&#10;application and a collection of independently developed extensions.&lt;/p&gt;&#10;&lt;p&gt;Dune Rev still looks like the Dune theme I liked in the first place, but it now feels much more like a complete&#10;theme I can use long-term. More importantly, it has evolved from a collection of modifications on my computer&#10;into an open-source project with its own identity—one that can be validated, updated, and published for others&#10;to use.&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;This post was co-written by GPT-5.6 Sol High and me.&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;</description></item></channel></rss>