quarto

How to automatically derive a custom order for the side navigation of a website?


I have a relatively simple question about quarto website. In _quarto.yml I've set auto for contents (sidebar formation):

website:
  sidebar:
    contents: auto

Besides I have the following structure of sub-folders.

/project
--/ 01_basics
    - index.qmd  # title: "Basics"
--/ 02_animals
    - index.qmd  # title: "Animals"

-- _quarto.yml

The rendered sidebar looks as follows (alphabetic order):

But I want it to be in the reversed order. Actually I've made the numbering of subfolders to organize the workspace and with the hope that it rules the order of the sidebar. I've added more explicit titles in index files (which seems to be a correct practice), but they eventually had changed the order of sections.

Question: What is the recommended way to order sub-folders in the sidebar without explicit numbering them in titles?


Solution

  • The numbering of the subfolders containing the different index.qmd has no relevance for the order of the navigation items within the sidebar. Generally there are some possibilities for defining a custom order:

    In your example, you have several subfolders, numbered e.g. 04_folder, and would like to order the navigation content as defined by the number of the folder. Similar to the second point above, we therefore could set a corresponding order within the different index.qmd. It would e.g. look like this:

    /project
    --/ 01_basics
        - index.qmd  # title: "Basics",    order: 1
    --/ 02_animals
        - index.qmd  # title: "Animals",   order: 2
    --/ 04_humans
        - index.qmd  # title: "Humans",    order: 4
    --/ 99_appendix
        - index.qmd  # title: "Appendix",  order: 99
    

    This can be achieved by using a Pre-Render script. Here is one example using Python (may have to be refined for your use case, but generally works for a minimal example):

    prepare.py

    import os
    
    rootdir = os.getcwd()
    folders = [fo for fo in os.scandir(rootdir) if fo.name[2] == "_"]
    
    for fo in folders:
        for filename in os.listdir(fo):
            if filename == "index.qmd":
                with open(os.path.join(fo, filename), "r") as f:
                    lines = [line for line in f.readlines() 
                             if not line.startswith("order: ")]
                    
                    index = lines.index("---\n", 1)
                    lines.insert(index, "order: " + str(int(fo.name[:2])) + "\n")
                with open(os.path.join(fo, filename), "w") as ff:
                    ff.writelines(lines)
    

    Locate this script within your project directory and reference it within the _quarto.yml via

    project:
      ...
      pre-render: prepare.py
    

    Then it provides the order field within the respective document metadata inside the index.qmd and you obtain your desired order.

    Example image