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