<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tsiry Sandratraina</title>
    <description>The latest articles on DEV Community by Tsiry Sandratraina (@tsirysndr).</description>
    <link>https://dev.to/tsirysndr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F942533%2F8f6846b4-4902-4959-8121-05a150ff0abb.png</url>
      <title>DEV Community: Tsiry Sandratraina</title>
      <link>https://dev.to/tsirysndr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tsirysndr"/>
    <language>en</language>
    <item>
      <title>Bringing Rockbox's Legendary Audio Engine to the Modern Desktop: A Native Port for Linux and macOS</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Sun, 21 Dec 2025 10:01:39 +0000</pubDate>
      <link>https://dev.to/tsirysndr/bringing-rockboxs-legendary-audio-engine-to-the-modern-desktop-a-native-port-for-linux-and-macos-4hih</link>
      <guid>https://dev.to/tsirysndr/bringing-rockboxs-legendary-audio-engine-to-the-modern-desktop-a-native-port-for-linux-and-macos-4hih</guid>
      <description>&lt;p&gt;Remember the iPod Classic era? Back in 2010, I installed Rockbox on mine and was completely blown away. The default Apple firmware was fine, but Rockbox unlocked a whole new level of audio goodness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-quality parametric equalizer&lt;/li&gt;
&lt;li&gt;Seamless crossfading&lt;/li&gt;
&lt;li&gt;Advanced audio filters and DSP effects&lt;/li&gt;
&lt;li&gt;Gapless playback, replay gain, and so much more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It turned my iPod into an audiophile's dream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftemlhp6j3vicxoyxk378.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftemlhp6j3vicxoyxk378.png" alt=" " width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fast forward to today: I no longer own an iPod, but my music library is bigger than ever, living on my Linux desktop and MacBook. I've tried pretty much every desktop music player out there - Clementine, Strawberry, Rhythmbox, even the big commercial ones, and none of them quite match that &lt;strong&gt;Rockbox audio quality&lt;/strong&gt;. I missed it badly.&lt;/p&gt;

&lt;p&gt;So, I decided to do something about it: port Rockbox to run natively on desktop Linux and macOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Idea: Keep the Engine, Ditch the Old UI
&lt;/h2&gt;

&lt;p&gt;Rockbox's audio processing core is incredible—it's lightweight, highly efficient, and packed with pro-level DSP features. The good news? All of that works perfectly when ported.&lt;/p&gt;

&lt;p&gt;The challenge?  Rockbox's UI was designed for low-res embedded screens (e.g., the iPod Classic's 320x240 pixels). It looks tiny and outdated on a modern 1080p+ desktop display.&lt;/p&gt;

&lt;p&gt;My solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run Rockbox in headless mode (completely disable the default SDL-- based GUI).&lt;/li&gt;
&lt;li&gt;Build a brand-new, native graphical interface on top:

&lt;ul&gt;
&lt;li&gt;GTK+ for Linux (integrates beautifully with GNOME, KDE, etc.)&lt;/li&gt;
&lt;li&gt;SwiftUI for macOS (modern, responsive, and feels right at home)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This way, you get the unbeatable Rockbox audio engine with a clean, modern UI that scales properly on big screens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ln394yvh59r518qfh2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ln394yvh59r518qfh2y.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Status &amp;amp; What's Coming
&lt;/h2&gt;

&lt;p&gt;The project is actively under development, and the core audio features are already there and sounding amazing. Playlist handling, library scanning, and playback work great.&lt;/p&gt;

&lt;p&gt;On the roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enhanced playlist management and search&lt;/li&gt;
&lt;li&gt;Cross-device music library sync&lt;/li&gt;
&lt;li&gt;Built-in scrobbling support (Rocksky)&lt;/li&gt;
&lt;li&gt;Cross-platform sync improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's 100% open source, and contributions are very welcome—whether it's code, testing, UI ideas, or packaging help.&lt;br&gt;
Check it out, star the repo, try it, and let me know what you think!&lt;br&gt;
&lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/tsirysndr/rockbox-zig" rel="noopener noreferrer"&gt;https://github.com/tsirysndr/rockbox-zig&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Tangled Repo:&lt;/strong&gt; &lt;a href="https://tangled.org/tsiry-sandratraina.com/rockbox-zig" rel="noopener noreferrer"&gt;https://tangled.org/tsiry-sandratraina.com/rockbox-zig&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters to Me (and Maybe to You)
&lt;/h2&gt;

&lt;p&gt;If you're an audio enthusiast running Linux or macOS and tired of compromising on sound quality, this could be the player you've been waiting for. Rockbox has been around forever for a reason, its DSP is still unmatched in many ways.&lt;/p&gt;

&lt;p&gt;What about you? What's your current desktop music player? Do you miss any specific Rockbox features? Drop a comment, I'd love to hear your thoughts, suggestions, or even war stories from the iPod modding days!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>opensource</category>
      <category>swift</category>
      <category>zig</category>
    </item>
    <item>
      <title>How I Built My Own Last.fm Clone on Bluesky’s AT Protocol — Join the Beta!</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Thu, 13 Mar 2025 14:24:10 +0000</pubDate>
      <link>https://dev.to/tsirysndr/how-i-built-my-own-lastfm-clone-on-blueskys-at-protocol-join-the-beta-7nj</link>
      <guid>https://dev.to/tsirysndr/how-i-built-my-own-lastfm-clone-on-blueskys-at-protocol-join-the-beta-7nj</guid>
      <description>&lt;p&gt;The idea of tracking and sharing what I listen to has always fascinated me. I’ve been a long-time user of Last.fm, but I wanted something more open, decentralized, and built on modern protocols. That’s why I decided to build my own Last.fm alternative—a social music tracking platform running on Bluesky’s AT Protocol.&lt;/p&gt;

&lt;p&gt;Now, I’m inviting early adopters to join the limited beta and help shape the future of this project! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build a Last.fm Alternative?
&lt;/h2&gt;

&lt;p&gt;Last.fm has been around for years, but I saw some limitations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Walled garden&lt;/strong&gt;: No true interoperability with decentralized social networks.&lt;br&gt;
&lt;strong&gt;Limited control&lt;/strong&gt;: Users don't fully own their listening data.&lt;br&gt;
&lt;strong&gt;Feature stagnation&lt;/strong&gt;: The core experience hasn't evolved much.&lt;br&gt;
&lt;a href="https://atproto.com/" rel="noopener noreferrer"&gt;The Bluesky AT Protocol (ATProto) &lt;/a&gt;offers a decentralized social graph where users own their content and identity, making it the perfect foundation for a next-gen music scrobbling service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ftivl9az2mbzg5035qn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ftivl9az2mbzg5035qn.png" alt="Image description" width="800" height="852"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;This project brings music tracking (scrobbling), sharing, and stats to Bluesky's AT Protocol. Here’s a high-level breakdown:&lt;/p&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;Scrobbling Tracks&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;I've built my own &lt;a href="https://github.com/tsirysndr/rockbox-zig/blob/master/crates/rocksky/src/lib.rs" rel="noopener noreferrer"&gt;Rockbox fork&lt;/a&gt;&lt;/strong&gt; that can send scrobbles automatically to the &lt;a href="https://docs.rocksky.app/" rel="noopener noreferrer"&gt;API&lt;/a&gt;.&lt;br&gt;
It also supports Spotify, local players, and streaming services (via future integrations).&lt;br&gt;
The &lt;a href="https://docs.rocksky.app/" rel="noopener noreferrer"&gt;API&lt;/a&gt; accepts &lt;strong&gt;“Now Playing”&lt;/strong&gt; and track history data.&lt;/p&gt;

&lt;p&gt;2️⃣ &lt;strong&gt;Bluesky AT Protocol for Social Feeds&lt;/strong&gt;&lt;br&gt;
Instead of a centralized database, users’ listening data is posted as ATProto records, making them portable.&lt;br&gt;
Users can see a feed of their friends’ recently played tracks—just like a decentralized Last.fm friends list.&lt;br&gt;
Playlists, top artists/albums, and listening trends are stored as ATProto posts, which can be discovered and shared.&lt;/p&gt;

&lt;p&gt;3️⃣ &lt;strong&gt;User Trends and Analytics&lt;/strong&gt;&lt;br&gt;
Weekly/monthly listening trends (top artists, albums, tracks).&lt;br&gt;
&lt;a href="https://docs.rocksky.app/" rel="noopener noreferrer"&gt;Open API&lt;/a&gt; for users to export their data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1xppomacjkerdthp7fi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1xppomacjkerdthp7fi.png" alt="Image description" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;To ensure scalability, performance, and flexibility, I chose the following stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Node.js (&lt;a href="https://hono.dev" rel="noopener noreferrer"&gt;Hono.js&lt;/a&gt;) – A fast, lightweight framework for handling API requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt;: &lt;a href="https://xata.io/" rel="noopener noreferrer"&gt;Xata (PostgreSQL)&lt;/a&gt; – A managed database for storing scrobbles and user data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: &lt;a href="https://duckdb.org/" rel="noopener noreferrer"&gt;DuckDB&lt;/a&gt; – Efficient in-memory analytics for trends and insights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: &lt;a href="https://www.dragonflydb.io/" rel="noopener noreferrer"&gt;DragonflyDB&lt;/a&gt; – A Redis-compatible, high-performance caching layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices (Rust)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spotify Watcher&lt;/strong&gt;: Tracks the user’s currently playing Spotify song.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;analytics Processor&lt;/strong&gt;: Handles scrobbling data aggregation. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Protocol&lt;/strong&gt;: Bluesky &lt;a href="https://atproto.com/" rel="noopener noreferrer"&gt;ATProto &lt;/a&gt;for decentralized data.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Frontend&lt;/strong&gt;: React for the web UI.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Auth&lt;/strong&gt;: Bluesky DID (Decentralized Identifiers).&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I'm actively improving the platform and adding new features, but my long-term goal is to open-source the project so anyone can contribute, self-host, or build upon it. I believe in open and decentralized music tracking, and I’d love for the community to help shape it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Beta!
&lt;/h2&gt;

&lt;p&gt;This project is still in its early days, but I’m opening a limited beta for those interested in trying it out. If you love music and want to explore a decentralized Last.fm alternative, sign up here:&lt;/p&gt;

&lt;p&gt;➡️ &lt;a href="https://rocksky.app/" rel="noopener noreferrer"&gt;Request Beta Access&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love your feedback! What features would make this the ultimate music tracking service? Let's discuss in the comments or on Bluesky.&lt;/p&gt;

&lt;p&gt;🔵 Find me on Bluesky: &lt;a href="https://bsky.app/profile/tsiry-sandratraina.com" rel="noopener noreferrer"&gt;@tsiry-sandratraina.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>atprotocol</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>Setting Up Your Base Workspace for Seamless Development 🧑‍💻</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Thu, 01 Feb 2024 10:24:46 +0000</pubDate>
      <link>https://dev.to/tsirysndr/setting-up-your-base-workspace-for-seamless-development-4cbl</link>
      <guid>https://dev.to/tsirysndr/setting-up-your-base-workspace-for-seamless-development-4cbl</guid>
      <description>&lt;p&gt;Welcome to the &lt;a href="https://github.com/tsirysndr/base-workspace"&gt;base workspace&lt;/a&gt; – a versatile foundation for all your projects! This environment comes equipped with a portable Docker setup, including pre-configured VSCode tunnels, all orchestrated through Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Usage
&lt;/h2&gt;

&lt;p&gt;Clone the &lt;a href="https://github.com/tsirysndr/base-workspace"&gt;base-workspace repo&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/tsirysndr/base-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;base-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize Terraform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a Docker container named base-workspace with essential tools like &lt;a href="https://pkgx.sh"&gt;pkgx&lt;/a&gt;, &lt;a href="https://ohmyposh.dev/"&gt;oh-my-posh&lt;/a&gt;, &lt;a href="https://atuin.sh/"&gt;atuin&lt;/a&gt;, and the VSCode server pre-installed.&lt;/p&gt;

&lt;p&gt;To connect to your environment, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs base-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the provided VSCode tunnel instructions, and you're ready to roll!&lt;/p&gt;

&lt;p&gt;You can also enter the environment directly using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; base-workspace bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ✨ Bonus
&lt;/h2&gt;

&lt;p&gt;The environment comes pre-configured with &lt;a href="https://ohmyposh.dev/"&gt;oh-my-posh&lt;/a&gt; and &lt;a href="https://atuin.sh/"&gt;atuin&lt;/a&gt; for an enhanced development experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐚 Environments
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;devbox&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://github.com/jetpack-io/devbox"&gt;devbox&lt;/a&gt; environment with vscode tunnels configured.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;devenv&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://devenv.sh/"&gt;devenv&lt;/a&gt; environment with vscode tunnels configured.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flox&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://flox.dev/"&gt;flox&lt;/a&gt; environment with vscode tunnels configured.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;homebrew&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://brew.sh/"&gt;homebrew&lt;/a&gt; environment with vscode tunnels configured.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nix&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://nixos.org/"&gt;nix&lt;/a&gt; environment with vscode tunnels configured.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pkgx&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://pkgx.sh/"&gt;pkgx&lt;/a&gt; environment with vscode tunnels configured.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;Base environment with VSCode tunnels configured&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Enhance your development workflow with this robust base workspace – tailored for efficiency and ease of use. Happy coding! 🚀&lt;/p&gt;

</description>
      <category>development</category>
      <category>tools</category>
      <category>docker</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Streamline Your GitLab CI Configuration with Fluent GitLab CI - A Deno Module</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Tue, 04 Jul 2023 06:20:27 +0000</pubDate>
      <link>https://dev.to/tsirysndr/streamline-your-gitlab-ci-configuration-with-fluent-gitlab-ci-a-deno-module-1ehl</link>
      <guid>https://dev.to/tsirysndr/streamline-your-gitlab-ci-configuration-with-fluent-gitlab-ci-a-deno-module-1ehl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When it comes to setting up and managing GitLab CI configuration files, developers often seek simplicity, readability, and efficiency. Imagine a tool that allows you to generate GitLab CI configuration files with ease and fluency. Enter &lt;a href="https://deno.land/x/fluent_gitlab_ci"&gt;Fluent GitLab CI&lt;/a&gt;, a powerful Deno module that simplifies the process of creating GitLab CI configurations. In this article, we will explore the features, benefits, and usage of Fluent GitLab CI, along with code examples to demonstrate its capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Fluent GitLab CI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tsirysndr/fluent-gitlab-ci"&gt;Fluent GitLab CI&lt;/a&gt; is a &lt;a href="https://deno.land/"&gt;Deno&lt;/a&gt; module designed to simplify the process of generating GitLab CI configuration files. With Fluent GitLab CI, you can effortlessly create CI/CD pipelines by defining stages and jobs with custom scripts. This module brings ease and fluency to the creation of GitLab CI configurations, making it a valuable tool for developers looking to streamline their CI setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To get started with Fluent GitLab CI, you need to import the necessary classes from the module and define your stages and jobs. The Job class represents a single job in a GitLab CI pipeline, while the GitlabCI class is used to construct the overall CI configuration. By chaining methods and setting properties, you can create a comprehensive CI pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring Fluent GitLab CI Features
&lt;/h2&gt;

&lt;p&gt;Fluent GitLab CI offers several powerful features to simplify the creation of GitLab CI configurations. Firstly, you can define stages using the &lt;code&gt;stages()&lt;/code&gt; method, specifying the order in which jobs will be executed. Each stage can consist of one or more jobs defined using the &lt;code&gt;addJob()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Each job can have its own custom script, which is defined using the &lt;code&gt;script()&lt;/code&gt; method. This allows you to include commands and actions specific to the job's purpose, such as compiling code, running tests, or deploying applications. Fluent GitLab CI also supports specifying dependencies between jobs using the &lt;code&gt;needs()&lt;/code&gt; method, ensuring proper execution order within the pipeline.&lt;/p&gt;

&lt;p&gt;To obtain the final GitLab CI configuration, you can use the &lt;code&gt;toString()&lt;/code&gt; method, which returns the configuration as a string. This string can then be outputted or saved to a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Example
&lt;/h2&gt;

&lt;p&gt;Let's take a closer look at an example that demonstrates the power of Fluent GitLab CI. Suppose you have a project with three stages: &lt;code&gt;"build"&lt;/code&gt;, &lt;code&gt;"test"&lt;/code&gt;, and &lt;code&gt;"deploy"&lt;/code&gt;. Within each stage, you want to define specific jobs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GitlabCI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://deno.land/x/fluent_gitlab_ci/mod.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  echo "Compiling the code..."
  echo "Compile complete."
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unitTest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  echo "Running unit tests... This will take about 60 seconds."
  sleep 60
  echo "Code coverage is 90%"
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deploy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deploy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  echo "Deploying application..."
  echo "Application successfully deployed."
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gitlabci&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;GitlabCI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deploy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build-job&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unit-test-job&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unitTest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deploy-job&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gitlabci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;gitlabci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we define three jobs: &lt;code&gt;"build-job"&lt;/code&gt;, &lt;code&gt;"unit-test-job"&lt;/code&gt;, and &lt;code&gt;"deploy-job".&lt;/code&gt; Each job is assigned to a specific stage and has its own custom script. The &lt;code&gt;stages()&lt;/code&gt; method is used to define the order of the stages. Finally, we call the &lt;code&gt;toString()&lt;/code&gt; method to obtain the GitLab CI configuration as a string and output it to the console. The &lt;code&gt;write()&lt;/code&gt; method can be used to save the configuration to a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Fluent GitLab CI
&lt;/h2&gt;

&lt;p&gt;Fluent GitLab CI offers numerous benefits for developers. First and foremost, it simplifies the process of creating GitLab CI configurations, reducing the time and effort required. The fluent and expressive syntax of the module makes the configuration files more readable and maintainable.&lt;/p&gt;

&lt;p&gt;By leveraging TypeScript and Deno compatibility, Fluent GitLab CI provides type safety and robustness in the CI configuration generation process. This helps catch errors and ensures that the configurations adhere to the expected structure.&lt;/p&gt;

&lt;p&gt;Fluent GitLab CI empowers developers to create comprehensive CI/CD pipelines easily, improving their productivity and enhancing the overall development workflow. With its intuitive API and flexible features, Fluent GitLab CI is a valuable asset for any project utilizing GitLab CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tsirysndr/fluent-gitlab-ci"&gt;Fluent GitLab CI&lt;/a&gt; provides developers with a powerful tool to generate GitLab CI configuration files easily and fluently. By leveraging the capabilities of this Deno module, developers can streamline their CI setup, improve productivity, and enhance the readability of their GitLab CI configurations. With Fluent GitLab CI, managing complex CI pipelines becomes a breeze. Give it a try and experience the efficiency and simplicity it brings to your GitLab CI workflows.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>typescript</category>
      <category>deno</category>
      <category>devops</category>
    </item>
    <item>
      <title>FluentDocker: Simplify Docker Image Generation with TypeScript</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Wed, 28 Jun 2023 06:55:41 +0000</pubDate>
      <link>https://dev.to/tsirysndr/fluentdocker-simplify-docker-image-generation-with-typescript-1di2</link>
      <guid>https://dev.to/tsirysndr/fluentdocker-simplify-docker-image-generation-with-typescript-1di2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Are you tired of writing lengthy Dockerfiles for your projects? Introducing &lt;a href="https://deno.land/x/fluentdocker@v0.1.0"&gt;FluentDocker&lt;/a&gt;, a powerful Deno module that allows you to generate Dockerfiles and build Docker images effortlessly using TypeScript. With FluentDocker, you can streamline your Docker image generation process, saving time and effort. In this article, we will explore how FluentDocker simplifies Docker image creation and demonstrates how you can leverage its fluent syntax to build Docker images with ease.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To begin using FluentDocker, you need to import the Dockerfile class from the module using the Deno runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Dockerfile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://deno.land/x/fluentdocker/mod.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building Docker Images with FluentDocker
&lt;/h2&gt;

&lt;p&gt;FluentDocker enables you to define Docker images using a fluent syntax. Let's dive into a practical example of how to build a Docker image for a Node.js application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Dockerfile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:18-alpine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apk update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npx --yes serve -s -l 8080&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dockerfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dockerfile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we start by creating a new Dockerfile instance. Then, we chain the methods to define the Dockerfile instructions. We specify the base image using &lt;code&gt;from()&lt;/code&gt;, run commands with &lt;code&gt;run()&lt;/code&gt;, expose ports with &lt;code&gt;expose()&lt;/code&gt;, and set the entrypoint with &lt;code&gt;cmd()&lt;/code&gt;. Finally, we call &lt;code&gt;toString()&lt;/code&gt; to obtain the generated &lt;code&gt;Dockerfile&lt;/code&gt; content, which we log to the console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Docker Images
&lt;/h2&gt;

&lt;p&gt;Once you have defined your Dockerfile using FluentDocker, you can proceed to build the Docker image. The &lt;code&gt;build()&lt;/code&gt; method takes in the build context directory and the desired image name as parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image.build(".", "node-app-example");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we specify the build context as the current directory (&lt;code&gt;.&lt;/code&gt;) and provide the desired image name (&lt;code&gt;node-app-example&lt;/code&gt;). FluentDocker takes care of the Docker image build process, providing a seamless experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tsirysndr/fluentdocker-deno"&gt;FluentDocker&lt;/a&gt; empowers developers to streamline the process of Docker image generation using TypeScript. With its fluent syntax and easy-to-use API, FluentDocker simplifies the creation of Dockerfiles, allowing you to define instructions in a clear and concise manner. By eliminating the need to write Dockerfiles manually, FluentDocker saves time and reduces errors in the image build process.&lt;/p&gt;

&lt;p&gt;Ready to simplify your Docker image generation? Give FluentDocker a try and experience the power of TypeScript for Docker. Happy coding!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>docker</category>
      <category>deno</category>
    </item>
    <item>
      <title>Simplify Your Development Environment Setup with 'setup-crosup' GitHub Action</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Thu, 22 Jun 2023 13:47:21 +0000</pubDate>
      <link>https://dev.to/tsirysndr/simplify-your-development-environment-setup-with-setup-crosup-github-action-45pj</link>
      <guid>https://dev.to/tsirysndr/simplify-your-development-environment-setup-with-setup-crosup-github-action-45pj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Setting up your development environment can often be a time-consuming process, especially when working with ChromeOS, MacOS or various Linux distributions. However, with the new &lt;a href="https://github.com/tsirysndr/setup-crosup"&gt;setup-crosup&lt;/a&gt; GitHub Action, you can effortlessly streamline the installation and setup of &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup CLI&lt;/a&gt; in your workflows. In this article, we will explore how to leverage this powerful GitHub Action to supercharge your development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt;What is 'setup-crosup' GitHub Action?&lt;br&gt;
Getting Started&lt;br&gt;
2.1 Prerequisites&lt;br&gt;
2.2 Setting up 'setup-crosup' in your Workflow&lt;br&gt;
Customizing the Action&lt;br&gt;
3.1 Specifying the Crosup Version&lt;br&gt;
3.2 Adding Packages for Installation&lt;br&gt;
Verifying the Installation&lt;br&gt;
4.1 Checking Crosup Version&lt;br&gt;
4.2 Verifying Installed Packages&lt;br&gt;
Conclusion&lt;/p&gt;
&lt;h2&gt;
  
  
  What is 'setup-crosup' GitHub Action? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/tsirysndr/setup-crosup"&gt;setup-crosup&lt;/a&gt; GitHub Action is a powerful tool that simplifies the process of downloading, installing, and setting up &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup CLI&lt;/a&gt; in your GitHub Actions workflows. It eliminates the hassle of manual installation steps and ensures a consistent and reliable development environment across different platforms.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  2.1 Prerequisites: &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Before diving into using 'setup-crosup', ensure you have the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub repository where you want to integrate  &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup CLI&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Basic knowledge of GitHub Actions and workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2.2 Setting up 'setup-crosup' in your Workflow: &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To integrate 'setup-crosup' into your GitHub Actions workflow, follow these steps:&lt;/p&gt;

&lt;p&gt;Open your repository and navigate to the &lt;code&gt;.github/workflows&lt;/code&gt; directory.&lt;br&gt;
Create a new YAML file (e.g., &lt;code&gt;crosup-setup.yml&lt;/code&gt;).&lt;br&gt;
Copy and paste the following code into the YAML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;Copy code&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Crosup&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;setup-superviseur&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;continue-on-error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Nix&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DeterminateSystems/nix-installer-action@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Crosup&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tsirysndr/setup-crosup@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;v0.4.8'&lt;/span&gt;
          &lt;span class="c1"&gt;# Add packages to install here&lt;/span&gt;
          &lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;deno&lt;/span&gt;
            &lt;span class="s"&gt;zig&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify Crosup&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;crosup --version&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify Deno&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deno --version&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify Zig&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zig version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Customizing the Action &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Specifying the Crosup Version: &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;You can specify the desired version of  &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup CLI&lt;/a&gt;  by modifying the version parameter in the 'Setup Crosup' step of the workflow YAML. Replace 'v0.4.8' with your preferred version.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Adding Packages for Installation: &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you need to install additional packages along with Crosup CLI, simply add them to the packages parameter, separated by newlines. For example, to install Deno and Zig, modify the packages parameter as shown in the example YAML above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying the Installation &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;After setting up 'setup-crosup' in your GitHub Actions workflow, it's essential to verify the successful installation and configuration of  &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup CLI&lt;/a&gt;  and any additional packages you specified. Let's explore how you can perform these verifications:&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Checking Crosup Version &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To ensure that  &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup CLI&lt;/a&gt;  has been installed correctly, you can add a verification step in your workflow. In the example YAML, we've included a step named "Verify Crosup" that runs the command ``crosup --version. This command will display the version of Crosup installed, confirming its successful setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Verifying Installed Packages &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you specified additional packages to be installed alongside Crosup, it's crucial to verify their installation as well. In the example YAML, we've included verification steps for Deno and Zig. The commands &lt;code&gt;deno --version&lt;/code&gt; and &lt;code&gt;zig version&lt;/code&gt; respectively check the versions of Deno and Zig installed.&lt;/p&gt;

&lt;p&gt;By performing these verification steps, you can ensure that all the necessary components of your development environment, including Crosup CLI and any additional packages, are successfully set up and ready to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With the &lt;a href="https://github.com/tsirysndr/setup-crosup"&gt;setup-crosup&lt;/a&gt; GitHub Action, the process of setting up your development environment becomes a breeze. Say goodbye to manual installation steps and hello to streamlined workflows. In this article, we explored the features and benefits of &lt;a href="https://github.com/tsirysndr/setup-crosup"&gt;setup-crosup&lt;/a&gt;, learned how to integrate it into your GitHub Actions workflow, and customized it to suit your requirements.&lt;/p&gt;

&lt;p&gt;Now, you can simplify your development environment setup on Chromebook/ChromeOS, MacOS or any Linux distribution, saving time and effort in the process. Get started with &lt;a href="https://github.com/tsirysndr/setup-crosup"&gt;setup-crosup&lt;/a&gt; today and enjoy a hassle-free development experience!&lt;/p&gt;

&lt;p&gt;Remember, automation is the key to unlocking your productivity potential as a developer. Embrace the power of &lt;a href="https://github.com/tsirysndr/setup-crosup"&gt;setup-crosup&lt;/a&gt; and elevate your development workflow to new heights. Happy coding!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introducing CrosUp: Simplifying Package Management with Nix for Any Linux Distro or macOS</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Sun, 18 Jun 2023 18:03:52 +0000</pubDate>
      <link>https://dev.to/tsirysndr/introducing-crosup-simplifying-package-management-with-nix-for-any-linux-distro-or-macos-5can</link>
      <guid>https://dev.to/tsirysndr/introducing-crosup-simplifying-package-management-with-nix-for-any-linux-distro-or-macos-5can</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Managing packages and dependencies is an essential part of every developer's life. However, it can often be a complex and time-consuming process, especially when dealing with different operating systems and package managers. But fear not! We are thrilled to introduce CrosUp, an open-source command-line tool that revolutionizes package management by seamlessly integrating Nix into your development environment. With CrosUp, you can now effortlessly search for, install, and manage packages from the Nix package registry on any Linux distribution or macOS system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplify Your Development Environment
&lt;/h2&gt;

&lt;p&gt;CrosUp is designed with simplicity and convenience in mind. Gone are the days of struggling with intricate Nix setups and configuration files. CrosUp streamlines the entire process, providing a fully automated installation experience that abstracts away the complexity of managing packages with Nix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search and Install Made Easy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vA858ry2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ja0m18prsmzxtna8z6kp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vA858ry2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ja0m18prsmzxtna8z6kp.png" alt="previe" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finding the right package is crucial for any development project. With CrosUp, searching for packages from the Nix package registry becomes a breeze. Simply run &lt;code&gt;crosup search &amp;lt;package-name&amp;gt;&lt;/code&gt;, and let CrosUp handle the rest. Whether you need the latest version of a popular library or a specific tool for your project, CrosUp enables you to discover and install packages effortlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seamless Integration with Your Workflow
&lt;/h2&gt;

&lt;p&gt;CrosUp goes beyond package installation. It enhances your development workflow by providing a seamless integration with tools you rely on. By running &lt;code&gt;crosup init &amp;lt;package-name&amp;gt;&lt;/code&gt;, CrosUp automatically sets up the package for your project, ensuring that it is readily available for use. Say goodbye to tedious manual configurations and hello to productivity!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-Platform Compatibility
&lt;/h2&gt;

&lt;p&gt;One of the standout features of CrosUp is its ability to work across various Linux distributions and macOS. It eliminates the need for developers to juggle different package managers and ensures a consistent experience regardless of the operating system. With CrosUp, you can enjoy the benefits of Nix's powerful package management on your preferred platform.&lt;/p&gt;

&lt;p&gt;Open-Source and Community-Driven:&lt;br&gt;
CrosUp is an open-source project, built by developers for developers. The code repository on GitHub (&lt;a href="https://github.com/tsirysndr/crosup"&gt;https://github.com/tsirysndr/crosup&lt;/a&gt;) is freely accessible, allowing you to contribute, provide feedback, and collaborate with other members of the community. Join us in making package management a seamless experience for everyone!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;CrosUp is the game-changing CLI tool that simplifies package management with Nix for Linux and macOS. By abstracting away the complexities and providing a user-friendly interface, CrosUp enables developers to effortlessly search, install, and manage packages from the Nix package registry. Embrace a seamless and productive workflow with CrosUp, and say goodbye to the hassle of package management. Try CrosUp today and experience the future of simplified development environments!&lt;/p&gt;

</description>
      <category>tooling</category>
    </item>
    <item>
      <title>Streamline Your Development Environment Setup on ChromeOS and Linux</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Sat, 10 Jun 2023 11:27:09 +0000</pubDate>
      <link>https://dev.to/tsirysndr/streamline-your-development-environment-setup-on-chromeos-and-linux-1jdl</link>
      <guid>https://dev.to/tsirysndr/streamline-your-development-environment-setup-on-chromeos-and-linux-1jdl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Setting up a development environment on a new Chromebook (ChromeOS) or any Linux distribution can be a time-consuming and daunting task. But fear not! Introducing &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt;, a powerful command-line tool designed to simplify and expedite the process. With &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt;, you can swiftly configure your development environment, install essential tools, and get coding in no time. In this article, we will explore the features, installation process, usage, and configuration options of &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt;, empowering you to streamline your development workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features That Make Crosup Stand Out
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Compatibility: Crosup is compatible with various operating systems, including ChromeOS, Debian-based Linux distributions, OpenSUSE, Fedora, RedHat, CentOS, Alpine, Arch, and Gentoo. It ensures a seamless experience regardless of your preferred platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy Installation: With a single command, you can quickly install Crosup on your machine. Just run &lt;code&gt;bash &amp;lt;(curl -sSL https://raw.githubusercontent.com/tsirysndr/crosup/master/install.sh)&lt;/code&gt; and let the magic unfold.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Developer Tools Galore: Crosup provides an extensive collection of developer tools ready to be installed. From Docker, Nix, and Homebrew to VS Code, fzf, and kubectl, Crosup has you covered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid Maintaining Custom Bash Scripts: &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt; eliminates the need to maintain custom bash scripts for setting up your development environment. Instead, it offers a standardized and easily configurable solution that saves you time and effort.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installation Made Simple
&lt;/h2&gt;

&lt;p&gt;To get started with &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt;, you need to execute a straightforward installation process. Just follow the command mentioned earlier, and &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt; will be up and running on your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage Made Easy
&lt;/h2&gt;

&lt;p&gt;Crosup's intuitive user interface simplifies the installation of developer tools. By executing the &lt;code&gt;crosup install&lt;/code&gt; command, you can effortlessly install various tools based on your requirements. Additionally, &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt; offers subcommands like &lt;code&gt;help&lt;/code&gt; and &lt;code&gt;init&lt;/code&gt; to provide further assistance and generate default configuration files.&lt;/p&gt;

&lt;p&gt;Streamlining Your Workflow with Configuration:&lt;br&gt;
Crosup employs a configuration file, &lt;code&gt;Crosfile.toml&lt;/code&gt;, to determine the tools to be installed. By default, &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt; includes an embedded configuration, but you can generate a default configuration file using the &lt;code&gt;crosup init&lt;/code&gt; command. The configuration file, written in HCL/TOML format, allows you to specify tools, packages, version checks, pre- and post-installation commands, and even dependencies.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example Configuration for Debian-based System:
&lt;/h2&gt;

&lt;p&gt;We'll explore a minimal &lt;code&gt;Crosfile.toml&lt;/code&gt; configuration, which installs Vim and Git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Crosfile.toml&lt;/span&gt;
&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s"&gt;"vim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;"git"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contributing and License
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt; is an open-source project, welcoming contributions, bug reports, and feature requests. If you're interested in improving Crosup, check out the project's &lt;a href="https://github.com/tsirysndr/crosup/blob/master/CONTRIBUTING.md"&gt;CONTRIBUTING&lt;/a&gt; guidelines. Crosup is licensed under the &lt;a href="https://github.com/tsirysndr/crosup/blob/master/LICENSE"&gt;MIT License&lt;/a&gt;, enabling you to freely use, modify, and distribute the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt; is your go-to command-line tool for quickly setting up a development environment on &lt;a href="https://www.google.com/chromebook/chrome-os/"&gt;ChromeOS&lt;/a&gt; and various Linux distributions. Its compatibility, simplicity, and extensive collection of developer tools make it a must-have for developers seeking an efficient workflow. With &lt;a href="https://github.com/tsirysndr/crosup"&gt;Crosup&lt;/a&gt;, you can bid farewell to lengthy setup processes and the need to maintain custom bash scripts, allowing you to focus on what you do best—coding.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>linux</category>
      <category>rust</category>
    </item>
    <item>
      <title>Developing on ChromeOS: Exploring the ChromeOS Flex and Nix Combo</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Fri, 26 May 2023 07:40:13 +0000</pubDate>
      <link>https://dev.to/tsirysndr/developing-on-chromeos-exploring-the-chromeos-flex-and-nix-combo-3fp5</link>
      <guid>https://dev.to/tsirysndr/developing-on-chromeos-exploring-the-chromeos-flex-and-nix-combo-3fp5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Developers have traditionally relied on Windows, macOS, or Linux distributions as their primary development environments. However, with the advancements in ChromeOS, the operating system developed by Google, it's worth exploring the possibilities it offers for developers. In this article, we will dive into ChromeOS as a development environment and explore the combination of &lt;a href="https://chromeos.dev/en/linux"&gt;Crostini&lt;/a&gt; and &lt;a href="https://nixos.org/"&gt;Nix&lt;/a&gt; to enhance your development workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChromeOS: embracing the cloud
&lt;/h2&gt;

&lt;p&gt;ChromeOS is an operating system designed around the Chrome web browser, emphasizing cloud-based applications and services. While not initially considered a full-fledged development platform, ChromeOS has evolved and now offers options to support developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux Support with Crostini
&lt;/h2&gt;

&lt;p&gt;One of the key features that make ChromeOS more developer-friendly is Crostini. Crostini enables the execution of a Linux container within the ChromeOS environment. This Linux container provides access to a terminal, package manager, and the ability to run Linux applications, opening up the door to a range of development possibilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nix: Reproducible Environments
&lt;/h2&gt;

&lt;p&gt;Nix, a powerful package manager and build system used primarily in the Linux ecosystem, can significantly enhance your development workflow on ChromeOS. With Nix, you can define your development environment as a set of packages and configurations, ensuring reproducible builds and the ability to create isolated development environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Nix
&lt;/h2&gt;

&lt;p&gt;To install Nix on your ChromeOS device, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open a terminal in your ChromeOS environment (using Crostini).&lt;/li&gt;
&lt;li&gt;Run the following command to download and execute the Nix installation script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--proto&lt;/span&gt; &lt;span class="s1"&gt;'=https'&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;-sSf&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; https://install.determinate.systems/nix | sh &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Follow the instructions presented during the installation process. The script will guide you through setting up Nix and configuring your environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the installation is complete, you'll have Nix available in your ChromeOS environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unlocking Development Potential
&lt;/h2&gt;

&lt;p&gt;Combining ChromeOS and Nix can unlock new possibilities for developers on Chromebooks. The Linux environment provided by Crostini allows you to leverage the Linux ecosystem and run various development tools and programming languages. Nix ensures reproducibility and simplifies the sharing of development setups across different machines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While ChromeOS was initially perceived as a limited platform for development, the introduction of Crostini, along with the reproducibility of Nix, has expanded its potential as a viable development environment. Developers can now harness the power of ChromeOS, leverage Linux tools and applications and ensure consistent development setups with Nix. While ChromeOS may not be suitable for all development workflows, it's certainly worth exploring for web and cloud-based development tasks.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>linux</category>
      <category>nix</category>
    </item>
    <item>
      <title>Introducing Superviseur - A process supervisor for local development</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Sun, 19 Mar 2023 15:50:20 +0000</pubDate>
      <link>https://dev.to/tsirysndr/introducing-superviseur-a-process-supervisor-for-local-development-3kc0</link>
      <guid>https://dev.to/tsirysndr/introducing-superviseur-a-process-supervisor-for-local-development-3kc0</guid>
      <description>&lt;p&gt;Are you tired of manually starting and stopping all the services you need for local development? Have you ever wished there was a tool that could handle this for you? Look no further than Superviseur!&lt;/p&gt;

&lt;p&gt;Superviseur is a simple process supervisor for UNIX-like systems that allows you to manage executables, WASM, and Docker containers all from one place. It is perfect for local development environments where you need to manage multiple services simultaneously.&lt;/p&gt;

&lt;p&gt;Installation is easy. Simply clone the repository and compile using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;protobuf &lt;span class="c"&gt;# macOS&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; protobuf-compiler &lt;span class="c"&gt;# Ubuntu/Debian&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://bun.sh/install | bash
git clone https://github.com/tsirysndr/superviseur
&lt;span class="nb"&gt;cd &lt;/span&gt;superviseur/webui &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; bun &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; bun run build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..
cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Superviseur is still in the alpha phase, so be warned that it may be unstable. However, the tool is already quite powerful and has a lot of features. You can download the latest release for your platform &lt;a href="https://github.com/tsirysndr/superviseur/releases"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you have installed Superviseur, you can start using it by starting the daemon and initializing a new project using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;superviseur daemon &amp;amp;
superviseur new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a &lt;code&gt;Superfile.hcl&lt;/code&gt; file in the current directory with an example configuration that you can modify to suit your needs. You can then start a service using the &lt;code&gt;superviseur start &amp;lt;service_name&amp;gt;&lt;/code&gt; command. You can check the status of a service using the &lt;code&gt;superviseur status &amp;lt;service_name&amp;gt;&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Superviseur also has a web UI that you can use to manage your services. To start the web UI, simply use the &lt;code&gt;superviseur ui&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Superviseur is still a young project, and there are plenty of ways you can contribute. If you encounter a bug or have a feature request, please submit an issue on the &lt;a href="https://github.com/tsirysndr/superviseur"&gt;GitHub repository&lt;/a&gt;. If you would like to contribute to the project, there are a number of open issues and feature requests that you can work on. You can also contribute by improving the documentation or helping to test the tool.&lt;/p&gt;

&lt;p&gt;In conclusion, Superviseur is a powerful and easy-to-use process supervisor that can help you manage your local development environment. Give it a try and let us know what you think!&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>rust</category>
    </item>
    <item>
      <title>Introducing TuneIn-CLI: A Command-Line Interface to Browse and Listen to Thousands of Radio Stations Globally</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Fri, 24 Feb 2023 16:34:04 +0000</pubDate>
      <link>https://dev.to/tsirysndr/introducing-tunein-cli-a-command-line-interface-to-browse-and-listen-to-thousands-of-radio-stations-globally-j1m</link>
      <guid>https://dev.to/tsirysndr/introducing-tunein-cli-a-command-line-interface-to-browse-and-listen-to-thousands-of-radio-stations-globally-j1m</guid>
      <description>&lt;p&gt;Are you a fan of radio stations, and looking for a way to listen to them from your terminal? Then you'll love TuneIn-CLI, an open-source project that allows you to browse and play thousands of radio stations worldwide without leaving your terminal.&lt;/p&gt;

&lt;p&gt;In this blog post, we will introduce TuneIn-CLI, its installation process, usage, and features. TuneIn-CLI is a lightweight and easy-to-use command-line tool developed using Rust, an efficient and modern programming language. It uses TuneIn's public APIs to browse and fetch radio stations data from all around the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;TuneIn-CLI is available for macOS and Linux platforms. You can download and install the latest version from the official GitHub repository or via Homebrew on macOS/Linux.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;tsirysndr/tap/tunein
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;TuneIn-CLI offers four subcommands: browse, play, search, and help. You can browse all available radio stations with the browse command, play a specific radio station with the play command, search for a station with the search command, and get help with the help command.&lt;/p&gt;

&lt;p&gt;For example, to search for a radio station, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tunein search &lt;span class="s2"&gt;"BBC Radio 1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the CLI will display a list of available radio stations with their unique IDs.&lt;/p&gt;

&lt;p&gt;To play a specific station, you can use the play command with the station name or ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tunein play &lt;span class="s2"&gt;"alternativeradio.us"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;TuneIn-CLI offers several features that make it a unique and powerful tool for radio lovers. Some of these features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Coverage&lt;/strong&gt;: TuneIn-CLI supports thousands of radio stations worldwide, making it easy to discover and listen to new stations from different countries and regions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Search&lt;/strong&gt;: You can search for radio stations by name, genre, language, location, and other criteria to find stations that match your interests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Play&lt;/strong&gt;: TuneIn-CLI allows you to play radio stations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy Navigation&lt;/strong&gt;: You can browse radio stations by genre, language, location, and popularity to quickly find stations that match your interests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open-Source&lt;/strong&gt;: TuneIn-CLI is an open-source project, which means that anyone can contribute to its development, report issues, or suggest new features.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;TuneIn-CLI is a powerful and user-friendly command-line tool that allows you to browse and listen to thousands of radio stations worldwide without leaving your terminal. With its intuitive interface, powerful search capabilities, and global coverage, TuneIn-CLI is an excellent tool for radio enthusiasts and anyone looking for a unique and exciting way to discover new radio stations.&lt;/p&gt;

&lt;p&gt;If you're interested in exploring thousands of radio stations across the globe right from your terminal, be sure to check out '&lt;a href="https://github.com/tsirysndr/tunein-cli" rel="noopener noreferrer"&gt;tunein-cli&lt;/a&gt;' on GitHub. The project is open-source, and we welcome contributions from developers like you. You can find the project repository here: &lt;a href="https://github.com/tsirysndr/tunein-cli" rel="noopener noreferrer"&gt;https://github.com/tsirysndr/tunein-cli&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>workspace</category>
      <category>playlist</category>
      <category>metal</category>
    </item>
    <item>
      <title>Building a Chromecast Plugin for my Rust Music Player Project</title>
      <dc:creator>Tsiry Sandratraina</dc:creator>
      <pubDate>Sun, 19 Feb 2023 05:50:26 +0000</pubDate>
      <link>https://dev.to/tsirysndr/building-a-chromecast-plugin-for-my-rust-music-player-project-1e2h</link>
      <guid>https://dev.to/tsirysndr/building-a-chromecast-plugin-for-my-rust-music-player-project-1e2h</guid>
      <description>&lt;p&gt;Recently, I built a Chromecast plugin for my Rust-based &lt;a href="https://github.com/tsirysndr/music-player"&gt;music player project&lt;/a&gt; on Github. In this blog post, I will walk you through the steps I took to build the plugin, and highlight some of the key features and design decisions that went into its development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;My music player project was originally built as a command-line tool, but I wanted to extend its functionality to support casting audio to Chromecast devices. To achieve this, I built a new &lt;a href="https://github.com/tsirysndr/music-player/blob/master/addons/src/chromecast.rs"&gt;Rust module &lt;/a&gt;called "Chromecast", which defines a struct that implements the "Addon" and "Player" traits in my player's architecture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Addon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;author&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_enabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[async_trait]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;load_tracks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;start_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;play_next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_current_playback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Playback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_current_tracklist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;play_track_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;remove_track_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;device_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Design and Implementation
&lt;/h2&gt;

&lt;p&gt;The Chromecast struct contains several fields, including the device name, version, author, description, host and port, client connection, transport ID, session ID, current playback status, and a CastPlayer instance for sending media commands to the Chromecast device.&lt;/p&gt;

&lt;p&gt;One of the most important methods in the Chromecast struct is "connect()", which connects to the Chromecast device and launches the Music Player App. This method uses the "CastDevice" and "CastDeviceApp" structs from the Rust crate &lt;a href="https://github.com/tsirysndr/rust-cast"&gt;"chromecast"&lt;/a&gt; to establish a connection and retrieve the transport and session IDs required for media playback.&lt;/p&gt;

&lt;p&gt;The Chromecast struct also implements the "Player" trait, which defines methods for media playback, such as "play()", "pause()", "stop()", "seek()", and "set_volume()". These methods use the "CastPlayer" instance to send media commands to the Chromecast device over the established connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[async_trait]&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Chromecast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.cmd_tx&lt;/span&gt;
            &lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CastPlayerCommand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.cmd_tx&lt;/span&gt;
            &lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CastPlayerCommand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Pause&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.cmd_tx&lt;/span&gt;
            &lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CastPlayerCommand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.cmd_tx&lt;/span&gt;
            &lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CastPlayerCommand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.cmd_tx&lt;/span&gt;
            &lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;CastPlayerCommand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Previous&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conslusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, I have developed a Rust-based Chromecast plugin for my music player project on GitHub. The plugin allows users to cast their music playback to a Chromecast device with ease. I hope that this plugin will help enhance the user experience for our music player users.&lt;/p&gt;

&lt;p&gt;This project is open source, and we welcome contributions from the community to help improve the plugin. If you are interested in contributing to the project, please feel free to check out the project's &lt;a href="https://github.com/tsirysndr/music-player"&gt;GitHub page&lt;/a&gt; and submit a pull request or open an issue. We appreciate any feedback and contributions that can help us make the plugin better.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>chromecast</category>
      <category>cli</category>
      <category>github</category>
    </item>
  </channel>
</rss>
