Publishing
Share a page as a read-only copy at a public URL. Visitors need no account.
Publishing a page
Open a page and use the globe button in its header. Publishing takes a snapshot of the page as it is now. Later edits stay private until you republish; the button shows a dot while there are unpublished changes.
Only pages can be published. Folders, sections, archived pages and conflict copies cannot.
The published copy has the page's title, body and table of contents, in the workspace's theme and custom CSS at the time of publishing. You choose whether it also shows:
- the author, the member who first published the page
- when the page was last edited and when it was published
- the table of contents
- word, character and backlink counts
- a "Written with Aquamarine" badge
- the page's properties (frontmatter), which are hidden by default
Republishing replaces the snapshot and keeps the URL, the toggles, the password and the expiry.
What stays private
- A link to another page works only if that page is published too. Otherwise it shows as plain text, and an alias hides the target's title.
- Links are checked each time the page is viewed, so a link lights up when its target is published and goes grey when it is taken down, without a republish.
- Embedded pages show a link if published, otherwise "Embedded page not shared". Local image embeds show "Image not available"; images from
httpsURLs are kept. - Tags are plain text. Obsidian
%%comments%%and HTML comments are removed when publishing. - Backlink counts include only published pages.
Before publishing, a check lists links and embeds that will not work for visitors. Publishing with any of them needs a confirmation.
Password and expiry
A password puts a form in front of the page. A correct password unlocks it in that browser for 30 days. Changing the password signs every visitor out. After 10 tries in 5 minutes from one address, the form refuses more for a few minutes.
An expiry date takes the page offline at that time. Visitors then see "This page is no longer shared." Pages with a password or an expiry are not indexed by search engines.
Taking a page down
Unpublishing, moving a published page to the trash or deleting the workspace takes the public copy down. Each asks for confirmation first and lists the published pages that link to it. Visitors then get a 410 page. Restoring a page from the trash brings its publication back.
Slugs
Published pages live at https://is.underwhelm.ing/p/<slug>. The default slug is the title plus six random characters, such as weekly-review-k3f9q2.
- A custom slug uses
a-z,0-9and-, 3 to 80 characters, unique per domain. - The default domain reserves
p,docs,api,mcp,session,profile,accounts,integrations,up,clientandassets. - Changing a slug redirects the old one to the new one with a
301while the page stays published. - A slug that was taken down is held for 30 days before anyone can claim it again.
Custom domains
Add a domain under Settings → Workspace → Custom domains. Settings shows two DNS records to create at your DNS provider:
| Type | Name | Value |
|---|---|---|
CNAME | notes.example.com | is.underwhelm.ing |
TXT | _aquamarine.notes.example.com | The token Settings shows |
For a domain without subdomain, use an A record pointing at the server's address instead of the CNAME. The domain is checked when it is added, then every 10 minutes for a day, then hourly for a week. Settings shows "Waiting for DNS", "Verified" or "Failed" with what was found, and "Check now" checks again at once. Only one workspace can verify a domain.
Once verified, pick the domain in a page's Publish panel. The page moves to https://<domain>/<slug> and its old address redirects there with a 301. The domain's root lists its published pages that have no password.
Removing a domain asks first and names the pages on it. They move back to /p/<slug>; links shared with the domain address stop working.
On a verified domain, /<slug> serves that domain's pages and / lists them. Removing a domain moves its pages back to the default domain under the same slugs, or a suffixed slug when one is taken.
TLS for custom domains
Self-hosted servers need a reverse proxy that gets certificates for custom domains on demand. The server answers GET /domains/tls_allowed?domain=<host> with 200 for verified domains and an error for anything else, which is the check Caddy's on-demand TLS expects:
{
on_demand_tls {
ask http://localhost:3000/domains/tls_allowed
}
}
https:// {
tls {
on_demand
}
reverse_proxy localhost:3000
}
API
Publishing needs the publish:notes scope. See publication endpoints in the REST API and the notes_publish, notes_unpublish and notes_publication_get MCP tools.