How to distribute a flake desktop gui application?

Hi everyone, I’m currently developing a pomodoro application in rust, and I want to package it properly using a flake.nix. Here is where I’m lost.

  • Where do icons go? How do I configure them?
  • What do I do with .desktop file?
  • Where do I put my package to be available to KDE and Gnome? What about MacOS?
  • How to convert or expose the app cfg (.toml) as a nixos module if applicable?

I was wondering if someone could share a primer and what are the best practices for doing this?
Ideally the outcome could be a section in the wiki.nixos.org as I haven’t found anything there.

I found that wezterm and ghostty could be a good starting point for me:

I feel like I can hack my way around, but I’d like to know best practices.

Thanks!

I was able to make some progress on this front.

you can build the .desktop file used by KDE and Gnome with the function makeDesktopItem.

You can also set desktopItems = [ hello-desktop ]; inside mkDerivation. Though this one is unclear what it does. It didn’t work for me.

The key was using postInstall step of a mkDerivation to install the logo.svg and the .desktop

Here’s an example (a distilled version from my flake, I actually haven’t tested it but you can use it as a guide):

{
  description = "A development shell for rust";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  };
  outputs =
    inputs@{
      flake-parts,
      ...
    }:
    let
      systems = [
        "x86_64-linux"
        "aarch64-darwin"
        "x86_64-darwin"
      ];
    in
    # https://flake.parts/
    flake-parts.lib.mkFlake { inherit inputs; } {
      debug = true;
      systems = systems;
      perSystem =
        {
          pkgs,
          inputs',
          self',
          ...
        }:
        let
          # app
          hello-desktop = pkgs.makeDesktopItem {
            name = "my-hello";
            exec = "my-hello"; # recommended way, so users can wrap around it?
            desktopName = "My Hello";
            genericName = "A Hello Application";
            icon = "org.reciperium.hello";
            comment = "Say hello";
            categories = [ "Utility" ];
            terminal = false;
            keywords = [
              "timer"
              "extra extra productivity"
            ];
          };
        in
        {
          packages = {
            my-hello = pkgs.stdenv.mkDerivation {
              pname = "hello";
              version = "2.12.1";
            
              src = fetchurl {
                url = "mirror://gnu/hello/hello-2.12.1.tar.gz";
                sha256 = "0ssw11k188884746x0y691842cz624ac123c4567a1b2c3d4e5";
              };

              # takes care of placing the .desktop under $out/share/applications/hello.desktop
              nativeBuildInputs = with pkgs; [ ] ++ lib.optionals stdenv.isLinux [ copyDesktopItems ];
              buildPhase = ''
                ./configure
                make
              '';
            
              installPhase = ''
                mkdir -p $out/bin
                cp hello $out/bin
              '';
              
              postInstall =
                with pkgs;
                lib.optionalString stdenv.isLinux ''
                  # install icon
                  mkdir -p "$out/share/icons/hicolor/scalable/apps"
                  install -Dm644 icons/logo.svg $out/share/icons/hicolor/scalable/apps/org.reciperium.hello.svg
                '';
              desktopItems = [ hello-desktop ];
            }
          };
        };
    };
}

TODO:

  • How to package for mac?
  • How to produce AppImages (appimageTools.wrapType2)

nix-bundle looks promising, as it can build AppImage and in the future also MacOS, but it’s still in progress.