Directories

This is probably one of the more detailed areas of my project setup. The layout of a project has two purposes: organization and revealing information.

Keep the Root Clean

Like my $HOME directory, I strive to keep my project roots as empty or clean as possible. The purpose is to give a high-level of the project.

But, even though many “dotfiles” such as .prettier and .gitignore are hidden when listing directories, they are not hidden in forge listings which gives a much longer list.

There are some things the root must have: read me, licenses, .gitignore, and other high-level.

Source

Whenever possible, all source code should go into the //src/. It doesn't matter the language or multiple languages. Some languages, like C#, will result in a number of assemblies which can create a large number of directories.

Exceptions

There are times when I have exceptions. For example, in writing projects, I use //src/ for code to support the project but //chapters/ for the individual chapters. My gut feeling is that it should be //src/chapters/ but I've resisted because I have 300+ projects that would need to be migrated.

Tests

The exception to the source code are tests. One of the first things when I'm stuck with a project is look at the source files. Pulling them out of //src/ and into //tests/ makes it easier to do searches in the code, use wild cards for figuring out what needs to be packages, and general keeps them relatively isolated.

Examples

A third category of source code are the examples. I put those in //examples/ much for the same reason I pulled //tests/ out.

Examples are stand-alone examples, basically CLI or applications. They will demonstrate an end-to-end implementation of a project. Since they are also built as part of the build process and used in the testing, they are checked as part of the build to ensure they stay up to date.

Documentation

I'm a strong believer in documentation in the code instead of a separate wiki. To that regard, my “wiki” is part of the source code and put into //docs/ folder. This is treated as a simple Markdown site with relative links pointing to the other Markdown files as this is a [link](../just/).

There are a couple reasons I do this. The main one is because I don't like when documentation doesn't match the source code. On the forges, there is a disconnect between the two projects and sometimes the wiki refers to code that “use to be” or “will be” but not always “currently is”.

Another reason is if the root project is loaded, then doing a search on the project will also search the documentation (and example and tests).

For my websites that format these documentation, such as my garden plots or software documentation, the code that generates those sites knows to convert the relative .md links into the proper format.

News and Blogs

Like the documentation, I found that putting the news and announcements in the wiki also coordinate it. It means that a pull request can have an announcement that will not go live until it is merged into the code. Also, I use this to track typos in the news and fix them via pull requests or feedback.

XDG-Based Folders

Many of these directory suggestions are based on the XDG Specification to store specifics parts of the system. This gives a semi-consistent location with known guidelines of what goes where.

Configuration

Project configuration should go into //.config/. This is based on XDG's XDG_CONFIG_HOME. Some tools, like dotnet use that and it keeps the clutter of .prettierignore and .editorconfig and other files out of the root.

This is why I have site-specific configurations use //.config/fedran.json or //.config/dmoonfire-website.json placed there.

Sadly, most tools don't support this at this point, but as they do (or they can be configured via the Justfile), then I will move them into the //.config/ directory. Unfortunately, sometimes this involves having to teach editors and other tools where it is, so I would rather have the individual tools also look in the .config folder for their settings.

Cache

Caches. Many projects need a temporary store that is never checked in. XDG uses XDG_CACHE_HOME which defaults to $HOME/.cache so caches should be put into //.cache/ in much the same manner.

I use this with Fiss to store the database files which are only used to cache the results from the forges.

Executables

Executables and scripts are put in //.local/bin/ based on those conventions. These are also added to the PATH as part of the setup.

Data

For generated data for a project, that needs to be checked in but is not intended for user-editing, is put in the equivalent of the XDG_DATA_DIR which is //.local/share/.

This is where I would put tag files, automated analysis for my novels, or anything that needs to go with the project but is basically “noise”.

State

State, which is based on XDG_STATE_DIR is generated or user-state files that are not to be checked into the code. This can include things like window states, the current position of a program, or per-user settings.