Need help adding custom templates to OnlyOffice Desktop Editors

I have a document that I want to add as a template to OnlyOffice.

At first, I discovered that in my home folder, under ~/.local/share/onlyoffice/desktopeditors, there is literally a file called templates.xml. This contains the paths to the default templates OnlyOffice ships with. But adding the path to my custom template (even with the right format) only works until I rebuild the system. It seems the file itself is regenerated during a rebuild, so any changes I make are lost.

Then I checked that templates.xml file again and found that the default template files are found in the nix store, at this path: /nix/store/onlyoffice-bin/share/desktopeditors/converter/templates/EN/Documents

Opening this folder shows me the same default template files there too.

Now, my guess is if my custom template file was present in this folder, it would probably get detected and added automatically in the templates.xml file I found previously. But since the nix store is read only, I can’t even test this. So I’m somewhat stumped on what to do.

Is there an easier way to do all this that I’m missing? Or at the very least, can I somehow add my custom template file to the nix store path where the default templates are and see if that changes anything?

I’ve had to implement a number of imperative workarounds for OnlyOffice to get fonts to work correctly. Without knowing any details about your configuration, I think the best way to implement what I think you want (which is a custom template entry) would be to append it with a Home manager activation script (assuming you are using Home manager).

Here is an example implementation using my configuration as a template:

{
config,
lib,
pkgs,
…
}:
# Workaround for OnlyOffice font issue:
# https://github.com/NixOS/nixpkgs/issues/373521
let
  hmFonts = “${config.home.profileDirectory}/share/fonts”;
  ooFonts = “${config.xdg.dataHome}/fonts/onlyoffice”; # ~/.local/share/fonts/onlyoffice
in
{
home.packages = with pkgs; [
  hunspell # Dictionary
  hunspellDicts.en_US
];

programs.onlyoffice = {
  enable = true;
  settings = {
    UITheme = “theme-night”; # the internal ID for Modern Dark
  };
};

# Populate ~/.local/share/fonts with ttf files (not symlinks)
home.activation = {
  onlyofficeUserFonts = lib.hm.dag.entryAfter [ “writeBoundary” ] # sh
    ''
      set -eu
      rm -rf "${ooFonts}"
      mkdir -p "${ooFonts}"

      # Copy actual files (dereference symlinks with -L)
      if [ -d "${hmFonts}" ]; then
      	${pkgs.rsync}/bin/rsync -aL \
      	--include='*/' --include='*.ttf' --include='*.otf' --exclude='*' \
      	"${hmFonts}/" "${ooFonts}/"
      fi
      chmod -R 744 "${ooFonts}"

      ${pkgs.findutils}/bin/find "${ooFonts}" -type f \( -name '*.ttf' -o -name '*.otf' \) -exec chmod 0644 {} \;
      ${pkgs.fontconfig}/bin/fc-cache -f "${ooFonts}" >/dev/null 2>&1 || true
    '';

onlyofficeTemplates = lib.hm.dag.entryAfter [ "writeBoundary" "onlyofficeUserFonts" ] # sh
    ''
      set -eu

      TEMPLATES_FILE="${config.xdg.dataHome}/onlyoffice/desktopeditors/templates.xml"
      MY_TEMPLATE_PATH="${config.home.homeDirectory}/Templates/my-template.docx"
      MY_TEMPLATE_NAME="My Custom Template"

      if [ ! -f "$TEMPLATES_FILE" ]; then
        printf "templates.xml not found, skipping (OnlyOffice will create it on first launch)\n"
        exit 0
      fi

      if ${pkgs.gnugrep}/bin/grep -qF "$MY_TEMPLATE_PATH" "$TEMPLATES_FILE"; then
        printf "Custom template already present, nothing to do\n"
        exit 0
      fi

      # Determine the next available template ID
      LAST_ID=$(${pkgs.gnugrep}/bin/grep -oP 'id="\K[0-9]+' "$TEMPLATES_FILE" | sort -n | tail -1)
      NEXT_ID=$(( LAST_ID + 1 ))

      # Insert the new template entry before the </templates> tag
      ${pkgs.gnused}/bin/sed -i \
        "s|</templates>|\t<template id=\"$NEXT_ID\" name=\"$MY_TEMPLATE_NAME\" path=\"$MY_TEMPLATE_PATH\" pin=\"0\" format=\"65\" />\n</templates>|" \
        "$TEMPLATES_FILE"

    '';

  };
}

You can read documentation on home.activation scripts here:

And here:

Basically it lets you define a ordered list of scripts that will run when activating your new configuration. In this example I define two scripts: onlyofficeUserFonts, and onlyofficeTemplates that will run on activation, and you should see them listed in the activation output:
Activating onlyofficeUserFonts
Activating onlyofficeTemplates

The template script assumes you have XDG paths configured and just has a placeholder name for your template here:

      TEMPLATES_FILE="${config.xdg.dataHome}/onlyoffice/desktopeditors/templates.xml"
      MY_TEMPLATE_PATH="${config.home.homeDirectory}/Templates/my-template.docx"
      MY_TEMPLATE_NAME="My Custom Template"

You will want to change these variables to match the correct paths, filenames, and templates you want to use, but you should be able to figure that out from this example.

Why is this all so complicated? Well, for a single user on a single machine, it probably isn’t worth all this effort, but if you were going to provision 25 machines for 50 different users in a business it would make much more sense. You could have templates defined for people in sales, and people in marketing, and then programmatically configure templates based on work roles, etc. and manage them all in a single repository.

Hope this helps. Good luck.

Hi, thanks for your help, it worked perfectly. I wasn’t entirely familiar with Home Manager so it took me a while to implement, but I got it working as a system module and adapted your config and it looks to be working just as needed.

I’m glad you were able to figure it out and get it to work for you.