Last Updated: July 9, 2026
This file serves as a single, up-to-date reference for agents and contributors working on PhotoPrism's public documentation. It explains where canonical content is located, how to preview and ship changes, and which conventions maintain consistency between https://docs.photoprism.app/ and the main application repository at https://github.com/photoprism/photoprism/.
README.md— contributor onboarding, MkDocs overview, and deployment expectations for this repository.mkdocs.yml— primary navigation tree (Getting Started, User Guide, Developer Guide, About) and metadata used by MkDocs Material. Thenav:map is the sole source of truth for site navigation, so every new page must be registered there before it becomes visible in the UI.mkdocs.deploy.yml— release-time configuration that enables the privacy plugin, mirrors remote assets, hosts the production redirect rules, and runs thellms.txtbuild hook (hooks/llmstxt.py; seeLLMS.md).- Main app references:
AGENTS.mdandCODEMAP.mdin the mainphotoprism/photoprismrepo (https://github.com/photoprism/photoprism) remain authoritative for product behavior, CLI semantics, and backend/frontend boundaries. - Published docs: https://docs.photoprism.app/ is the live contract; verify edits there before referencing version-specific behavior.
- Contributor process notes:
docs/developer-guide/documentation.md,docs/developer-guide/pull-requests.md, anddocs/developer-guide/reviewing-pull-requests.mddescribe how documentation changes are reviewed alongside code. - Make targets defined in
Makefile(e.g.,make deps,make watch,make merge) are the supported way to install dependencies, run MkDocs, resize images, and deploy.
- MkDocs pulls Markdown from
docs/, where the top folders align with the site navigation:getting-started/,user-guide/, anddeveloper-guide/. Keep new topics inside these trees to benefit from inherited index pages and localimg/directories. - Directory names mirror canonical URLs, not necessarily the navigation hierarchy. For example,
docs/release-notes.mdrenders at https://docs.photoprism.app/release-notes/ for a short path, even though its nav entry lives under “User Guide > Release Notes”. Maintain these short-link exceptions when they exist. - Landing and shared pages live at
docs/index.md,docs/known-issues.md,docs/release-notes.md,docs/credits.md, anddocs/license/(AGPL, Apache, and documentation terms). Update these when legal notices or release metadata change. - Static assets ship from
docs/img/(global) and the section-specificimg/folders. Icons and favicons reside indocs/icons/; logos includedocs/icons/logo/*.svgplusdocs/icons/LICENSE. - Styling overrides belong in
docs/css/custom.css. Theme overrides live inoverrides/(main.htmlfor OG/Twitter tags and analytics,partials/copyright.htmlfor footer text). - Work-in-progress drafts go under
todo/(currentlytodo/developer-guide/setup-fedora.md). Clearly mark TODO files until they are promoted intodocs/.
- Build tool: the site is built with ProperDocs, a maintained drop-in fork of MkDocs 1.x (MkDocs core is EOL; its planned 2.0 removes the plugin system). It reads
mkdocs.ymlunchanged, keeps every plugin and thellms.txthook working, and silences the MkDocs-2.0/ProperDocs build warnings.makeand CI invokeproperdocs;mkdocsstays installed only as a dependency of the Material theme. - Local Python environment: run
make depson Debian/Ubuntu (installs system packages) ormake installelsewhere. Both targets createvenv/, grab MkDocs Material (the former Insiders build now ships via PyPI, so noGH_TOKENis required), and pull all pinned requirements fromrequirements.txt. - Refresh dependencies with
make upgradewhenever you need the latest MkDocs Material release; it rebuilds the virtualenv before you start working. - Preview:
make watch(alias formake serve) invokes./venv/bin/properdocs serve --watch docs --watch overrides --watch mkdocs.yml -a 0.0.0.0:8000(ProperDocs enables livereload by default). A common loop ismake upgrade && make watch, then browse http://localhost:8000/ while it hot-reloads Markdown, templates, and configuration. - Build artifacts:
make buildrenders the production site usingmkdocs.deploy.yml, whilemake deployrunsproperdocs gh-deploy --force --config-file mkdocs.deploy.ymlfor manual GitHub Pages pushes. The rendered HTML lands insite/locally—never edit files there by hand or commit that directory. - Image hygiene:
make img-resize(ImageMagickmogrify) enforces a1000x860max width for specific folders. Run it after adding screenshots todocs/user-guide/imgordocs/getting-started/**/img. - Spell check:
make spellcheckrunstyposoverdocs/, configured in_typos.toml.make install-typosfetches a pinned, checksum-verified binary intobin/— there is no GitHub Action, and no interpreter or package manager is involved. It only flags words in a curated typo list, so a finding is almost always real; add genuine product terms and personal names to_typos.tomlrather than working around them. Apply fixes with./bin/typos --write-changes docs/. - Prose style (optional, under evaluation):
make valerunsvalewith the in-repo house style understyles/PhotoPrism/, installed the same way viamake install-vale. It is deliberately not a gate — the target swallows a non-zero exit status, and it is not part ofmake build. Findings are advisory while we judge whether prose linting earns its keep; do not treat them as a review blocker. - Containerized workflow: the repo's own
Dockerfile(FROM squidfunk/mkdocs-material:latest, nothing else) is not maintained — don'tdocker buildit, as it lacks the extra plugins (mkdocs-redirects,mkdocs-tooltips). To build without installing a host toolchain, run the upstreamsquidfunk/mkdocs-materialimage andpip install -r requirements.txtat run time; the exact command is inREADME.md/CLAUDE.md(§ Building in a Container).
mkdocs.ymldefines navigation, metadata (site_name,extra.social, edit links), plugins (search,redirects), theme options, and Markdown extensions (pymdownx, tooltips, tabs, mermaid). Always update nav entries and redirect maps in this file when adding or moving pages.mkdocs.deploy.ymlinherits frommkdocs.yml, re-declares the plugins with the production redirect map, and adds theprivacyplugin plus ahooks:entry (hooks/llmstxt.py, which generates/llms.txt+/llms-full.txt— seeLLMS.md). When you add redirects, mirror them in both configs so local previews and production builds behave the same.overrides/contains the only custom templates.overrides/main.htmlaugments meta tags, favicons, analytics, and announcement banners; update it when branding or tracking domains change.overrides/partials/copyright.htmlinjects footer copy.docs/css/custom.cssholds layout tweaks for the Material theme; limit overrides to what cannot be configured inmkdocs.ymland keep selectors scoped to avoid regressions.LICENSE(root) covers the repository;docs/license/docs.mdspells out the documentation license (CC BY-NC-SA 4.0). Keep legal text in sync with the main application repository when terms change.- Helper directories:
venv/(local virtualenv),site/(build output), andtodo/(drafts) are workspace artifacts; they should remain uncommitted and are safe to delete when resetting your environment.
- Headings, link titles, and navigation labels must use Chicago-style title case, matching the main repository’s style requirement. When copying headings from other sources, normalize them before committing.
- Prefer Markdown over raw HTML; use MkDocs Material components (admonitions, tabs, tooltips) configured in
mkdocs.yml. When HTML is unavoidable, keep it minimal and validate thatmake watchrenders it correctly in dark/light themes. - Update
mkdocs.ymlnavigation whenever you add, rename, or move a page. If a URL changes, add a redirect entry to bothmkdocs.ymlandmkdocs.deploy.ymlso legacy links stay valid. - Store images next to the Markdown that references them (for example,
docs/user-guide/organize/img/). Optimize screenshots before committing and include descriptive alt text in Markdown. - Reuse canonical CLI flags, file paths, and configuration snippets from the main PhotoPrism repository. When documenting new application behavior, confirm the implementation in
photoprism/photoprismbefore publishing. - Front matter: use MkDocs
metablocks (or thepage.metakeys referenced inoverrides/main.html) when you need a custom page title or social caption. Avoid adding bespoke metadata keys unless templates consume them.
Title Case rules (Chicago-style, with code- and path-aware normalization):
- Capitalize the first word, the first word after a colon, dash, or end punctuation, and all major words, including the second part of a hyphenated major word.
- Lowercase only articles, short conjunctions, and short prepositions of three letters or fewer when they are not in one of those positions.
- Preserve known acronyms (for example, API, CLI, HTTP, JSON) and slash-separated acronym groups (for example, CSV/TSV) as uppercase.
- Preserve inline code spans (
`foo`), file paths (e.g.docs/foo-bar.md), and slash commands (e.g./grill-me) verbatim; do not recase their contents.- Use
&instead ofAnd/Orin headings.
Use concise, imperative subjects with a one-word prefix indicating the scope or topic:
Config: Add tests for "darktable-cli" path detection
If the commit relates to specific issues or pull requests, reference their IDs in the message:
Docker: Use two stage build to reduce image size #123 #5632
Commit messages must not exceed 80 characters in length.
Issue titles MUST be concise, use the imperative mood, and start with a single capitalized prefix followed by a colon and a space, e.g. Search: Add filter for RAW image formats.
Issue descriptions MUST begin with a one-sentence User Story where the sentence itself is fully bold in the format: **As a <role>, I want <goal>, so that <outcome>.**
Follow the User Story with a clear summary of the expected behavior, rationale, technical considerations, and constraints.
Descriptions MUST conclude with a checklist of Acceptance Criteria:
- Use GitHub checklist formatting:
- [ ] - Criteria MUST be clear, testable, and unambiguous.
- Each item MUST use one of the following priority keywords:
MUST— required for the issue to be considered completeSHOULD— strongly recommended but not strictly requiredMAY— optional enhancement
Additional details MAY be included as needed, such as related issues, references, screenshots, or external resources.
Agents MUST create, edit, close, reopen, relabel, or otherwise modify GitHub issues only when explicitly requested by the user.
- Working branch is
develop. Mergedevelopintodeploy(or runmake merge) to trigger the GitHub Actions pipeline that rebuilds and uploads docs to docs.photoprism.app. Always resolve conflicts locally so deployment commits stay clean. mkdocs deployis reserved for emergency GitHub Pages pushes; it writes to thegh-pagesbranch. Coordinate with maintainers before using it so automation does not overwrite manual changes.- The built-in
privacyplugin (part of Material for MkDocs, enabled inmkdocs.deploy.yml) mirrors external assets (badges, images) into the site. Keepassets_excludeup to date when new PhotoPrism-owned domains are introduced. - Verify redirects, social previews, and structured data locally with
make buildbefore merging. Production uses the same config, so a clean local build is the release gate.
- Never commit credentials. MkDocs Material Insiders is now public on PyPI, so we no longer ask contributors to add
GH_TOKENvalues to.env; keep that file untracked if you use it for other local overrides. - Treat
docs/license,docs/icons/LICENSE, anddocs/img/LICENSEas authoritative for third-party assets. Confirm redistribution rights before adding new binaries or artwork. - All social sharing and analytics scripts live in
overrides/main.html. Review those tags when changing analytics providers to ensure we only load scripts from approved domains (a.photoprism.appfor outbound tracking). - Follow the main repository’s security and contribution policies (see
SECURITY.mdandCONTRIBUTING.mdin photoprism/photoprism) when referencing vulnerabilities or non-public features in these docs.