Archival Editor Configuration
The optional archival_editor.toml file lets you customize how your site's content appears in the Archival editor.
This file is most useful when creating an archival template or for customizing the editing experience in the archival editor.
Place archival_editor.toml in the root of your repo, alongside archival_objects.toml and archival.toml. The editor reads it automatically when your site loads, and re-reads it whenever the file changes.
It is also where you turn on ActivityPub, which publishes your content to Mastodon and the rest of the fediverse whenever your site deploys.
Object views
The file configures views for your object types. A view controls which fields are shown as columns when you browse the list of objects of a given type in the editor.
The top-level key of each entry is the name of an object type, exactly as it appears in archival_objects.toml. Under each object type you define one or more views as a TOML array of tables:
# Configure views for the "post" object type
[[post.views]]
name = "default"
primary = "title"
secondary = "published_at"
tertiary = "author"
[[post.views]]
name = "by date"
primary = "published_at"
secondary = "title"
Each view supports the following fields:
name(required) — the label for this view. It appears in the view selector dropdown above the object list.primary(required) — the field shown in the first column of the list.secondary(optional) — the field shown in the second column.tertiary(optional) — the field shown in the third column.
The values of primary, secondary, and tertiary are field names defined for that object type in archival_objects.toml. You can also use the special value filename, which displays the object's filename (its slug) rather than one of its fields.
How views are displayed
- The first view listed for an object type is selected by default when you open that object's list.
- The editor always appends a built-in
slugview that shows only thefilenamecolumn, so you can switch back to it at any time from the view selector. - If an object type has no entry in
archival_editor.toml, its list shows a singlefilenamecolumn. - Around the columns you configure, every row also includes the object's
order(always first) and anactionscolumn (always last).
Example
Given an object type defined in archival_objects.toml:
[post]
title = "string"
author = "string"
published_at = "date"
body = "markdown"
This archival_editor.toml gives editors two ways to browse posts — one organized around the title, and one organized around the publish date:
[[post.views]]
name = "default"
primary = "title"
secondary = "author"
tertiary = "published_at"
[[post.views]]
name = "by date"
primary = "published_at"
secondary = "title"
See Object Fields for the field types you can reference, Validators for constraining what they may contain, and Custom Editors for customizing how individual fields are edited.
Shortcuts
A shortcut puts one list a single tap away from anywhere in the editor. Name the lists that get added to often — posts, updates, photos — and every editor screen grows a button in its bottom right corner that opens a composer for a new entry, with a publish button that writes and deploys it in one step.
Shortcuts are an array of tables at the top level of the file, alongside your object types:
[[shortcuts]]
name = "New Post"
path = "post"
[[shortcuts]]
name = "Site Update"
path = "homepage.updates"
Each entry takes:
path(required) — the list a new entry joins. See addressing a list, below.name(optional) — the label on the button and in the shortcut menu. Left out, the last segment ofpathis used with dashes and underscores turned into spaces and each word capitalized, sopostreads "Post" andpress_releasesreads "Press Releases".
shortcuts is reserved at the top level of this file, so an object type named shortcuts cannot be configured here.
Addressing a list
path addresses a list the way the editor addresses one everywhere else: the object type, then the filename when that type holds many objects, then the child lists to descend into, with the index of the entry you descend through between them. Segments are separated by dots, and an index counts from zero.
[[shortcuts]]
path = "post" # a new post
[[shortcuts]]
path = "homepage.updates" # a new update on the homepage
[[shortcuts]]
path = "post.hello-world.sections" # a new section on the "hello-world" post
[[shortcuts]]
path = "post.hello-world.sections.0.links" # a new link on that post's first section
An object your site has exactly one of stores its content in a file named after the type, so there is no filename to give: homepage.updates, not homepage.homepage.updates. Pointing a shortcut at such an object on its own is refused, since it already holds the one file it will ever have.
Every step is checked against what your site actually contains. A type you have since removed, an index past the end of a list, or a path that stops at a single entry rather than a list resolves to nothing, and that shortcut simply does not appear. Correcting the path brings it back, along with any drafts saved under it.
Drafts
The composer saves what you write as you write it. A draft is kept on your device until you publish or discard it, so closing the editor and coming back tomorrow reopens it exactly as you left it.
Drafts are never written into your site's files. An unpublished draft is not a pending change, it does not show up in your unsynced changes, and publishing your site any other way leaves it alone.
The shortcut button carries a badge counting the drafts you have saved. Pressing it opens a menu of every shortcut you configured and every draft you have going, so you can start something new or pick up where you left off. With a single shortcut configured and nothing saved, pressing the button skips the menu and starts a draft immediately.
Inside the composer:
- Save closes the composer and keeps the draft.
- Cancel throws it away, asking first if anything has been filled in.
- Publish adds the entry to your site and deploys it. It stays disabled until at least one field has something in it.
With more than one draft saved, the composer pages between them: swipe left or right on a touch screen, or use the arrows and dots below the fields.
What publishing writes
The commit message is written for you, as Add <shortcut name>: <title>. The title is the first field the draft has text in — the primary field of the list's first view when one is configured, and otherwise the first string or markdown field the type declares.
A new object is filed under that same text, lowercased and hyphenated, with a number appended if the name is already taken. A draft with no text anywhere is filed under the name of its type.
Publishing a draft publishes your site, so anything else you had left unsynced is deployed along with it.
Changing a schema under an open draft
A draft can outlive the shape it was started in. Every time one is opened it is reconciled against the current object definition: a field the type no longer declares is dropped, a field whose type has changed to one the saved value cannot fit is dropped with it, and a child list you have added since appears empty. Everything still valid is preserved, so editing your schema never costs you a draft outright.
ActivityPub
An activitypub section turns your site into an account people can follow from Mastodon, Threads, Ghost, and anything else that speaks ActivityPub. Every object you map becomes a post on that account, and each time your site deploys, the people following it see what you added, changed, or removed.
[activitypub]
username = "blog"
[activitypub.actor]
object = "site"
name = "title"
summary = "bio"
icon = "logo"
[activitypub.objects.post]
name = "title"
content = "body"
published = "published_at"
image = "cover"
With this file, a site at example.com is followed as @blog@example.com.
Every value in the section other than username and type names a field of your object, exactly as it appears in archival_objects.toml. Nothing you write here is itself published: what goes out is whatever your content says.
activitypub is reserved at the top level of this file, so an object type named activitypub cannot be configured here.
The account
username(optional) — the part of the handle before your domain. It may hold letters, numbers, underscores, dots and dashes. Left out, the first part of your site's domain is used, with anything else turned into underscores, somy-site.comis followed as@my_site@my-site.com.
The handle is always on your site's primary domain. Changing that domain later leaves existing followers following an account that no longer answers, so settle on a domain before you start federating.
[activitypub.actor] is optional, and sets the profile other servers show for the account. object is required, and names an object your site has exactly one of — a site settings or about object is the usual choice. The rest name its fields:
name— the display name. Astring,markdownorenumfield. Left out, thesite_nameinarchival.tomlis used, and failing that the domain.summary— the bio. Astring,markdownorenumfield.icon— the avatar. Animagefield.image— the header image. Animagefield.
Posts
Each table under activitypub.objects is keyed by an object type your site has many of, and every object of that type is published:
type(optional) —"Article"(the default) or"Note". An article is a piece of writing with a title. A note is a short post like a status update, and is shown in full wherever it is read.name— the title. Astring,markdownorenumfield.content— the body. Astring,markdownorenumfield. Markdown is rendered to HTML.summary— astring,markdownorenumfield. Mastodon shows a summary as a content warning, hiding the post behind it until it is opened, so only map one you mean that way.published— when the post was published. Adatefield. Left out, or left empty on an object, the post is dated when it was first federated.updated— when the post last changed. Adatefield. Left out, an edited post is dated by the deploy that changed it.image— animagefield, attached to the post. The image's description is used as its alt text.
Each type must map at least one of content or name. Fields you do not map are never published, and a secret field cannot be mapped at all.
When an object type has a page template, each post links to its page, and pasting that page's address into Mastodon's search finds the post.
When things are published
Publishing happens when your site deploys, however the change reached it — from the editor, a shortcut, or a git push. Nothing is sent while you are still editing.
- Added objects are posted, changed objects are updated, and removed objects are deleted from the servers that received them.
- The first deploy with
activitypubconfigured sends nothing to anyone. Your existing content is published to the account so it can be browsed and found, but it will not arrive in anyone's timeline as though it were new. - A single deploy delivers at most 10 new posts and 20 updates, the most recent first, so importing a backlog does not flood your followers. Everything else is still published and can be found on the account. Deletions are always delivered.
If the section names a field your object does not have, or one whose type cannot fill it, that deploy publishes nothing to the fediverse until the mapping is corrected. Your site itself still deploys as usual.
Turning it off
Removing the activitypub section and deploying stops the account from answering. Its followers and posts are kept, and adding the section back resumes it where it left off. The same happens while a site's subscription is cancelled: the account stops answering, and the next deploy after it is reactivated brings it back.
While a site federates, Archival answers /.well-known/webfinger and requests for ActivityPub documents on its behalf, and reserves the paths under /_archival/ap/.
Replies, likes, and boosts your posts receive are not yet shown on your site.