Images and attachments
An attachment is not a record in a media library. It is a file in your repository, sitting in a
folder called _attachments, committed alongside the pages that reference it. Clone the
repository and you have the images; delete the repository and they are gone with it. There is no
separate asset store to back up and nothing to migrate.
Where they live
Each project keeps its own _attachments/ folder directly under the project directory:
handbook/
├── index.md
├── onboarding.md
├── policies/
│ ├── index.md
│ └── expenses.md
└── _attachments/
├── org-chart.png
└── expense-policy.pdf
A folder named _attachments is skipped by the walker that builds the page tree — case
insensitively, at any depth — so nothing inside it is ever listed or rendered as a page. Even a
.md file in there is ignored. Repository layout
covers the rest of the tree.
Adding an image in the editor
The toolbar has one upload control, an icon button labelled Upload image, in the same group as Insert link and Link to a document. It opens your operating system’s file picker, filtered to image files.
Pick a file and that is the whole interaction. There is no dialog, no preview step, and no
confirmation: the file is uploaded into the project’s _attachments/ and the image appears at
your cursor immediately. A failure raises a single alert reading Upload failed.
The upload writes the file to disk straight away, but the document is still unsaved — the image
reference only reaches the .md file when you press Save.
What happens to the file name
The name is lowercased, and every character outside a-z, 0-9, ., _, and - becomes a
hyphen, with runs of hyphens collapsed. Screen Shot 2026.PNG lands as screen-shot-2026.png.
Nothing is de-duplicated and nothing is ever overwritten. Upload the same picture twice and
you get logo.png and logo-1.png — two identical files. A different file that happens to share
a name gets the same numbered suffix. Renaming a file before you upload it is the only way to
control what it ends up called.
The upload size ceiling is 200 MB per file by default. It is worth staying a long way under that, for reasons the Git section below explains.
What the editor does not do
- No drag and drop. Dropping an image onto the page does nothing.
- No paste. The editor takes plain text from the clipboard and discards the rest, so pasting a screenshot inserts nothing at all. Save it to a file first and use Upload image.
- No non-image upload. The picker accepts images only. A PDF, a spreadsheet, or a ZIP gets
into
_attachments/by being copied there with your file manager and committed like any other file. - No alt text prompt. The editor writes
with the description empty. Fill it in yourself in the source view — it is what a screen reader reads out, and it is indexed for search.
Referencing an attachment
The editor writes the reference as an absolute application path, which is stable wherever the document later moves to inside its project:

Written by hand, a plain relative path works too, and is resolved against the folder the document
sits in — so the number of ../ steps depends on how deep the page is:
 from handbook/onboarding.md
 from handbook/policies/expenses.md
Both forms end up pointing at the same file. Either way the reference resolves within its own
project: a path that climbs out into another project’s _attachments/ is left alone and does
not resolve.
Non-image attachments use ordinary link syntax rather than image syntax:
The full text is in [the expense policy](_attachments/expense-policy.pdf).
Clicking that link on the server downloads or opens the file directly rather than trying to navigate to it as a page.
What exports do with them
Markdown export is literal — you get the .md file, references and all, with no files bundled
alongside it.
Self-contained HTML and PDF export behave differently depending on how the attachment is referenced:
| In the page | In an HTML or PDF export |
|---|---|
An image (.png, .jpg/.jpeg, .gif, .svg, .webp) | Read from disk and embedded as a base64 data URI |
| Anything else, linked rather than embedded | Left as a link — the file itself is not included |
So an exported HTML file shows its pictures on a machine that has never seen your repository, but a link to a PDF in that same export points at a server the reader may not be able to reach. If an attachment has to travel with the document, put it in as an image. If it cannot be an image, send it separately.
Attachments and Git
Attachments are ordinary tracked files. Save a snapshot stages every new file under an
_attachments/ folder along with new and changed .md files, so an image you uploaded this
morning goes into the same commit as the paragraph you wrote about it. Nothing else new is swept
in — the staging rules are in
Connect your Git repository.
Three things follow from attachments being real files in real commits, and all three are worth knowing before a repository gets large.
Binaries grow history the way they do in any repository. Git stores a full new copy of a changed binary, and history is forever. A 12 MB uncompressed screenshot re-uploaded weekly costs 12 MB of permanent history each time. Export images at the size they are displayed at, and prefer PNG or WebP for screenshots; the discipline is the same one you would apply to a code repository.
Git LFS is not supported. Do not enable it on a DocuCommit repository. An LFS-tracked
_attachments pattern would replace each image with a small text pointer file on push, and every
other clone — including the server’s — would sync those pointers instead of the images. Pages
would render broken images with no obvious cause. There is no LFS support to switch on, so the
only safe configuration is not to use it.
A conflicting attachment has no merge view. The merge screen reads both sides as UTF-8 text, which is meaningless for an image. The path appears in the conflict list like any other, but you decide which file you want rather than merging them. See Resolve conflicts for how that screen behaves.
Housekeeping is yours
Nothing removes an attachment. There is no delete action, no unused-file report, and no cleanup
pass: deleting a document leaves its images in _attachments/, and moving a document to another
project copies its attachments across without removing the originals. The folder only ever grows.
That is not a serious problem at documentation scale, but it does mean the tidying is a manual
job. Delete the files with your file manager or git rm, and commit the removal as its own
snapshot.