[{"data":1,"prerenderedAt":311},["ShallowReactive",2],{"blog-\u002Fblog\u002Fbuilding-kitsu-desktop-with-tauri":3},{"article":4,"newer":292,"older":308},{"id":5,"title":6,"body":7,"canonical":292,"date":293,"description":294,"draft":292,"extension":295,"image":292,"imageAlt":292,"meta":296,"navigation":297,"path":298,"seo":299,"status":300,"stem":301,"tags":302,"updated":292,"__hash__":307},"blog\u002Fblog\u002Fbuilding-kitsu-desktop-with-tauri.md","Building Kitsu Desktop with Tauri: A Pipeline TD's First Look at Rust",{"type":8,"value":9,"toc":280},"minimark",[10,14,25,28,33,68,87,91,94,100,103,106,109,113,116,119,122,127,130,134,137,160,163,166,170,173,176,179,183,186,196,199,202,205,208,212,215,218,221,224,227,230,234,237,240,243,246,249,253,256,259,262,265,268,271],[11,12,13],"p",{},"Most of my development work happens inside python pipelines.\nRust was outside my usual stack.",[11,15,16,17,24],{},"I had been curious about Tauri, so I decided to test it on a real problem instead of building another tutorial app: could I turn ",[18,19,23],"a",{"href":20,"rel":21},"https:\u002F\u002Fwww.cg-wire.com\u002Fkitsu",[22],"nofollow","CGWire Kitsu"," into a Windows desktop application?",[11,26,27],{},"Kitsu already works well in a browser. I was not trying to rewrite it. I wanted to find out what a native shell could add around it: a dedicated window, system tray integration, system autostart, connection checks, and notifications.",[29,30,32],"h2",{"id":31},"screenshots","Screenshots",[34,35,36,49],"table",{},[37,38,39],"thead",{},[40,41,42,46],"tr",{},[43,44,45],"th",{},"Kitsu workspace",[43,47,48],{},"Connection settings",[50,51,52],"tbody",{},[40,53,54,62],{},[55,56,57],"td",{},[58,59],"img",{"alt":60,"src":61},"Kitsu workspace open in Kitsu Desktop","\u002Fblog\u002Fkitsu-task-view.png",[55,63,64],{},[58,65],{"alt":66,"src":67},"Kitsu Desktop connection settings","\u002Fblog\u002Fkitsu-settings-connection-status.png",[34,69,70,77],{},[37,71,72],{},[40,73,74],{},[43,75,76],{},"System tray menu",[50,78,79],{},[40,80,81],{},[55,82,83],{},[58,84],{"alt":85,"src":86},"Kitsu Desktop system tray menu","\u002Fblog\u002Fkitsu-desktop-windows-thumbnail.png",[29,88,90],{"id":89},"starting-with-the-wrong-question","Starting with the wrong question",[11,92,93],{},"My first question was simple:",[95,96,97],"blockquote",{},[11,98,99],{},"Can I use Tauri to turn Kitsu into a native desktop app?",[11,101,102],{},"The answer was yes, but the first version still felt like a launcher placed in front of another web app. It had navigation sections, shortcuts, settings, and several ways to open Kitsu.",[11,104,105],{},"At one point it felt like a \"glorified Chrome tab.\" Wrapping a website in a window did not make it feel OS-native.",[11,107,108],{},"That changed the direction of the project. Instead of asking how much interface I could add, I started asking what Windows could provide that the browser could not.",[29,110,112],{"id":111},"keeping-the-scope-narrow","Keeping the scope narrow",[11,114,115],{},"The application initially drifted toward Docker and local Kitsu management. I removed that early.",[11,117,118],{},"Artists should not be starting containers, managing backups, or inspecting server infrastructure from this app. I also avoided turning it into a DCC launcher. this is closer to the role of AYON or another pipeline launcher, not Kitsu.",[11,120,121],{},"The boundary became straightforward:",[95,123,124],{},[11,125,126],{},"The desktop app handles Windows integration. Kitsu handles production management.",[11,128,129],{},"That rule kept the project small and prevented it from becoming another pipeline platform.",[29,131,133],{"id":132},"the-stack","The stack",[11,135,136],{},"The app uses:",[138,139,140,144,147,150,153],"ul",{},[141,142,143],"li",{},"Tauri 2 for the desktop shell;",[141,145,146],{},"Rust for native behavior and connection checks;",[141,148,149],{},"TypeScript and Vite for the settings interface;",[141,151,152],{},"WebView2 to display the existing Kitsu site;",[141,154,155,159],{},[156,157,158],"code",{},"reqwest"," with Rustls for HTTP and HTTPS checks.",[11,161,162],{},"I kept the frontend in plain TypeScript. The settings UI was small enough that adding Vue or another framework would not have solved the interesting problems.",[11,164,165],{},"Most of the experimenting happened on the Rust and Tauri side: application lifecycle, plugins, and native events.",[29,167,169],{"id":168},"what-made-it-feel-native","What made it feel native",[11,171,172],{},"The biggest improvements were not visual.",[11,174,175],{},"The app stays available in the Windows system tray, can start quietly with Windows, and enforces single-instance behavior. Launching it twice focuses the existing application instead of creating duplicate windows.",[11,177,178],{},"Kitsu opens in a separate work window, while profiles, diagnostics, and native settings stay in a smaller settings window.",[29,180,182],{"id":181},"moving-connection-checks-into-rust","Moving connection checks into Rust",[11,184,185],{},"The backend checks both the Kitsu site and the Zou API:",[187,188,194],"pre",{"className":189,"code":191,"language":192,"meta":193},[190],"language-text","\u003CKITSU_URL>\u002F\n\u003CKITSU_URL>\u002Fapi\n","text","",[156,195,191],{"__ignoreMap":193},[11,197,198],{},"The root endpoint confirms that the site responds. The API check also verifies that the response looks like Zou rather than an unrelated page.",[11,200,201],{},"Running these checks through Rust gives the app control over timeouts and error reporting.",[11,203,204],{},"Instead of showing a generic network failure, it can provide more useful messages for connection refusal, DNS problems, certificate failures, timeouts, incorrect ports, or missing VPN access.",[11,206,207],{},"It also produces copyable diagnostics with the application version, platform, configured URL, site status, and API status. That is much more useful when an artist sends a problem to pipeline support.",[29,209,211],{"id":210},"notifications-were-harder-than-expected","Notifications were harder than expected",[11,213,214],{},"I originally wanted task notifications.",[11,216,217],{},"Displaying a native Windows notification through Tauri is easy. Deciding where reliable task events come from is not.",[11,219,220],{},"A proper implementation would need authenticated API access, polling or websocket behavior, deduplication, user identity, and a clear definition of which events deserve an operating-system notification.",[11,222,223],{},"Bundling Kitsu's frontend would not solve that. It would mostly create another frontend to maintain.",[11,225,226],{},"For now, the app only supports connection-state notifications, such as Kitsu becoming unavailable or coming back online.",[11,228,229],{},"That was a useful lesson: calling the native API is often the easy part. Designing a dependable event model is the real work.",[29,231,233],{"id":232},"my-first-impressions-of-rust","My first impressions of Rust",[11,235,236],{},"Coming from Python, Rust initially feels strict. The compiler asks you to be explicit about types, errors, ownership, and platform-specific behavior.",[11,238,239],{},"For quick scripts, that can feel slow. For a desktop application, I started to appreciate it.",[11,241,242],{},"The compiler catches assumptions that might otherwise become runtime bugs, and Tauri encourages a clean boundary: the frontend owns interface state while Rust owns privileged native behavior.",[11,244,245],{},"I did not need to become a Rust expert to build something practical. Most of the backend is made of small functions and Tauri commands.",[11,247,248],{},"That made this project a good introduction. It was complex enough to expose real Rust concepts without also requiring me to design a large backend system.",[29,250,252],{"id":251},"the-app-improved-as-i-removed-things","The app improved as I removed things",[11,254,255],{},"I removed Docker stuff, unnecessary launcher options and frontend bundling that did not justify its maintenance cost.",[11,257,258],{},"I moved secondary actions into the tray and stopped treating the settings window as the main product.",[11,260,261],{},"The final app is smaller than the original idea, but more useful.",[11,263,264],{},"For me, this project was less about making Kitsu \"native\" and more about learning where a desktop shell can add value around an existing web application.",[11,266,267],{},"my initial opinions about Rust from all the googling and reading I did, was that it's an over-hyped new-kid-on-the-block next-big-thing language with some serious fanboyism issues in the dev community.\nIt was also a practical introduction to Rust and Tauri from the perspective of a Pipeline TD.",[11,269,270],{},"I don't think I will need it much in my journey. The VFX, Animation and Gaming industries are all dominated by C++ and python (I don't like Unity)",[11,272,273,274,279],{},"The source is available in the ",[18,275,278],{"href":276,"rel":277},"https:\u002F\u002Fgithub.com\u002FAhmed-Hindy\u002Fkitsu-desktop-launcher",[22],"Kitsu Desktop repository",".",{"title":193,"searchDepth":281,"depth":281,"links":282},2,[283,284,285,286,287,288,289,290,291],{"id":31,"depth":281,"text":32},{"id":89,"depth":281,"text":90},{"id":111,"depth":281,"text":112},{"id":132,"depth":281,"text":133},{"id":168,"depth":281,"text":169},{"id":181,"depth":281,"text":182},{"id":210,"depth":281,"text":211},{"id":232,"depth":281,"text":233},{"id":251,"depth":281,"text":252},null,"2026-07-13","How I used a small Kitsu desktop client to explore Rust and Tauri, and why removing features made the app more useful.","md",{},true,"\u002Fblog\u002Fbuilding-kitsu-desktop-with-tauri",{"title":6,"description":294},"published","blog\u002Fbuilding-kitsu-desktop-with-tauri",[303,304,305,306],"Rust","Tauri","Pipeline","Kitsu","mpJsRlMz3oiYv79mpN3l4GkwX5VkcvIqY0OsuXIK5QQ",{"path":309,"title":310,"date":293},"\u002Fblog\u002Fbuilding-rv-the-easy-way","Building RV the Easy Way: Abusing CI Minutes Instead of Downloading the World",1784707438337]