On <2026-04-28 Tue> I tried to add footnotes to notes in Textpod. It
works, {C-c C-x f} adds a footnote link. Then publishing works
normally, just make sure footnotes heading is level down of the
published note (usually h2).
But, footnotes looks ugly, and rendered at the bottom. I want
sidenotes, as in Tufte CSS. I remember org-tufte exporter, so decided
to try. Apparently, there's newer version exists -
Zilong-Li/org-tufte. Let's try it.
(use-package org-tufte :ensure nil)
Export to plain HTML looks fine, side-notes as footnotes work
fine
this is side note, but in Org file it's actually a footnote!
. But when exporting into Textpod – body only, + custom
HTML and JS injected – it breaks.
On <2026-04-27 Mon> I'm once again fascinated how bad Markdown is
and how broken the export is. So for Textpod I decided to skip Markdown,
and export notes directly from Org to HTML.
Problem
Markdown can't handle lists properly.
This Org Mode block:
- github :: [[https://github.com/inanimate-tech/mist][inanimate-tech/mist]]
- posts ::
- [[https://interconnected.org/home/2026/02/12/mist][mist: Share and edit Markdown together, quickly (Interconnected)]]
- [[https://interconnected.org/home/2026/04/10/open-mist][mist is now open source and looking for interop (Interconnected)]]
: curl https://mist.inanimate.tech/new -T file.md
is exported as this Markdown block:
- **github:** [inanimate-tech/mist](https://github.com/inanimate-tech/mist)
- **posts:** - [mist: Share and edit Markdown together, quickly (Interconnected)](https://interconnected.org/home/2026/02/12/mist)
- [mist is now open source and looking for interop (Interconnected)](https://interconnected.org/home/2026/04/10/open-mist)
curl https://mist.inanimate.tech/new -T file.md
Another round of improvements of textpod.el, a companion Emacs
package to Textpod.
Custom ID format - attribute name and prefix
Added two defcustom options in textpod.el:
textpod-id-property (default "TEXTPOD_ID") - name of the Org
property used to store the note id.
textpod-id-prefix (default "") - prefix prepended to ids when
stored, stripped before sending requests to the server.
Introduced textpod--strip-prefix helper and updated all id call
sites (textpod-open-current-note, textpod-org-heading-to-note,
textpod-org-region-to-note) to respect these configs.
textpod-set-id sets ID without creating a node
I need a function to create texpod id property without sending note to
the server. This is needed to submit old notes so they have proper
timestamp.
Added textpod-set-id: an interactive command that sets
textpod-id-property on the current heading (with textpod-id-prefix)
derived from a time as YYYYMMDDhhmmss, without making any HTTP
request.
No prefix arg → uses (current-time).
With prefix arg → prompts via org-read-date, so the note can be
back-dated before later uploading with textpod-org-heading-to-note.
Quickly getting to Textpod notes
Using Ack is possible, placing point on a file-name and pressing {H-RET} will
call visit-source and go directly to the line.
On <2026-04-21 Tue> I rewritten Textpod from Rust to Go.
While I'm on vacation with the new MacBook Pro M4 Pro and I have
installed only bare minimum on it, I don't have Rust toolchain but do
have Go. So, asked Claude to do rewrite. The only external
dependency is goldmark package to render Markdown as HTMLs.
textpod-org-region-to-note: Convert the Org region between BEG and END to Markdown and send to Textpod.
textpod-org-heading-to-note: Send the current heading’s subtree to Textpod.
textpod-open-current-note: Open the current heading’s Textpod note in a browser.
When creating a note, textpod.el sets TEXTPOD_ID property that's equal
to node'id.
Change separator in notes.md to ^L
Default separator \n\n---\n\n is fragile as it requires exactly two
newlines before / after the note. I often messed up notes when
editing notes.md file manually. To fix that, I replaced it with ^L
character (insert in Emacs via C-q C-l) which usually represents new
pages.
Fix attachments links
Attachement links need to respect --base-path flag.
Handling attachments
My current workflow:
Assets are stored next to Notes under assets/ directory
I can quickly search for them, then open in Emacs/qView:
An image is a link to an image file that does not have a description part (Images (The Org Manual)).
Textpod already support images. What happens when I drag-n-drop an
image file to the textarea? Textpod copies them under attachments
directory.
What I want:
When creating a public note containing an image via API (using
textpod.el), copy the asset to assets/ directory, mimicing the directory
structure in the notes.
I need another API endpoint - POST /notes/assets/<name>, accepting
binary as payload.
Okay, I implemented it, let's test.
textpod-org-heading-to-note
Prompt: Implement textpod-org-heading-to-note function, it should select
current (top) heading - the one that has TEXTPOD_ID parameter, and
call textpod-org-region-to-note on it.
The command {M-x textpod-org-heading-to-note} works!
Should the textpod id be just id?
Currently I use TEXTPOD_ID property. If using ID property, notes will
automatically become Org-roam nodes. Currently IDs are generated as
timestamps via (setq org-id-method 'ts) with nanoseconds precision.
Then it will come with seconds precision. I will need to a prefix, to
be able to quickly find them (e.g. with {M-x deadgrep}).
Wrap h3 into details on index page
To declutter the index page, h3 markdown headings (h2 Org headings)
are wrapped into <details> tag. The note page renders normally,
showing table of contents on the left sidebar.
☑ Internal Org Roam links are pasted as markdown files. So in theory,
I could somehow expose them.
I ended up forking it to https://github.com/velppa/textpod and greatly
improving it for my needs. You're reading notes served by Textpod
v0.2.0. It is my project.
Notable changes:
Read-only mode with token authentication: The app now supports an
optional --token flag that enables authentication. When a token is
set, users without the token see a read-only interface where they
can only search notes. Access is granted via a ?token=X query
parameter (which sets a cookie) or a Bearer token in the
Authorization header. The UI dynamically adjusts based on
authentication status, hiding edit/delete controls and changing the
editor placeholder for unauthenticated users.
Enhanced note management: Notes now have unique IDs based on
timestamps, enabling direct access via /note/:id URLs. PUT method
allows editing notes (upserting if not found).
Subpath support: to deploy on your domain under subpath, supply
--base-path notes flag. Then notes will be under /notes subpath.
The app watches the notes file for external changes and
automatically reloads.
The link archiving feature lets users prefix URLs with + to both raw
urls and Markdown-formatted.
Special handling of links to .md files: They appear when exporting
from Org-roam. These are internal links and Textpod now turns them
into search by filename, effectively returning all mentions of this
concept. Poor man zettelkasten import.
UI improvement: larger fonts, footer, better code snippets for
dark mode, tags on the heading.
textpod.el: Companion Emacs package for quick sending notes to
Textpod.
Later changes to setup will go into separate notes.