Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The README is a 50,000-foot view — what markfluence does, which command to rea

**`docs/commands/` is generated, not written.** `tools/gendocs` renders every command's help to Markdown via cobra's doc generator (using `cmd.Root()`, exported for that one caller — a `main()` inside `cmd` would land in the binary, and a `_test.go` that writes into the repo is not a test). It is a second copy of the help text, and only safe because it cannot drift: `make docs-check` regenerates into a temp dir and diffs, inside `make check`. `DisableAutoGenTag` is set, or a timestamp would make every regeneration a diff and the guard noise. **Never hand-edit a file under `docs/commands/`.**

The rest of `docs/` is written: `markdown-file.md` (the page format — every frontmatter field and every body construct, the two halves that used to be split between the README and a separate file), `json-output.md` (per-command `--json` detail the schema cannot express as reasoning), `releasing.md` (**the maintainer's release runbook** — the tag format and why Go modules and goreleaser both demand it, which steps run on a laptop and which in Actions, and why the Homebrew cask PR is opened by hand; `CONTRIBUTING.md` only points at it, since its own audience is contributors and none of this applies to them), `root-model.md` (the documentation root *and* `markfluence.yaml`'s settings), `credentials.md` (where credentials come from and the setup a person does by hand; the credential errors link to it on GitHub, so renaming it breaks every released binary's pointer), `design-principles.md`, and `confluence/`. **There is no CI document here.** `github-actions.md` used to be one, from before the action existed; it was deleted once [mozilla/markfluence-action](https://github.com/mozilla/markfluence-action) shipped, because keeping it meant maintaining a parallel hand-rolled recipe — and that copy had silently rotted, carrying three bugs the action had already fixed. The README points at the action, and the action's README is the reference.
The rest of `docs/` is written: `tutorial.md` (the quick start — install, credentials, then create, list and export one page in a personal space; its sample output is what the commands print, with the identities swapped for examples, so a change to that output can leave it stale), `markdown-file.md` (the page format — every frontmatter field and every body construct, the two halves that used to be split between the README and a separate file), `json-output.md` (per-command `--json` detail the schema cannot express as reasoning), `releasing.md` (**the maintainer's release runbook** — the tag format and why Go modules and goreleaser both demand it, which steps run on a laptop and which in Actions, and why the Homebrew cask PR is opened by hand; `CONTRIBUTING.md` only points at it, since its own audience is contributors and none of this applies to them), `root-model.md` (the documentation root *and* `markfluence.yaml`'s settings), `credentials.md` (where credentials come from and the setup a person does by hand; the credential errors link to it on GitHub, so renaming it breaks every released binary's pointer), `design-principles.md`, and `confluence/`. **There is no CI document here.** `github-actions.md` used to be one, from before the action existed; it was deleted once [mozilla/markfluence-action](https://github.com/mozilla/markfluence-action) shipped, because keeping it meant maintaining a parallel hand-rolled recipe — and that copy had silently rotted, carrying three bugs the action had already fixed. The README points at the action, and the action's README is the reference.

A change that adds a package, exports a function, adds a make target, or introduces a generated artifact belongs in **this file** as part of the same change. The only time it has drifted was a docs-only branch that felt like it needed no architecture note while adding all four.

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ to use it. It also tells you where to find more documentation.
| | |
|---|---|
| [README.md](README.md), this file | installation, configuration, and use |
| [docs/tutorial.md](docs/tutorial.md) | a quick start: install, set up credentials, then create a page in your personal space and export it |
| [docs/commands/](docs/commands/) | the `--help` text of every command, as Markdown. It is the same text that `markfluence CMD --help` prints, and it comes from the binary |
| [docs/markdown-file.md](docs/markdown-file.md) | the page format: every frontmatter field, and what the converter does with each body construct |
| [docs/credentials.md](docs/credentials.md) | where markfluence reads credentials from, how to set up your credentials file, and what each credentials error means |
Expand Down
265 changes: 265 additions & 0 deletions docs/tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
# Tutorial

This tutorial takes you from no markfluence to a page that you published to
your personal space and exported back to a file.

We'll be using a Mac with [Homebrew](https://brew.sh/). For Linux, or to
build from source, see [Install](../README.md#install) in the README.

You'll need an [Atlassian API token][token] for your Confluence account on a Confluence Cloud site,
such as `your-org.atlassian.net`.

[token]: https://id.atlassian.com/manage-profile/security/api-tokens

The output in this tutorial is what markfluence prints. The ids, the names, and
the site are examples. Yours will be different.

## 1. Install markfluence

This repository is its own Homebrew tap, so `brew tap` needs the URL:

```sh
brew tap mozilla/markfluence https://github.com/mozilla/markfluence
brew trust mozilla/markfluence
brew install markfluence
```

Make sure that it works:

```sh
markfluence --version
```

## 2. Set up your credentials

markfluence needs your site URL, your username (the email address of your
Atlassian account), and your API token. `credentials-init` asks for each one,
does a check of them with Confluence, and writes them to
`~/.config/markfluence/credentials`:

```sh
markfluence credentials-init
```

When you're tying your API token, it'll be hidden.

Once you're done filling in information, markfluence will test your credentials
and let you know if it works. If Confluence refuses the credentials, then
markfluence will save nothing and you can run it again.

If you ever have to rotate your API token, you can run this command again
and markfluence will prompt you with your existing answers so you don't
have to type the ones that aren't changing again.

Now you can see your account information:

```console
$ markfluence user-info
account id: 5b10ac8d82e05b22cc7d4ef5 (these credentials)
name: Ada Lovelace
email: ada@example.com
type: atlassian (a person)
status: active
external: no
guest: no
personal space: ~5b10ac8d82e05b22cc7d4ef5 https://your-org.atlassian.net/wiki/spaces/~5b10ac8d82e05b22cc7d4ef5
visible spaces: 533
write access: 102 (too many to list; see --json output)
admin access: 2 -- ENG, ~5b10ac8d82e05b22cc7d4ef5
```

This command takes a few seconds, because it does a survey of every space that
you can see.

The line to note is `personal space`. Its key starts with `~`, and you use it in
the next steps. If there is no `personal space` line, your account has no
personal space. Create one in Confluence, or use the key of a space where you
have write access.

[docs/credentials.md](credentials.md) tells you more about credentials, and
what each credentials error means.

## 3. Look at your personal space

`space-info` shows what a space is and what you can do in it. Put the key in
quotes, because some shells expand a `~` at the start of a word:

```console
$ markfluence space-info '~5b10ac8d82e05b22cc7d4ef5'
key: ~5b10ac8d82e05b22cc7d4ef5
name: Ada Lovelace
id: 76646426
type: personal (current)
homepage: 76646878 Things
labels: favourite
your access: read, create pages, administer
page statuses: Rough draft, In progress, Ready for review, Verified
pages: 40 current, 1 archived
root pages: 1
last activity: 2026-09-28 (9 days ago)
pages created: 0 in the last 7 days
pages touched: 0 in the last 7 days
```

`your access` must include `create pages`, or the next step fails.

## 4. Write a Markdown file

Each Markdown file is one Confluence page. The frontmatter at the top of the
file tells markfluence the title of the page, the space to put it in, and other
settings, such as the width of the page.

Make a directory for the tutorial, and write `hello.md` in it:

```sh
mkdir markfluence-tutorial
cd markfluence-tutorial
```

```markdown
---
title: Hello from markfluence
space: ~5b10ac8d82e05b22cc7d4ef5
page_width: medium
---

This page started as a Markdown file.

## A list

- one
- two

> [!NOTE]
> This is a callout. In Confluence it is an info panel.
```

Use your own personal space key in the `space:` line.

`markfluence check` finds problems in a file before you publish it. It makes no
network request and needs no credentials. Let's run it on our file:

```console
$ markfluence check hello.md
✗ [hello.md] invalid page_width "medium"; expected narrow, wide, or max
root: /Users/ada/markfluence-tutorial
✗ 1 of 1 file(s) failed.
```

Oops! There's an error with the file.

`check` exits with `1`, and the message tells you the values that are correct.
Change the `page_width:` line in `hello.md` to:

```yaml
page_width: wide
```

Then run `check` again:

```console
$ markfluence check hello.md
[hello.md] clean
root: /Users/ada/markfluence-tutorial
```

`check` also finds broken links, images that do not exist, and frontmatter that
does not parse. A message about the body gives the line number in the file.

[docs/markdown-file.md](markdown-file.md) tells you about every frontmatter
field and every Markdown construct.

## 5. Create the page

`markfluence create` creates the page in Confluence. To see what `create` will
do, and change nothing, use `--dry-run`:

```console
$ markfluence create --dry-run hello.md
! DRY RUN — no changes will be written.
root: /Users/ada/markfluence-tutorial
[hello.md] page width: wide
✓ [hello.md] Would create page 'Hello from markfluence' in ~5b10ac8d82e05b22cc7d4ef5
```

That looks good, so let's create the page:

```console
$ markfluence create hello.md
root: /Users/ada/markfluence-tutorial
[hello.md] page width: wide
✓ [hello.md] Created page 1234567890: https://your-org.atlassian.net/wiki/spaces/~5b10ac8d82e05b22cc7d4ef5/pages/1234567890
```

Open the URL to see the page in Confluence.

`create` also updates the information in the frontmatter of `hello.md`:

```markdown
---
title: Hello from markfluence
space: ~5b10ac8d82e05b22cc7d4ef5
parent: null
page_id: 1234567890
page_width: wide
---
```

The `page_id` connects the file to the page allowing you to update it as you
make changes. `parent: null` means that the page is at the top level of the
space. To publish changes made to the file, use `update`.

```sh
markfluence update hello.md
```

## 6. Show the pages in your personal space

`markfluence children --space` lists the pages and folders in a space. The new
page is at the top level, next to the homepage:

```console
$ markfluence children --space '~5b10ac8d82e05b22cc7d4ef5'
TYPE ID TITLE
page 76646878 Things
page 1234567890 Hello from markfluence

Showing the space's top level. Use --depth 2, or --depth all for the whole tree.
```

To see the whole tree, add `--depth all`.

## 7. Export the page

`markfluence export` exports a Confluence page to a Markdown file on your file
system, with its frontmatter and the attachments that it uses. You can give the
page as an id, as a URL, or as a Markdown file that has a `page_id`:

```console
$ markfluence export hello.md --dest exported
✓ wrote /Users/ada/markfluence-tutorial/exported/hello-from-markfluence.md
```

The exported file has the same frontmatter as `hello.md`, and the body is the
page converted back to Markdown. It is semantically the same as `hello.md`, but
it is not always byte-for-byte the same.

To compare your file with the page in Confluence, use `diff`. It exits with
`0` when they are the same:

```sh
markfluence diff hello.md
```

## Next steps

- `markfluence COMMAND --help` is the reference for each command. The same
text is in [docs/commands/](commands/).
- The [Common workflows](../README.md#common-workflows) section of the README
shows how to edit a page that exists and how to export a tree of pages.
- [docs/root-model.md](root-model.md) tells you how to keep many files in one
project with a `markfluence.yaml`.
- To publish from a GitHub repository, use
[markfluence-action](https://github.com/mozilla/markfluence-action).
- To remove the tutorial page, delete it in Confluence. markfluence does not
delete pages.
Loading