Firefox: import HTML bookmark file in a declarative manner

I only keep bookmarks in the Bookmarks Toolbar and when I use my script they show up in the same place (the Bookmarks Toolbar). When I initially wrote the script, I tested all locations and they all worked, so my only guess at the moment is that they are showing up in the same way they were exported.

I really do need to go to bed, but I’ll ask you a few questions and touch base tomorrow:

  • Where were the bookmarks located in the browser that originally generated the HTML file?
  • What was the original exporting browser (I’ve only tested FireFox)?

If I’m not able to figure out what’s going on from those questions, then I may need the HTML file to check out what’s going on.

First and foremost I’d like to make sure this is not caused by my script. However, if we’re not able to resolve your issue, you could import them as they are now, then launch Firefox, move all the bookmarks to the location you’d like, then re-export them in another HTML file and send that through my script again.

Thank you @ReedClanton I solved the issue. In practice one Firefox Policy prevents the change (and so the add and removal) of bookmarks. This Firefox policy is:

      policies = {
        NoDefaultBookmarks = true;

So, to make bookmarks being set correctly, NoDefaultBookmarks must be removed or set to false.

Note that depending which settings is / are used to set bookmarks, different synthax are required.

Following places are configurable within home-manager.users."$USER_NAME".program.firefox:

@ReedClanton home-manager seems to be parsing “nix” dedicated bookmarks syntax into Netscape format (.html) in firefoxBookmarksFile bookmarks function.


As an example:

{
  home-manager.users."${USER}" = {
    programs = {
      firefox = {
        enable = true;

        policies = {
          ManagedBookmarks = lib.importJSON ./managed-bookmarks.json;
        };

        profiles = {
          # default profiles
          default = {
            id = 0;
            name = "Default";
            isDefault = true;

            bookmarks = lib.importJSON ./default-bookmarks.json;
          };

          "alternative-profile" = {
            id = 1;
            name = "Alternative Profile";

            bookmarks = lib.importJSON ./alternative-bookmarks.json;
          }
        }
      };
    };
  };
}

Files:

// managed-bookmarks.json
[
  {
    "toplevel_name": "My Managed Bookmarks"
  },

  {
    "url": "https://login.live.com/login.srf",
    "name": "Microsoft 365"
  },

  {
    "url": "https://github.com/login",
    "name": "GitHub"
  },

  {
    "name": "Nix",
    "children": [
      {
        "url": "https://nixos.org/learn",
        "name": "NixOS"
      },
      {
        "url": "https://nixos.wiki/wiki/Main_Page",
        "name": "NixOS Wiki"
      },
      {
        "url": "https://search.nixos.org/packages",
        "name": "Nix packages"
      },
      {
        "url": "https://nix.dev/index.html",
        "name": "Nix Dev"
      }
    ]
  }
]
// for profiles
// default-bookmarks.json
// alternative-bookmarks.json
[
  {
    "name": "Some bookmarks...", // directory name won't show if `toolbar = true`, first level will be level 0 in toolbar
    "toolbar": true, // required to show in toolbar, else a directory in menu
    "bookmarks": [
      {
        "url": "https://google.com#top-link-1",
        "name": "Top Link #1"
      },
      {
        "url": "https://google.com#top-link-2",
        "name": "Top Link #2"
      },

      {
        "name": "Nested Links #1",
        "bookmarks": [
          {
            "url": "https://google.com#nested-link-1-1",
            "name": "Nested Link #1"
          },
          {
            "url": "https://google.com#nested-link-1-2",
            "name": "Nested Link #2"
          }
        ]
      },

      {
        "name": "Nested Links #2",
        "bookmarks": [
          {
            "url": "https://google.com#nested-link-2-1",
            "name": "Nested Link #1"
          },
          {
            "name": "Sub-Nested Links #1",
            "bookmarks": [
              {
                "url": "https://google.com#sub-nested-link-1",
                "name": "Sub-Nested Link #1"
              },
              {
                "url": "https://google.com#sub-nested-link-2",
                "name": "Sub-Nested Link #2"
              }
            ]
          }
        ]
      }
    ]
  }
]
1 Like

Thanks! That’s good info. Not surprising that programs.firefox.<name>.bookmarks is implemented like that.

I have a, possibly mis-placed, aversion to using Firefox policies (hence why I chose to use a profiles option when importing bookmarks). From what little research I did before hand, it seems like policies is more commonly used by enterprises, and profiles by individual users. I figured since I’m not an enterprise, I’d use profiles. So far I don’t regret that choice, but I’ve gotten the impression that more Nix users use policies.

It kind feels odd to have to parse bookmarks to comply to Nix and then Nix re-format them on build :joy:

You might be able to override “default” policies per profiles (?)
policies still have their use for the “average user”, e.g if you wanna pre-configure your browser (e.g extensions can be set in policies). It’s only less common to do so on non-Nix environments