# File Naming Conventions in Zakirullin Files: Rules and Best Practices

> Discover Zakirullin Files naming conventions. Learn best practices for using filenames as unique document identifiers for storage, sync, and UI display.

- Repository: [Artem Zakirullin/files.md](https://github.com/zakirullin/files.md)
- Tags: best-practices
- Published: 2026-05-21

---

**In Zakirullin Files, the filename (including the `.md` extension) serves as the unique identifier for every document, acting as the primary key for storage, synchronization, and UI display across all platforms.**

Zakirullin Files is an open-source, Markdown-based knowledge management system that stores all data as plain text files. Understanding the file naming conventions is essential for maintaining compatibility between the web interface and Go-based back-end while ensuring reliable cross-platform synchronization.

## The Filename as Unique Identifier

In [`zakirullin/files.md`](https://github.com/zakirullin/files.md/blob/main/zakirullin/files.md), the **filename** itself functions as the primary key for every document. According to [`README.md`](https://github.com/zakirullin/files.md/blob/main/README.md), the system treats the filename (e.g., [`note.md`](https://github.com/zakirullin/files.md/blob/main/note.md)) as the unique ID when locating, synchronizing, and linking files. This design eliminates the need for database indices or UUIDs, keeping the architecture portable and simple.

When the back-end processes a file, it extracts the filename from the path and uses it for all subsequent operations:

```go
// Example of creating a new file (server side)
func (fs *FS) Put(path string, content []byte) error {
    filename := toFilename(path)                // e.g. "note.md"
    if strings.TrimSpace(filename) == "" {
        return errors.New("filename cannot be empty")
    }
    // The filename is the unique identifier for the file
    // …
}

```

## One-Level Directory Nesting

The application enforces a strict **one-level nesting policy** to simplify path handling. A file is uniquely identified by the combination of its directory and filename, where the directory is either the root (`/`) or a predefined top-level folder such as `brain/`, `journal/`, or `habits/`.

This constraint, documented in [`README.md`](https://github.com/zakirullin/files.md/blob/main/README.md), prevents complex recursion issues in both the client and server code. The file-to-path index in [`web/files.js`](https://github.com/zakirullin/files.md/blob/main/web/files.js) relies on this flat structure to build efficient lookup tables without traversing deep directory trees.

## File Extensions and Type Handling

All content files must use the **`.md` extension** to ensure the Markdown parser can process them correctly. Non-Markdown assets such as images, videos, and other media files must reside in the dedicated `media/` folder and retain their original extensions (e.g., `.png`, `.jpg`).

This separation guarantees that the sync engine and UI renderer can distinguish between editable notes and static attachments without inspecting file contents.

## Forbidden Characters and Sanitization

To ensure cross-platform compatibility across Windows, macOS, and Linux, the system strips specific characters from all user-provided filenames. In [`web/lib/fs.js`](https://github.com/zakirullin/files.md/blob/main/web/lib/fs.js), the `sanitizeFilename` function removes the following prohibited characters: `< > : " | \ ? * \0 /`.

```javascript
// web/lib/fs.js – sanitising a filename before any filesystem operation
const FORBIDDEN_FILENAME_CHARS = ['<', '>', ':', '"', '|', '\\', '?', '*', '\x00', '/'];
function sanitizeFilename(filename) {
    // Remove all prohibited characters
    return FORBIDDEN_FILENAME_CHARS.reduce(
        (result, ch) => result.replaceAll(ch, ''), filename);
}

```

This sanitization runs automatically during every rename or create operation, preventing filesystem errors when files are saved to Windows drives or cloud storage services with strict naming rules.

## ASCII-Only Policy and Encoding

While the system supports Unicode, **non-ASCII characters are discouraged** in filenames. When present, users must disable quoting (as documented in [`docs/your-own-server.md`](https://github.com/zakirullin/files.md/blob/main/docs/your-own-server.md)) to prevent encoding issues during API transfers that expect URL-safe strings.

For maximum compatibility, the documentation recommends using descriptive, short, ASCII-only names that are easy to type and share across different operating systems.

## Uniqueness Constraints

Filenames must be **unique within their directory**, with enforcement performed case-insensitively. The system does not allow two files with identical names (such as [`Note.md`](https://github.com/zakirullin/files.md/blob/main/Note.md) and [`note.md`](https://github.com/zakirullin/files.md/blob/main/note.md)) to exist in the same folder.

This rule, implemented in the synchronization logic, guarantees deterministic lookups and prevents collision errors during rename operations. The sync engine detects changes by comparing header-derived filenames with actual file paths, as detailed in [`docs/sync-flow.md`](https://github.com/zakirullin/files.md/blob/main/docs/sync-flow.md).

## Header Generation from Filenames

The **display header** for each file is automatically derived from its filename by stripping the `.md` extension and capitalizing the first letter. For example, [`note.md`](https://github.com/zakirullin/files.md/blob/main/note.md) becomes `Note` in the UI navigation and linking system.

This convention ensures consistency between the filesystem representation and the user-facing interface without requiring separate metadata files or frontmatter.

## Practical Naming Patterns

The repository recommends descriptive, human-readable names following these common patterns:

- [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md) – Central conversation log
- [`brain/Note.md`](https://github.com/zakirullin/files.md/blob/main/brain/Note.md) – Knowledge note in the "brain" category
- `journal/2024.08 August.md` – Dated journal entry with period notation
- `habits/Ate consciously.md` – Habit tracking file
- `media/photo.png` – Attached image asset

These patterns support a Zettelkasten-style workflow while maintaining the simplicity required by the flat file structure.

## Summary

- **Filename as ID**: The filename (including `.md`) serves as the unique primary key for all storage and sync operations in [`zakirullin/files.md`](https://github.com/zakirullin/files.md/blob/main/zakirullin/files.md).
- **One-level nesting**: Files reside either in the root or in specific top-level directories like `brain/` or `journal/`, with no subdirectories allowed.
- **Extension requirement**: Content files must end with `.md`, while media files belong in `media/` with original extensions.
- **Character sanitization**: The `sanitizeFilename` function in [`web/lib/fs.js`](https://github.com/zakirullin/files.md/blob/main/web/lib/fs.js) automatically removes characters like `<`, `>`, `:`, `"`, `|`, `\`, `?`, `*`, `\0`, and `/`.
- **Uniqueness**: Duplicate filenames (case-insensitive) are prohibited within the same directory to prevent collision errors.
- **Header derivation**: UI display names are generated by removing the extension and capitalizing the first letter of the filename.

## Frequently Asked Questions

### What characters are forbidden in Zakirullin Files filenames?

The system automatically strips the following characters from all filenames: less-than (`<`), greater-than (`>`), colon (`:`), double quote (`"`), pipe (`|`), backslash (`\`), question mark (`?`), asterisk (`*`), null byte (`\0`), and forward slash (`/`). This sanitization occurs in [`web/lib/fs.js`](https://github.com/zakirullin/files.md/blob/main/web/lib/fs.js) to ensure compatibility with Windows, macOS, and cloud storage providers.

### How does Zakirullin Files handle file organization and subdirectories?

The application supports only **one level of directory nesting**. Files can exist in the root directory or in predefined top-level folders such as `brain/`, `journal/`, or `habits/`. The system identifies each file by the pair `(directory, filename)`, simplifying path resolution in both the web client and Go back-end.

### Why must Markdown files use the .md extension in Zakirullin Files?

The `.md` extension is mandatory for content files because the system relies on this suffix to identify parseable Markdown documents. This distinction allows the sync engine to separate editable text files from media assets, which must be stored in the `media/` directory with their original extensions preserved.

### How are display titles generated from filenames in the UI?

The web interface generates headers by removing the `.md` extension and capitalizing the first character of the remaining string. For example, a file named [`project-ideas.md`](https://github.com/zakirullin/files.md/blob/main/project-ideas.md) displays as `Project-ideas` in the navigation. This convention ensures consistency between the filesystem and the user interface without requiring separate metadata files.