---
title: Publish a document
summary: Add a Markdown or HTML file, preview it, and publish a stable link to the company library.
owner: Platform
tags:
  - getting-started
  - publishing
---

# Publish a document

Commons is the shared public library for Vimaksh. You write a file; Commons
adds a page, an entry in the library, and searchable text. You keep the original
file and its attachments in Git.

## Install once

You need Python 3.11 or newer, Git, and access to the private repository.
Authenticate Git with your normal GitHub credentials. If you use GitHub CLI:

```bash
gh auth login
gh auth setup-git
```

Install the CLI with [uv](https://docs.astral.sh/uv/):

```bash
uv tool install git+https://github.com/prag-man/commons.git
commons init
cd commons
```

If you have already cloned the repository, run commands there instead of
`commons init`. For development, use `uv sync --frozen` and prefix commands
with `uv run --frozen`.

## Add a file

```bash
commons add ~/notes/decision.md --owner Platform --tag decisions
commons add ~/reports/experiment.html --owner Research --tag experiments
```

No front matter is required. Commons infers a title from the first Markdown
heading or the HTML title, and creates a summary from readable text. Set
`--title`, `--summary`, and `--slug` when you want to choose them explicitly.

```bash
commons add ~/notes/decision.md \
  --title "How we publish documents" \
  --slug publishing-decision \
  --summary "The choices behind the shared library." \
  --owner Platform --tag decisions
```

Each document gets a stable address:

```text
https://commons.vimaksh.in/d/publishing-decision/
```

`commons add` only imports the file into your local checkout. It does not
commit, push, or publish anything.

## Preview and publish

```bash
commons preview
```

Open the printed `127.0.0.1` URL. Check the document and try finding it with
search. Press Ctrl+C when finished. Use `--port 8766` if the default port is
already in use.

```bash
commons publish
```

This validates and builds the library, commits changes under `documents/`, and
pushes to `main`. Connected hosting rebuilds after that push. The CLI reports **pushed**,
which means Git accepted the changes; it does not claim that deployment has
finished. A successful hosting build makes the new page live.

**Initial rollout, 22 October 2026:** the public library is live. Automatic
deployment is pending the Cloudflare Pages GitHub app's access to the private
repository. Until that connection is enabled, publishing updates Git and an
administrator must deploy the built site separately. Check the repository
README for the current hosting status.

The command refuses an already staged Git index, a different branch, a
checkout behind the remote, changes to tracked non-document files, or local
commits that include unrelated code. It never force-pushes, auto-merges, or
commits your application code. For a review workflow, commit your document on
a feature branch and open a normal pull request instead.

## Update the same link

```bash
commons add ~/notes/decision.md --slug publishing-decision --replace
commons preview
commons publish --message "Update the publishing decision"
```

The slug and creation date stay stable. Attachments already in the bundle
are kept unless explicitly replaced. The imported file is a copy: edit your
original and re-import it, or edit the file under `documents/` directly.

## Images and attachments

Keep local assets next to the source file, or in a directory beside it:

```text
my-report/
  report.html
  images/chart.png
  styles/report.css
```

Direct image, script, and stylesheet references are imported automatically,
including CSS `url()` resources. File paths must stay inside the source
folder. Root-relative URLs refer to the hosted site, so use relative paths
for assets. Runtime-generated requests and module import graphs are not
automatically discovered; include their directories explicitly:

```bash
commons add ./report.html --assets ./assets --assets ./results.csv
```

Self-contained HTML reports work directly. HTML keeps its CSS and scripts and
is displayed in a sandboxed reader. The sandbox permits scripts, downloads,
and popups, but does not grant same-origin access to the library. HTML that
depends on same-origin fetch or module loading may need to be made
self-contained. The original file remains downloadable.

## Metadata in Markdown

Optional YAML front matter is read when importing:

```yaml
---
title: A useful decision
summary: The context and tradeoffs behind the decision.
owner: Platform
tags:
  - decisions
  - architecture
---
```

The generated `document.json` is the authoritative metadata after import.
Explicit CLI flags override front matter. Do not rename an established slug
to change its title.

## List and search from the terminal

```bash
commons list
commons search "source maps"
commons --library ~/commons add ./another-note.md
```

Search matches all query words across the title, summary, owner, tags, and
readable body. HTML scripts and styles are excluded; text inside inactive
report tabs is included. Search is basic word-prefix matching, not semantic
search. The browser fetches one static index and searches locally.

## Drafts and visibility

```bash
commons add ./draft.md --draft
commons preview --include-drafts
```

Drafts are omitted from the public build, catalog, and search index. The
repository is private, but every published document and its included
attachments can be read by anyone. Draft status is a publishing state rather
than an access-control system. Publish only material intended for that audience.

For the exact file layout and metadata rules, read the
[publishing protocol](../publishing-protocol/).
