<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://blog.davep.org</id>
  <title>davep</title>
  <updated>2026-09-09T08:06:55.026868+00:00</updated>
  <link href="https://blog.davep.org/feeds/coding.atom.xml" rel="self"/>
  <link href="https://blog.davep.org" rel="alternate"/>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
  <subtitle>Posts in category "Coding" from davep</subtitle>
  <entry>
    <id>https://blog.davep.org/2026/09/09/rogallo-v2-4-0.html</id>
    <title>Rogallo v2.4.0</title>
    <updated>2026-09-09T08:37:57+01:00</updated>
    <content type="html">&lt;p&gt;I've released &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v240" rel="noopener noreferrer" target="_blank"&gt;v2.4.0&lt;/a&gt;, which contains two new
features.&lt;/p&gt;
&lt;p&gt;The first is the addition of a feature related to the &lt;a href="https://blog.davep.org/tag/gemini-protocol/"&gt;Gemini
Protocol&lt;/a&gt;, and it's something I've been meaning to
add for a wee while: a trusted host browser/manager. It's a simple enough
idea: you might want to have a look at all the host/port pairs that exist in
your trusted hosts list and, perhaps, revoke the trust for one or more.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The trusted host browser" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/09/09/trusted-host-browser.webp#centre" width="1020" /&gt;&lt;/p&gt;
&lt;p&gt;From the dialog you can either visit the host/port combination (perhaps you
got curious about what you've trusted in the past and want to see what was
there), or you can forget the trust. This also somewhat follows on from work
done in &lt;a href="https://blog.davep.org/2026/08/31/rogallo-v2-1-0.html"&gt;Rogallo v2.1.0&lt;/a&gt;, except rather
than having to make the decision when you visit a capsule, you can review
all the capsules you currently trust.&lt;/p&gt;
&lt;p&gt;If this seems useful, it's called up with the new &lt;code&gt;BrowseTrustedHosts&lt;/code&gt;
command, bound to &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;t&lt;/kbd&gt; by default.&lt;/p&gt;
&lt;p&gt;The second new feature is something that's been on my TODO list for quite a
while, and has mainly been sat there because I wanted the viewer widget in
the application to settle down a bit before I tackled this. I'm talking here
about in-viewer search. It's a simple enough requirement, but one that's not
&lt;em&gt;that&lt;/em&gt; straightforward when you're dealing with views of different kinds of
text files, views of the source of such documents, and also having to handle
things like embedded ANSI escape sequences.&lt;/p&gt;
&lt;p&gt;The work is now done, so if the viewer itself is focused, you can press
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;f&lt;/kbd&gt;, enter some text to search for, and then press
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;n&lt;/kbd&gt; to keep moving through all the hits. Once you
hit the last match, you'll be told there are no more matches, but then the
search will start again from the top.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Performing a text search" loading="lazy" src="https://blog.davep.org/attachments/2026/09/09/text-search.gif#centre" /&gt;&lt;/p&gt;
&lt;p&gt;You can also cancel an ongoing search with
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;f&lt;/kbd&gt;.&lt;/p&gt;
&lt;p&gt;I'm glad to finally get this added to Rogallo as it's a feature I've been
finding myself needing on a good few occasions.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/09/09/rogallo-v2-4-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-09-09T08:37:57+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/09/06/rogallo-v2-3-0.html</id>
    <title>Rogallo v2.3.0</title>
    <updated>2026-09-06T10:41:12+01:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v230" rel="noopener noreferrer" target="_blank"&gt;v2.3.0&lt;/a&gt; is now available. The
main addition to this release is support for the &lt;a href="https://rogallo.davep.dev/titan/" rel="noopener noreferrer" target="_blank"&gt;Titan
Protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First up, there's a small fix. The other day I discovered
&lt;a href="gemini://ultimatumlabs.com/scripto.gmi" rel="noopener noreferrer" target="_blank"&gt;Scriptonite&lt;/a&gt;. While looking at the
examples I noticed none of them worked with Rogallo. This struck me as odd
because the whole point of Scriptonite is that it all happens on the
server-side; nothing on the client-side should affect how well it works.&lt;/p&gt;
&lt;p&gt;It turns out that &lt;a href="https://wasat.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Wasat&lt;/a&gt; had a bug when it came
to slicing and dicing Gemini URIs, where parts of a URI that followed a &lt;code&gt;;&lt;/code&gt;
were being lost. Somewhat amusingly, I didn't even need to do any work on a
fix because it had already been taken care of in the branch that existed to
support Titan.&lt;/p&gt;
&lt;p&gt;The point here being: as of v2.3.0, Rogallo now works fine with the
Scriptonite examples.&lt;/p&gt;
&lt;p&gt;As I mentioned, the &lt;em&gt;main&lt;/em&gt; change in this release is support for the Titan
protocol. It's been on the TODO list for a wee while, partly because I was
struggling to follow the idea of it, and also partly because I'd not played
with it and just didn't see the purpose. The other day I sat down and
properly dived in and it finally all clicked.&lt;/p&gt;
&lt;p&gt;With v2.3.0, if you now visit a &lt;code&gt;titan://&lt;/code&gt; URI, you will be presented with a
rich input dialog. It is a tabbed view, with one tab being for text
input/upload:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Titan text entry" height="1856" loading="lazy" src="https://blog.davep.org/attachments/2026/09/06/titan-text.webp#centre" width="1942" /&gt;&lt;/p&gt;
&lt;p&gt;and the other being a file attachment and upload:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Titan file upload" height="1856" loading="lazy" src="https://blog.davep.org/attachments/2026/09/06/titan-file.webp#centre" width="1942" /&gt;&lt;/p&gt;
&lt;p&gt;As per the Titan specification, there is support for setting the MIME type
for the attached data. If using the text view, this will always be set to
&lt;code&gt;text/plain&lt;/code&gt;. If using a file attach/upload, you have full control over it,
but it will default to the best guess based on the file selected.&lt;/p&gt;
&lt;p&gt;There is also support for entering an upload token.&lt;/p&gt;
&lt;p&gt;As well as supporting the core Titan specification, I've also added support
for &lt;a href="gemini://transjovian.org/titan/Edit%20Link" rel="noopener noreferrer" target="_blank"&gt;the proposed &lt;code&gt;;edit&lt;/code&gt;
extension&lt;/a&gt;. This means that it
is safe to enable Titan-based editing on
&lt;a href="gemini://bbs.geminispace.org/" rel="noopener noreferrer" target="_blank"&gt;bbs.geminispace.org&lt;/a&gt;, making it easier to
modify text you've already written.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Editing a post with Titan" height="2048" loading="lazy" src="https://blog.davep.org/attachments/2026/09/06/titan-edit.webp#centre" width="2598" /&gt;&lt;/p&gt;
&lt;p&gt;One final change in this release of Rogallo also relates to user input. I've
given the Gemini-based input dialog an overhaul. Originally this was, by
design, as simple and as bare-bones as possible. It was simply a free-text
input box that would grow as you added lines, and the prompt from the server
was shown as a title in the border of that box. While testing out editing on
BBS, I realised that this doesn't always work so well; most of the time the
prompt would get truncated.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The input prompt being truncated" height="232" loading="lazy" src="https://blog.davep.org/attachments/2026/09/06/old-input.webp#centre" width="1592" /&gt;&lt;/p&gt;
&lt;p&gt;Not a great user experience. The redesigned input box works more or less the
same, but now ensures that the prompt is fully visible.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The new version of the input box" height="358" loading="lazy" src="https://blog.davep.org/attachments/2026/09/06/new-input.webp#centre" width="1048" /&gt;&lt;/p&gt;
&lt;p&gt;Between this change and the new Titan edit/upload dialog, I feel Rogallo is
now in a good position to act as a near-zero-compromise daily driver when
it comes to wandering around the small web.&lt;/p&gt;
&lt;p&gt;I guess adding tabs will get it closer to zero. Perhaps in-terminal image
viewing. Okay, perhaps a sprinkle of http(s) support too? Also...&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/09/06/rogallo-v2-3-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="Titan Protocol"/>
    <category term="smolweb"/>
    <published>2026-09-06T10:41:12+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/09/03/rogallo-v2-2-0.html</id>
    <title>Rogallo v2.2.0</title>
    <updated>2026-09-03T08:14:57+01:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v220" rel="noopener noreferrer" target="_blank"&gt;v2.2.0&lt;/a&gt; is available. This
release contains a handful of small new features and also a very minor
cosmetic change.&lt;/p&gt;
&lt;p&gt;First to the small cosmetic change: the overall design behind the UI of
Rogallo is that it's split into a couple of key panels -- the side-panel and
the main viewer. The styling of a panel when focus is within it, and when it
is outwith it, is different; the idea being that your eye should be drawn to
the active panel. This is an approach I take with all my
&lt;a href="https://blog.davep.org/tag/textual/"&gt;Textual&lt;/a&gt; applications.&lt;/p&gt;
&lt;p&gt;Part of this styling is to have a thin border to the left of the active
panel, which also helps signify that the panel is the one you should be
paying attention to. In applications where there's always two or more panels
on the screen all the time, this makes sense -- you want the line between
the panels anyway to help break up the content. In Rogallo, however, it's
going to be normal to only ever have the one panel in view (the viewer).&lt;/p&gt;
&lt;p&gt;The other day I realised that, when it's just the viewer available, I should
remove that left-hand border. So that's how Rogallo works now. If the viewer
is the only panel visible: no border. If the side-panel is also visible:
borders. I think it makes the display look a little cleaner; for what it's
worth it also saves one column of the display for something more useful.&lt;/p&gt;
&lt;p&gt;I've also added a couple of useful features to the active link in the
viewer. Now, when a link is selected, you can press &lt;kbd&gt;c&lt;/kbd&gt; to copy the
URI of that link to the clipboard. You can also press &lt;kbd&gt;o&lt;/kbd&gt; to open
the URI by passing it to the operating system. Both these changes should
make it easier to take a link out of a document and go and do something else
with it.&lt;/p&gt;
&lt;p&gt;The last couple of changes are around visiting &lt;code&gt;finger://&lt;/code&gt; URIs. The first
is a quick and simple change: any finger content now makes use of Rogallo's
document cache, so if you find yourself navigating back and forth between
finger responses, there should be fewer requests made in a short period of
time.&lt;/p&gt;
&lt;p&gt;I added caching partly in anticipation of another change to finger
responses: making them interactive where possible. Having created
&lt;a href="https://blog.davep.org/2026/09/02/finger2gemtext-a-library-for-converting-finger-responses-to-gemtext.html"&gt;&lt;code&gt;finger2gemtext&lt;/code&gt;&lt;/a&gt;,
I've updated Rogallo so that, where possible, the response is turned into
&lt;a href="https://blog.davep.org/tag/gemtext/"&gt;Gemtext&lt;/a&gt; and anything that can be turned into a link is now
interactive. This means that some finger services should be easier to
navigate, no longer requiring that you copy/edit/paste text to get a fresh
&lt;code&gt;finger://&lt;/code&gt; URI to follow.&lt;/p&gt;
&lt;p&gt;This can be seen if you visit somewhere like
&lt;a href="finger://plan.cat" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;finger://plan.cat&lt;/code&gt;&lt;/a&gt; or
&lt;a href="finger://redterminal.org/" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;finger://redterminal.org/&lt;/code&gt;&lt;/a&gt;. Whereas before you
would just be shown some plain text:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A plain text finger response" height="820" loading="lazy" src="https://blog.davep.org/attachments/2026/09/03/finger-plain.webp#centre" width="780" /&gt;&lt;/p&gt;
&lt;p&gt;Now you get a version that lets you follow the implied links in the
response:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A richer finger response" height="820" loading="lazy" src="https://blog.davep.org/attachments/2026/09/03/finger-rich.webp#centre" width="780" /&gt;&lt;/p&gt;
&lt;p&gt;This is, of course, going to be reasonably brittle. If any of the services
change their output format such that the "links" can't be detected any more,
the output won't be turned into Gemtext. Likewise, it's not impossible that
false positives might turn up. I'm going to run with this for a while and
see how it works out. I also have a vague plan for how the detection and
smarter rendering of finger responses could be made configurable by the
user.&lt;/p&gt;
&lt;p&gt;Anyway, that's it for this release of Rogallo. Now I can return to the main
change I was making a start on this week:
&lt;a href="gemini://transjovian.org/titan/index" rel="noopener noreferrer" target="_blank"&gt;Titan&lt;/a&gt;
&lt;a href="https://github.com/davep/rogallo/issues/355" rel="noopener noreferrer" target="_blank"&gt;support&lt;/a&gt;. I've not so much
been putting it off as I have been allowing myself to get distracted by the
above changes -- mostly because I don't quite &lt;em&gt;get&lt;/em&gt; Titan support yet and I
don't have a good location to play around with it. Time to solve that
problem...&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/09/03/rogallo-v2-2-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-09-03T08:14:57+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/31/rogallo-v2-1-0.html</id>
    <title>Rogallo v2.1.0</title>
    <updated>2026-08-31T08:18:32+01:00</updated>
    <content type="html">&lt;p&gt;I've just made a small release to &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;,
bumping the version to &lt;a href="https://rogallo.davep.dev/changelog/#v210" rel="noopener noreferrer" target="_blank"&gt;v2.1.0&lt;/a&gt;.
This release mostly has some small cosmetic fixes and improvements, and one
new feature.&lt;/p&gt;
&lt;p&gt;The cosmetic improvements include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed the verification method and client certificate status icons in the
  viewer title bar so they don't use the &lt;em&gt;"this is clickable"&lt;/em&gt; mouse cursor
  when there's nothing worth clicking.&lt;sup id="fnref:429-1"&gt;&lt;a class="footnote-ref" href="#fn:429-1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Adjusted the styling of tooltips so they better stand out against the
  background text.&lt;/li&gt;
&lt;li&gt;Fixed the cosmetics of the viewer when the content is set to a narrowed
  state (some of the changes in &lt;a href="https://blog.davep.org/2026/08/29/rogallo-v2-0-0.html"&gt;v2.0.0&lt;/a&gt;
  had inadvertently changed some of the styling).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The new feature is one of the last issues I wanted to address when it came
to all things related to Gemini and security: the option to "forget" the
certificate fingerprint of a host when the fingerprint has changed.&lt;/p&gt;
&lt;p&gt;Until now, if you visited a site that was using a self-signed certificate,
and the fingerprint for that certificate had changed, you'd just get an
error toast and the page would not be loaded. Technically this is the safest
thing to do, but it's not the most pragmatic approach most of the time;
capsules will change up certificates and you probably know you can still
trust them.&lt;/p&gt;
&lt;p&gt;So, from now on, rather than simply refusing to load the page, Rogallo will
tell you about the issue and then offer to forget the fingerprint and try
again.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The new security alert" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/31/security-alert.webp#centre" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;This should make the issue more noticeable and also easier to handle.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:429-1"&gt;
&lt;p&gt;If you're wondering what that even means... it only matters if your terminal of choice supports the &lt;a href="https://sw.kovidgoyal.net/kitty/pointer-shapes/" rel="noopener noreferrer" target="_blank"&gt;kitty mouse pointer shapes protocol&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:429-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content>
    <link href="https://blog.davep.org/2026/08/31/rogallo-v2-1-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-31T08:18:32+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/29/rogallo-v2-0-0.html</id>
    <title>Rogallo v2.0.0</title>
    <updated>2026-08-29T12:56:00+01:00</updated>
    <content type="html">&lt;p&gt;I've just released
&lt;a href="https://github.com/davep/rogallo/releases/tag/v2.0.0" rel="noopener noreferrer" target="_blank"&gt;v2.0.0&lt;/a&gt; of
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;. This release has quite a lot of
changes, one or two of them &lt;em&gt;"breaking changes"&lt;/em&gt;, hence the bump to v2.0.0.
I will add though that, when I say &lt;em&gt;"breaking changes"&lt;/em&gt;, nothing should
&lt;em&gt;actually&lt;/em&gt; break, it's just some features have changed in an incompatible
way and some application commands have been removed or renamed (and so some
default keyboard bindings have changed). The worst that might happen is a
keyboard binding you set up no longer works.&lt;/p&gt;
&lt;p&gt;With this in mind, in &lt;a href="https://semver.org" rel="noopener noreferrer" target="_blank"&gt;the spirit of semver&lt;/a&gt;, the major
version is bumped.&lt;/p&gt;
&lt;p&gt;Now for what's new in this release.&lt;/p&gt;
&lt;h2 id="client-certificate-management"&gt;Client certificate management&lt;/h2&gt;
&lt;p&gt;While Rogallo supported the creation and use of client certificates for use
with Gemini capsules, it never made it that easy to work with them. Creating
and using them was pretty frictionless, but if you were someone who wanted
to bring your own certificate from another application, you were on your
own. Actually doing that was easy enough, if you were comfortable with
diving into the certificate directory and hand-editing the JSON file to
create the association. What was lacking though was a good interface to
manage all of this in the application.&lt;/p&gt;
&lt;p&gt;This version solves that problem. Rogallo now contains a client certificate
manager that lets you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create new client certificates&lt;/li&gt;
&lt;li&gt;Add and remove associations for client certificates&lt;/li&gt;
&lt;li&gt;Delete client certificates&lt;/li&gt;
&lt;li&gt;Import client certificates&lt;/li&gt;
&lt;li&gt;Export client certificates&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, when you encounter a capsule that demands a certificate and you don't
have one associated, you can pick an existing one from your certificate
library; before the only option you had was to create a new one.&lt;/p&gt;
&lt;h2 id="reworked-side-panel"&gt;Reworked side panel&lt;/h2&gt;
&lt;p&gt;Initially, when I first started work on Rogallo, I had a simple history list
that could be popped in/out on the side of the display. Then, when I added
bookmarks, this became a sort of toggle, with either the history showing,
the bookmarks showing, or both hidden. The command to show the history would
hide the bookmarks; the command to show the bookmarks would hide the
history; both would toggle themselves to hide. This was... kind of messy,
but it worked.&lt;/p&gt;
&lt;p&gt;When I started work on the certificate manager it made sense that it also
occupied the same space. However, the code for managing this, and the
resulting user experience, started to get pretty messy. I wasn't at all
happy with it so ended up going on a bit of a side-quest to clean this up.&lt;/p&gt;
&lt;p&gt;The result is that Rogallo now has a &lt;a href="https://rogallo.davep.dev/side-panel/" rel="noopener noreferrer" target="_blank"&gt;tabbed side
panel&lt;/a&gt; (similar to the one in
&lt;a href="https://hike.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Hike&lt;/a&gt;). This contains the bookmark manager,
history manager and client certificate manager.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The new side panel" height="1952" loading="lazy" src="https://blog.davep.org/attachments/2026/08/29/side-panel.webp#centre" width="1942" /&gt;&lt;/p&gt;
&lt;p&gt;This is where one of the main breaking changes comes in: the
&lt;code&gt;ToggleHistoryManager&lt;/code&gt; and &lt;code&gt;ToggleBookmarksManager&lt;/code&gt; commands have been
removed from Rogallo and their default keyboard bindings have been freed up.
Also, to clean up the naming of things, I've renamed &lt;code&gt;JumpToSidebar&lt;/code&gt; to
&lt;code&gt;JumpToSidePanel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I feel this side panel approach is far cleaner and far easier to work with.&lt;/p&gt;
&lt;p&gt;It's also worth noting that it's moved over to the left side of the display.
However, if you'd prefer it on the right &lt;a href="https://rogallo.davep.dev/side-panel/#left-or-right-side" rel="noopener noreferrer" target="_blank"&gt;there's a configuration option for
that&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="viewing-client-certificate-information"&gt;Viewing client certificate information&lt;/h2&gt;
&lt;p&gt;As part of the work on managing client certificates, I added a dialog that
lets you view details of a certificate. As well as being available in the
certificate manager, it can also be used to view any certificate that might
be in use when viewing the current page. The &lt;code&gt;AboutClientCertificate&lt;/code&gt;
command (bound to &lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;F7&lt;/kbd&gt; by default) can be used to
bring up the view.&lt;/p&gt;
&lt;p&gt;For the folk who lean more on the mouse, the key icon that appears in the
title bar of the viewer can be clicked on to get the same view.&lt;/p&gt;
&lt;h2 id="protocol-guessing-in-the-command-line"&gt;Protocol guessing in the command line&lt;/h2&gt;
&lt;p&gt;The command line in the application now tries to be a little bit smarter
when it comes to understanding input. Before now, if you were to type in
&lt;code&gt;example.com&lt;/code&gt;, Rogallo would assume that you were attempting to visit a
Gemini capsule on that host and process the input as if it were
&lt;code&gt;gemini://example.com/&lt;/code&gt;. This release extends this a little.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the input doesn't appear to be anything else and it includes a &lt;code&gt;@&lt;/code&gt; it
  will be turned into a &lt;code&gt;finger&lt;/code&gt; URI. So &lt;code&gt;user@example.com&lt;/code&gt; becomes
  &lt;code&gt;finger://example.com/user&lt;/code&gt; and &lt;code&gt;@example.com&lt;/code&gt; becomes
  &lt;code&gt;finger://example.com/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the first part of the host has a recognisable protocol name, it will be
  assumed that that protocol should be used. In other words:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gopher.example.com&lt;/code&gt; -&amp;gt; &lt;code&gt;gopher://gopher.example.com/1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spartan.example.com&lt;/code&gt; -&amp;gt; &lt;code&gt;spartan://spartan.example.com/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nex.example.com&lt;/code&gt; -&amp;gt; &lt;code&gt;nex://nex.example.com/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is probably of very minor use, but it was easy enough to add and seemed
like a useful little change.&lt;/p&gt;
&lt;h2 id="emoji-removal-overhaul"&gt;Emoji removal overhaul&lt;/h2&gt;
&lt;p&gt;I've overhauled the code that does emoji removal if you toggle removal on.
More work is done to identify "real" emoji. This should mean that all the
usual colourful image-like candidates are removed, but now things like
braille and box drawing characters, etc, &lt;em&gt;won't&lt;/em&gt; be removed.&lt;/p&gt;
&lt;p&gt;Also, when removing an emoji, if there is a space following it, that space
will also be removed. This solves the cosmetic problem of &lt;code&gt;"👉 This"&lt;/code&gt; being
turned into &lt;code&gt;" This"&lt;/code&gt; when it would make more sense that it is turned into
&lt;code&gt;"This"&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It's worth keeping in mind here that this isn't intended to be a
100%-correct solution. It's aimed at being a good-enough solution to clean
up most of the emoji clutter if you don't like that sort of thing.&lt;/p&gt;
&lt;h2 id="overall-performance"&gt;Overall performance&lt;/h2&gt;
&lt;p&gt;My general approach to developing anything is one of &lt;em&gt;"make it right then
make it fast"&lt;/em&gt;. I've never been a fan of early optimisation, and when I've
watched people obsess over such things far too early in a codebase's
lifecycle I've generally watched them get into a mess. I like to try and
avoid that mess.&lt;/p&gt;
&lt;p&gt;So this was my approach with Rogallo. When it came to building the widget
that displayed the content of a page, I spent my time trying to ensure it
was correct, not that it was fast. Quite quickly, however, I found that once
a page had quite a few links on it -- especially when you got to many 100s
of links -- performance was terrible. I'd had an issue sat in TODO for this
from the start, but hadn't gone back to address it.&lt;/p&gt;
&lt;p&gt;Then the other day someone else noted this issue so I decided it was time to
go back and work on it. As of this release of Rogallo you should find that a
page with 1,000 links on it performs about as well as a page with a handful
of links.&lt;/p&gt;
&lt;p&gt;In doing this work I've also made a lot of optimisations to how a page is
initially built; so not only should a page be more responsive as you
navigate it, it should be noticeably quicker to appear in the first place.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There's a lot in this release and I'm really delighted with how it's turned
out. I wasn't intending to make quite so many large changes, but each bit of
work naturally caused the next bit of work and... well, here we are.&lt;/p&gt;
&lt;p&gt;With this work out of the way I can start to look at the one remaining
protocol that's currently on the TODO list, and also look at making some
other quality-of-life improvements.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/29/rogallo-v2-0-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-29T12:56:00+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/24/rogallo-v1-12-1.html</id>
    <title>Rogallo v1.12.1</title>
    <updated>2026-08-24T10:06:56+01:00</updated>
    <content type="html">&lt;p&gt;I've just made a small but important bug fix to
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;. Currently, I'm working on a more
comprehensive approach to managing client-side certificates and, in doing
so, I noted a bug with how such certificates are currently created by
Rogallo.&lt;/p&gt;
&lt;p&gt;Simply put: by default, Rogallo &lt;em&gt;should&lt;/em&gt; create certificates that
effectively never expire (the actual expiry time is the end of 9999-12-31).
Instead, if no actual expiry time was given, the certificates were being
created to expire a year after creation.&lt;/p&gt;
&lt;p&gt;This does mean that, if you've created a client certificate with Rogallo and
didn't specify your own expiry date, it currently has a far more limited
lifespan than you were probably expecting. As such, you might want to review
them and consider making fresh ones and setting them up well before they
expire (expiry probably being some time in July next year, given that
Rogallo itself has only been fully usable since around July this year).&lt;/p&gt;
&lt;p&gt;Apologies if you've used this facility and it accordingly results in a
little extra work. Thankfully it came to light sooner rather than later, and
it has come to light while I'm giving client certificate management a big
overhaul.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/24/rogallo-v1-12-1.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-24T10:06:56+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/22/rogallo-v1-12-0.html</id>
    <title>Rogallo v1.12.0</title>
    <updated>2026-08-22T12:08:13+01:00</updated>
    <content type="html">&lt;p&gt;I've released &lt;a href="https://rogallo.davep.dev/changelog/#v1120" rel="noopener noreferrer" target="_blank"&gt;v1.12.0&lt;/a&gt; of
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;. This version contains a number of
internal changes, as well as some user-facing improvements.&lt;/p&gt;
&lt;h2 id="improved-navigation-history"&gt;Improved navigation history&lt;/h2&gt;
&lt;p&gt;For a wee while now I've been wanting to tweak the way the navigation
history works. Up until this release, this was simply a backward/forward
affair with no attempt to restore the actual context of a page you've gone
back to. This could best be felt if you're a fan of
&lt;a href="gemini://astrobotany.mozz.us/" rel="noopener noreferrer" target="_blank"&gt;AstroBotany&lt;/a&gt;. If you were to visit the
flowering plants in your community garden, with a view to visiting each one
and picking petals, the natural thing to do would be to visit a specific
plant, pick a petal, then go &lt;code&gt;Backward&lt;/code&gt; twice to get back to the list of
flowering plants. The problem at that point is that the link for the
just-visited plant would no longer be focused. This made it just a bit more
faff to go to the next plant on the list.&lt;/p&gt;
&lt;p&gt;From this release, when going backward and forward through navigation
history, Rogallo attempts to ensure that the link you had followed on that
page is focused again.&lt;/p&gt;
&lt;p&gt;Internally, this caused a fairly big overhaul of how history navigation
information is recorded. I've done a fair bit of testing and all seems good;
but &lt;a href="https://github.com/davep/rogallo?tab=contributing-ov-file" rel="noopener noreferrer" target="_blank"&gt;do let me
know&lt;/a&gt; if you
experience any oddness.&lt;/p&gt;
&lt;h2 id="showing-empty-content"&gt;Showing empty content&lt;/h2&gt;
&lt;p&gt;This is a small fix. If you were to visit a URI that resulted in an empty
document being received, the viewer would disappear. The viewer &lt;em&gt;is&lt;/em&gt;
supposed to disappear if you are visiting nowhere, but it shouldn't
disappear if you're visiting somewhere that has nothing to show. This is now
fixed.&lt;/p&gt;
&lt;h2 id="parentroot-navigation"&gt;Parent/root navigation&lt;/h2&gt;
&lt;p&gt;Rogallo has a couple of commands that make it easier to navigate to the
parent directory of a visited location, and also to the root. However, I'd
only implemented this for Gemini and Spartan URIs and sort of forgotten to
finish this off. With this release Gopher and Nex get to join in on the
parent/root navigation party.&lt;/p&gt;
&lt;h2 id="cancelling-requests"&gt;Cancelling requests&lt;/h2&gt;
&lt;p&gt;This one came up because, as of the time of writing, the server where my wee
capsule lives is dead&lt;sup id="fnref:447-1"&gt;&lt;a class="footnote-ref" href="#fn:447-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. This meant that if I checked if it was there, and
got impatient and went to navigate somewhere else, the somewhere else would
load and then, after the defined timeout, the error about the previous
request would pop up.&lt;/p&gt;
&lt;p&gt;Rogallo now ensures that, if you have an in-flight request running, and then
navigate elsewhere, that pre-existing request is cancelled.&lt;/p&gt;
&lt;h2 id="custom-prompts"&gt;Custom prompts&lt;/h2&gt;
&lt;p&gt;The in-application command line of Rogallo has two styles of prompt. The
normal input prompt (shown as &lt;code&gt;&amp;gt;&lt;/code&gt;), and the busy prompt (shown as a series
of braille characters that animate as dots snaking around). I realised that
some folk might enjoy &lt;a href="https://rogallo.davep.dev/command-line/#configuration" rel="noopener noreferrer" target="_blank"&gt;setting their own
prompts&lt;/a&gt;. While I
think the defaults are nice and clean, if you wanted something more
colourful and on-theme (in a Gemini sense anyway, which tends to be
space-oriented), you could update your configuration file with:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"command_line_prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"🚀"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"busy_indicator_cells"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"🌑🌒🌓🌔🌕🌖🌗🌘"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and have this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A space-themed prompt" loading="lazy" src="https://blog.davep.org/attachments/2026/08/22/space-prompt.gif#centre" /&gt;&lt;/p&gt;
&lt;p&gt;I'm currently running with this for my own installation of Rogallo and it's
rather growing on me.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:447-1"&gt;
&lt;p&gt;From what I've seen, someone managed to break in and pretty much &lt;code&gt;rm -rf /&lt;/code&gt; the thing. The restore of the server is being used as a good moment to change the architecture of the services it offers. This does mean it'll be a wee while before I get my capsule back.&amp;#160;&lt;a class="footnote-backref" href="#fnref:447-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content>
    <link href="https://blog.davep.org/2026/08/22/rogallo-v1-12-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-22T12:08:13+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/19/rogallo-v1-11-0.html</id>
    <title>Rogallo v1.11.0</title>
    <updated>2026-08-19T15:24:54+01:00</updated>
    <content type="html">&lt;p&gt;A quick little update to &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;, bumping to
&lt;a href="https://rogallo.davep.dev/changelog/#v1110" rel="noopener noreferrer" target="_blank"&gt;v1.11.0&lt;/a&gt;. This release is
mainly in support of people who like to use the mouse as much as, if not
more than, the keyboard; and also in support of people who might wish to
reclaim a couple of lines of display for actual content.&lt;/p&gt;
&lt;p&gt;The main change in this release is that I've swapped out the header line
that Rogallo used to have (which used the &lt;a href="https://textual.textualize.io/widgets/header/" rel="noopener noreferrer" target="_blank"&gt;stock Textual &lt;code&gt;Header&lt;/code&gt;
widget&lt;/a&gt;) and replaced it with
a mouse-friendly toolbar.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The new Rogallo toolbar" height="1212" loading="lazy" src="https://blog.davep.org/attachments/2026/08/19/new-toolbar.webp#centre" width="1288" /&gt;&lt;/p&gt;
&lt;p&gt;The thinking behind this was twofold: first, the current header wasn't
really very useful, showing just the name of the application and the version
number. I would hope, really, that most people know what application it is
they're running, so having the name there wasn't super useful. Secondly,
while Rogallo aims to be keyboard-friendly -- ideally keyboard-first -- it
also aims to be mouse-friendly where possible. The problem with the
mouse-friendly approach is that a lot of application commands were, for the
mouse user, locked behind the command palette. While not impossible to
navigate and use, it wasn't the smoothest experience.&lt;/p&gt;
&lt;p&gt;So I've swapped that header out for &lt;a href="https://rogallo.davep.dev/toolbar/" rel="noopener noreferrer" target="_blank"&gt;a configurable toolbar of command
buttons&lt;/a&gt;. The content of the toolbar is
set using the &lt;code&gt;toolbar_contents&lt;/code&gt; setting in the configuration file. The
default set looks like this:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GoHome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2302"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Reload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u21bb"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Backward"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u25c0\u25c0"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Forward"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u25b6\u25b6"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GoToParent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2191"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GoToRoot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u21c8"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"SearchHistory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u25f7"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"SearchBookmarks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2605"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ToggleView"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u21cb"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The value in the first position for each button is the name of a &lt;a href="https://rogallo.davep.dev/configuration/#bindable-commands" rel="noopener noreferrer" target="_blank"&gt;bindable
command&lt;/a&gt;. The
second value is the text to place on the button itself. If you simply want
to use the command's name, rather than a pair of values, you can just use
the command name. So suppose you wanted to use &lt;code&gt;Reload&lt;/code&gt;, &lt;code&gt;Backward&lt;/code&gt; and
&lt;code&gt;Forward&lt;/code&gt; as-is, you could set things like this:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GoHome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2302"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"Reload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"Backward"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;"Forward"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GoToParent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2191"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GoToRoot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u21c8"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"SearchHistory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u25f7"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"SearchBookmarks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2605"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ToggleView"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u21cb"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In addition to this setting, I've also added some other toolbar-related
settings. There is:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"toolbar_visible"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which controls if the toolbar is visible at all. So if you're a
keyboard-only kind of user and you want that extra line back, just set that
to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is also:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"toolbar_tooltips"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which controls the tooltips that will appear when you hover over a button in
the toolbar. These are there to explain what each button does, and to also
show you what keyboard binding is associated with each one. If the tooltips
get irritating, set this to &lt;code&gt;false&lt;/code&gt; so they don't appear.&lt;/p&gt;
&lt;p&gt;Lastly, there is:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"toolbar_can_get_focus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As I've said: the toolbar is added in support of people who use the mouse a
fair bit. This means that, by default, it can't be interacted with using the
keyboard. This makes sense in that each of the commands will have a keyboard
binding, so it makes more sense to simply use that. However, if you really
&lt;em&gt;must&lt;/em&gt; use the toolbar with the keyboard, you can set this setting to &lt;code&gt;true&lt;/code&gt;
to enable it. When set this way, you can navigate into the toolbar and
switch focus to each of those buttons using the normal &lt;kbd&gt;Tab&lt;/kbd&gt; and
&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;Tab&lt;/kbd&gt; navigation keys.&lt;/p&gt;
&lt;p&gt;One other little configuration feature can also be used to reclaim an extra
line in the display. If you have no need for the footer of the application
(where some important keys are shown), you can turn it off with:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"footer_visible"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Set it to &lt;code&gt;false&lt;/code&gt; and you get one more line of content.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/19/rogallo-v1-11-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-19T15:24:54+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/18/rogallo-v1-10-0.html</id>
    <title>Rogallo v1.10.0</title>
    <updated>2026-08-18T09:03:27+01:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v1100" rel="noopener noreferrer" target="_blank"&gt;v1.10.0&lt;/a&gt; has been released.
This is a pretty small release, with a bug fix to navigation, and an
improvement to how navigable Markdown documents are if viewed in the
application.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://blog.davep.org/2026/08/13/rogallo-v1-8-0.html"&gt;Rogallo v1.8.0&lt;/a&gt; I made some changes to
how Markdown documents are shown, if they're encountered and detected in
Geminispace (or any of the other protocol spaces that might let you know the
content type of a document). Whereas originally the document was shown in
its raw form (marked up with syntax highlighting), v1.8.0 moved to using a
fully-rendered form thanks to the internal Markdown widget.&lt;/p&gt;
&lt;p&gt;But, &lt;a href="https://blog.davep.org/2026/08/16/md2gemtext-a-library-for-converting-markdown-to-gemtext.html"&gt;as I've mentioned elsewhere in this
blog&lt;/a&gt;,
I wasn't 100% happy with this. The main problem is that the Markdown widget
supplied by Textual is pretty unfriendly to keyboard navigation, and I want
as much of Rogallo to be navigable with the keyboard as is possible.&lt;/p&gt;
&lt;p&gt;To solve this I've created &lt;a href="https://md2gemtext.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;md2gemtext&lt;/a&gt; and
started using it here in Rogallo. This means that, by default, from now on,
any time a Markdown document is received by Rogallo, the content is
converted into Gemtext before being displayed. The big advantage here is
that links are far easier to see and follow and the document as a whole
looks more in keeping with most other pages you'll visit.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Markdown rendered as a Gemtext document" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/18/markdown-after.webp" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;I'm sensitive to the fact that some folk might prefer the previous method of
viewing Markdown, so this feature &lt;a href="https://rogallo.davep.dev/viewer/#markdown-rendering" rel="noopener noreferrer" target="_blank"&gt;is
configurable&lt;/a&gt;. If
you'd prefer the widget-based rendering instead, set this value:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"convert_markdown_to_gemtext"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Markdown rendered in a full Markdown widget" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/18/markdown-before.webp#centre" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;The other change in this release is a fix to how navigation history is saved
and restored. For a couple or so weeks now, on occasion, I was finding that
when I ran up Rogallo again, navigated from the restored page, and then used
&lt;code&gt;Backward&lt;/code&gt;, I would end up somewhere else. It was intermittent and, for a
while, hard to pin down. Mostly I'd notice this while rapidly closing and
opening Rogallo while working on some other feature. Eventually &lt;a href="https://github.com/davep/rogallo/issues/290#issuecomment-5304008984" rel="noopener noreferrer" target="_blank"&gt;I figured
out the sequence of events causing the
problem&lt;/a&gt;
and it was an easy enough fix.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/18/rogallo-v1-10-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="Markdown"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-18T09:03:27+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/15/rogallo-v1-9-0.html</id>
    <title>Rogallo v1.9.0</title>
    <updated>2026-08-15T16:07:49+01:00</updated>
    <content type="html">&lt;p&gt;Another update to &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;, another new
protocol! The main change in
&lt;a href="https://rogallo.davep.dev/changelog/#v190" rel="noopener noreferrer" target="_blank"&gt;v1.9.0&lt;/a&gt; is the addition of
support for the &lt;a href="https://nightfall.city/nex/info/specification.txt" rel="noopener noreferrer" target="_blank"&gt;Nex
protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Nex support in action" height="1952" loading="lazy" src="https://blog.davep.org/attachments/2026/08/15/nex-in-action.webp#centre" width="1766" /&gt;&lt;/p&gt;
&lt;p&gt;As with &lt;a href="https://rogallo.davep.dev/protocols/" rel="noopener noreferrer" target="_blank"&gt;any other supported
protocol&lt;/a&gt;, entering a &lt;code&gt;nex://&lt;/code&gt; URI
into the &lt;a href="https://rogallo.davep.dev/command-line/" rel="noopener noreferrer" target="_blank"&gt;command line&lt;/a&gt; will cause
Rogallo to load up the response in the viewer and render it. Nex is kind of
fun in that it's &lt;em&gt;almost&lt;/em&gt; a plain text system, by default, but the
expectation is that any &lt;code&gt;text/plain&lt;/code&gt; document that has &lt;code&gt;=&amp;gt;&lt;/code&gt; at the start of
a line will have those lines be treated just like Gemtext links. So, in
Rogallo, when you visit a page, and that page is &lt;code&gt;text/plain&lt;/code&gt;, the result
will be rendered like it's very simplistic Gemtext that only supports links.&lt;/p&gt;
&lt;p&gt;Also, as per the Nex specification, the MIME type of a document is worked
out from the extension of the file it points at; so if you happen to get a
Gemtext or Markdown file back from a &lt;code&gt;nex://&lt;/code&gt; URI, this will be suitably
rendered.&lt;/p&gt;
&lt;p&gt;Another addition is a &lt;code&gt;SaveSource&lt;/code&gt; command (bound to
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; by default). As you can probably work out from
the name, this will save the source of the document you're currently
viewing.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Saving the content of a page" height="1952" loading="lazy" src="https://blog.davep.org/attachments/2026/08/15/saving.webp#centre" width="1766" /&gt;&lt;/p&gt;
&lt;p&gt;A small housekeeping addition in this release is the cleaning of the content
cache. When you start up Rogallo, in the background, any cache entries that
have exceeded their time-to-live (something you can set in the configuration
file) will be removed. If this results in any cache directories being left
empty, they will also be removed. This should result in a nice clean cache
directory that's easier to navigate and manage, if you want to go diving
into it.&lt;/p&gt;
&lt;p&gt;I've also added a small experimental development tool, mostly for myself but
it might be something someone else wants to play with. I realised a few days
ago that it could be fun to &lt;a href="gemini://tilde.team/~davep/rogallo/screenshots.gmi" rel="noopener noreferrer" target="_blank"&gt;include screenshots of Rogallo in action in my
Gemini capsule&lt;/a&gt;. The
thing is: Gemtext doesn't allow for inline images. What it does allow for,
and many clients support, is ANSI escape sequences. Meanwhile, Rogallo is a
terminal-based application; its whole method of display is ANSI escape
sequences. As such, it should be trivial to capture the sequences for any
given screen and just include them in a Gemtext page.&lt;/p&gt;
&lt;p&gt;I tried it out and it works a treat! So, if you happen to have
&lt;code&gt;ROGALLO_SCREENSHOTS&lt;/code&gt; in your environment and it's set to any non-empty
value, pressing &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;F12&lt;/kbd&gt; writes the
current screen to &lt;code&gt;~/rogallo-screenshot.ansi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Yes, it's all horribly hard-coded: the key combination is hard-coded (and
probably only good for more modern terminal emulators), and the name of the
file is hard-coded. As I said: it's a development tool that's there for my
own use. I might make it a little more generic in the future.&lt;/p&gt;
&lt;p&gt;One final tweak to this release is a fix to the &lt;code&gt;ToggleView&lt;/code&gt; command, which
stopped letting you view the source of a Gopher map. That ability is now
back.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/15/rogallo-v1-9-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-15T16:07:49+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/14/smolserve-v1-1-0.html</id>
    <title>SmolServe v1.1.0</title>
    <updated>2026-08-14T19:44:23+01:00</updated>
    <content type="html">&lt;p&gt;Currently, I'm working on adding support for the &lt;a href="https://blog.davep.org/tag/nex-protocol/"&gt;Nex
Protocol&lt;/a&gt; to &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;.
Having
&lt;a href="https://blog.davep.org/2026/08/14/port1900-an-async-python-client-library-for-the-nex-protocol.html"&gt;Port1900&lt;/a&gt;
as the client library, and having &lt;a href="https://github.com/davep/rogallo/pull/345" rel="noopener noreferrer" target="_blank"&gt;done the bulk of the work in
Rogallo&lt;/a&gt;, I needed things in
place to be able to add some &lt;code&gt;nex://&lt;/code&gt;-related documentation too -- which is
where &lt;a href="https://smolserve.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;SmolServe&lt;/a&gt; comes in.&lt;/p&gt;
&lt;p&gt;So I've dropped &lt;a href="https://smolserve.davep.dev/changelog/#v110" rel="noopener noreferrer" target="_blank"&gt;v1.1.0&lt;/a&gt; on
&lt;a href="https://blog.davep.org/tag/pypi/"&gt;PyPI&lt;/a&gt;, which adds support for running up a simple
just-good-enough Nex server (although, to be fair, Nex is &lt;em&gt;so&lt;/em&gt; simple this
is probably a fully capable one just by the very nature of how trivial the
protocol is).&lt;/p&gt;
&lt;p&gt;Now to get back to polishing that Rogallo PR...&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/14/smolserve-v1-1-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="SmolServe"/>
    <category term="Nex Protocol"/>
    <category term="smolweb"/>
    <published>2026-08-14T19:44:23+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/13/rogallo-v1-8-0.html</id>
    <title>Rogallo v1.8.0</title>
    <updated>2026-08-13T08:28:31+01:00</updated>
    <content type="html">&lt;p&gt;I've released &lt;a href="https://rogallo.davep.dev/changelog/#v180" rel="noopener noreferrer" target="_blank"&gt;v1.8.0&lt;/a&gt; of
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;. This release has a bit of an
accidental emphasis on control of how things are rendered in the main
viewer.&lt;/p&gt;
&lt;h2 id="markdown"&gt;Markdown&lt;/h2&gt;
&lt;p&gt;While Rogallo is, of course, primarily aimed at loading and rendering
&lt;a href="https://blog.davep.org/tag/gemtext/"&gt;Gemtext&lt;/a&gt; documents, I have written it so that it'll try and
display anything whose content type matches &lt;code&gt;text/*&lt;/code&gt;. In most cases this
will result in something being shown as plain text and, as of
&lt;a href="https://blog.davep.org/2026/08/08/rogallo-v1-6-0.html"&gt;v1.6.0&lt;/a&gt;, it will also attempt to add some
syntax highlighting where appropriate. So, if you happened to come across a
Markdown file in Geminispace, and the server told Rogallo that it was a
Markdown file, it would look something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Viewing highlighted raw Markdown" height="868" loading="lazy" src="https://blog.davep.org/attachments/2026/08/13/raw-markdown.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;p&gt;Simply put: raw Markdown but syntax-highlighted.&lt;/p&gt;
&lt;p&gt;The thing is, Rogallo contains everything needed to actually render the
Markdown; it's &lt;a href="https://textual.textualize.io/widgets/markdown/" rel="noopener noreferrer" target="_blank"&gt;carrying that code
around&lt;/a&gt; due to it being
built on top of the &lt;a href="https://blog.davep.org/tag/textual/"&gt;Textual framework&lt;/a&gt;, so it seemed a shame
to not use it. So as of this version, if a Markdown file is encountered, by
default it'll be shown as a full Markdown widget.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Viewing rendered Markdown" height="868" loading="lazy" src="https://blog.davep.org/attachments/2026/08/13/rendered-markdown.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;h2 id="html"&gt;HTML&lt;/h2&gt;
&lt;p&gt;Having added the above, I got to thinking that it might be interesting to
consider other &lt;code&gt;text/*&lt;/code&gt; types that I could render in a more Rogallo-friendly
way. The next that came to mind was &lt;code&gt;text/html&lt;/code&gt;. While it's not going to be
&lt;em&gt;that&lt;/em&gt; common to encounter HTML on the end of a &lt;code&gt;gemini://&lt;/code&gt; connection, it's
not impossible. Initially I did consider going via a route that had me turn
the HTML into Markdown and then use the Markdown widget to show the result,
&lt;a href="https://blog.davep.org/2026/08/11/html2gemtext-a-simple-library-for-converting-html-to-gemtext.html"&gt;but in the end I decided to turn it into Gemtext
instead&lt;/a&gt;;
in part because it's a fun challenge, and in part because it feels more in
keeping with the Geminispace aesthetic&lt;sup id="fnref:443-1"&gt;&lt;a class="footnote-ref" href="#fn:443-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;So, whereas before, if you landed on some HTML in Geminispace, you'd see
this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Viewing raw HTML" height="868" loading="lazy" src="https://blog.davep.org/attachments/2026/08/13/raw-html.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;p&gt;From now on you'll see something more like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Viewing HTML rendered as Gemtext" height="868" loading="lazy" src="https://blog.davep.org/attachments/2026/08/13/rendered-html.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;p&gt;This HTML to Gemtext support is still in its infancy so I imagine there's
going to be a lot of fun corner cases that don't quite work out, but for me
the utility makes it worth working on.&lt;/p&gt;
&lt;h2 id="extended-toggleview"&gt;Extended &lt;code&gt;ToggleView&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Until now the &lt;code&gt;ToggleView&lt;/code&gt; command (bound to &lt;kbd&gt;F4&lt;/kbd&gt; by default)
simply toggled Gemini-based Gemtext and Gopher maps between their rendered
and raw views (acting as a sort of "view source" command). With the addition
of richer rendering of Markdown and HTML it will also toggle those content
types. The point here being, if you really need to look at the raw content
of a Markdown or HTML document found in Geminispace, it's still there for
you.&lt;/p&gt;
&lt;h2 id="the-handofftooperatingsystem-command"&gt;The &lt;code&gt;HandOffToOperatingSystem&lt;/code&gt; command&lt;/h2&gt;
&lt;p&gt;A key feature of Rogallo is the automatic handing off of URIs and MIME types
that it can't directly handle. On occasion, though, I find myself wanting to
do the same hand-off with a document I'm successfully viewing in Rogallo.
This was easy enough to do with the &lt;code&gt;CopyLocationToClipboard&lt;/code&gt; command (bound
to &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;c&lt;/kbd&gt; by default), pasting the
URI into my normal web browser and going from there. But it felt like this
should be a command in its own right.&lt;/p&gt;
&lt;p&gt;So now there's &lt;code&gt;HandOffToOperatingSystem&lt;/code&gt; (bound to
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;o&lt;/kbd&gt; by default), which will ask
your environment to open the current URI.&lt;/p&gt;
&lt;h2 id="hiding-some-pre-formatted-text"&gt;Hiding some pre-formatted text&lt;/h2&gt;
&lt;p&gt;Yesterday, I saw &lt;a href="gemini://station.martinrue.com/freezr/54d38c82c214477eba340638ce787e2f" rel="noopener noreferrer" target="_blank"&gt;a post on
Station&lt;/a&gt;
which was talking about the site logo. The main thrust of it being, while
the logo is cool and all, it does use up a fair bit of vertical space that
you have to get past to get to the content. I can see this being an
&lt;a href="https://blog.davep.org/tag/a11y/"&gt;a11y&lt;/a&gt; issue in some situations, if nothing else.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The Station logo taking up space" height="868" loading="lazy" src="https://blog.davep.org/attachments/2026/08/13/the-station-logo.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;p&gt;So I got to thinking: in the case of
&lt;a href="gemini://station.martinrue.com/" rel="noopener noreferrer" target="_blank"&gt;Station&lt;/a&gt;, the author of the site has been
kind enough to give the pre-formatted text block some alt-text&lt;sup id="fnref:443-2"&gt;&lt;a class="footnote-ref" href="#fn:443-2"&gt;2&lt;/a&gt;&lt;/sup&gt;, so that
means it's possible to have a targeted filter for such well-designed sites.
Given this, I've added &lt;a href="https://rogallo.davep.dev/viewer/#filtering-out-pre-formatted-text" rel="noopener noreferrer" target="_blank"&gt;a method of filtering out pre-formatted
blocks&lt;/a&gt;,
keyed on a URI and alt-text. So now, with the addition of this to my
configuration:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"hide_preformatted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"gemini://station.martinrue.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;"Station logo"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I can get straight to the content when landing at the Station:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Station without the logo" height="868" loading="lazy" src="https://blog.davep.org/attachments/2026/08/13/station-sans-logo.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;div class="admonition admonition-note"&gt;
&lt;div class="admonition-title"&gt;ℹ️ Note&lt;/div&gt;
&lt;div class="admonition-content"&gt;
&lt;p&gt;I did hesitate before adding this. There's a part of me that was thinking
&lt;em&gt;"but the creator of the site has designed the site this way, does it make
sense to override their choice?"&lt;/em&gt; -- but then I decided that, if
Geminispace is about anything, it's about privacy, freedom and control
over &lt;em&gt;your&lt;/em&gt; experience of it. Moreover, using this is a choice on the
client side, and like I say, it's in part an a11y feature.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="gopher-cache-support"&gt;Gopher cache support&lt;/h2&gt;
&lt;p&gt;More as an accident of how I was working on things than a conscious choice,
the only protocols in Rogallo that also used the content cache were Gemini
and Spartan. With this release of Rogallo I've extended it to Gopher
responses too. I've made a point of &lt;em&gt;not&lt;/em&gt; using the cache for any response
that is going to be the result of a search, as that feels like something
that's often going to have more dynamic content.&lt;/p&gt;
&lt;h2 id="small-gopher-fix"&gt;Small Gopher fix&lt;/h2&gt;
&lt;p&gt;Talking of Gopher: there's also a small fix to Gopher responses in this
release. When looking for responses that indicated an error from Gopher
servers, Rogallo was a little too keen in how it worked, which could result
in a plain text response, that just happened to have a &lt;code&gt;3&lt;/code&gt; in the first
column of any line, being seen as a Gopher map that indicated an error.&lt;/p&gt;
&lt;p&gt;This is now fixed.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:443-1"&gt;
&lt;p&gt;Which also has me wanting, longer-term, to do the same for Markdown. While using the Markdown widget is neat and all, I think it would be far more in keeping with the purpose of this project to turn Markdown into Gemtext.&amp;#160;&lt;a class="footnote-backref" href="#fnref:443-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:443-2"&gt;
&lt;p&gt;As I write more Gemtext myself, I'm going to do my very best to always do the same.&amp;#160;&lt;a class="footnote-backref" href="#fnref:443-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content>
    <link href="https://blog.davep.org/2026/08/13/rogallo-v1-8-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-13T08:28:31+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/10/rogallo-v1-7-0.html</id>
    <title>Rogallo v1.7.0</title>
    <updated>2026-08-10T20:13:18+01:00</updated>
    <content type="html">&lt;p&gt;I've just made a small release of &lt;a href="https://rogallo.davep.dev" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;,
bumping the version to &lt;a href="https://rogallo.davep.dev/changelog/#v170" rel="noopener noreferrer" target="_blank"&gt;v1.7.0&lt;/a&gt;.
Most of the changes in this version aren't very visible, but quite a few
things have changed under the hood.&lt;/p&gt;
&lt;p&gt;One change that &lt;em&gt;might&lt;/em&gt; show up on occasion is the addition of an encoding
fallback if you encounter an ISO-8859-1 file out in the wild (oh how that
takes me back). Before, Rogallo would pop up an error and refuse to show the
file; now it will show it just fine.&lt;/p&gt;
&lt;p&gt;I've also made some improvements to how Rogallo navigates Gemtext files
being browsed locally in the filesystem. Before now, when viewing local
files, if a link was for another local file, it would show an external link
icon rather than a Gemini link icon. This is now fixed. The other change is
that, if you're browsing local files that have links to a directory rather
than a file -- thereby implying that an &lt;code&gt;index.gmi&lt;/code&gt; should be looked for --
Rogallo will take a peek at the directory, see if there is an index file
available, and take this into account.&lt;/p&gt;
&lt;p&gt;This &lt;em&gt;should&lt;/em&gt; make it a smoother experience if you're using Rogallo to
locally preview some Gemtext files before you upload them to a capsule.&lt;/p&gt;
&lt;p&gt;The final noticeable change is the addition of a &lt;code&gt;ViewChangeLog&lt;/code&gt; command
(AKA &lt;code&gt;!view_change_log&lt;/code&gt; in the internal command line). Bound to
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;l&lt;/kbd&gt; by default, this navigates you
to the &lt;a href="gemini://tilde.team/~davep/rogallo/changelog.gmi" rel="noopener noreferrer" target="_blank"&gt;Gemtext version of the Rogallo
ChangeLog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In addition to this, I've made a &lt;em&gt;lot&lt;/em&gt; of changes to some of the internals.
The class that handles the main screen of Rogallo was getting pretty large,
with a lot of detail of how to handle different protocols sitting in the
code. While not causing any runtime issues, it made the code increasingly
bloated and untidy (and I &lt;strong&gt;really hate&lt;/strong&gt; large Python files). So I've moved
the handling of each of the protocols into their own files. This also has
the benefit of making it a little easier and a little more maintainable
if/when I add another protocol or two. It should also make the code more
readable for anyone else looking over it.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/10/rogallo-v1-7-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="smolweb"/>
    <published>2026-08-10T20:13:18+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/09/smolserve-a-lightweight-multi-protocol-small-web-server.html</id>
    <title>SmolServe - A lightweight multi-protocol small web server</title>
    <updated>2026-08-09T14:05:08+01:00</updated>
    <content type="html">&lt;p&gt;As &lt;a href="https://blog.davep.org/tag/rogallo/"&gt;Rogallo&lt;/a&gt; got close to being "stable", I did a fair bit of
work on &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;its documentation&lt;/a&gt;. Something that I
wanted to include in the site was a good collection of up-to-date
screenshots. These are all created on the fly. To do this, of course,
requires something that looks like a Gemini server.&lt;/p&gt;
&lt;p&gt;Initially, this was simple: Rogallo only supported Gemini capsules, so I
could illustrate most things just using &lt;a href="https://blog.davep.org/tag/gemtext/"&gt;Gemtext&lt;/a&gt; files in
the local filesystem (with an admonition in the documentation to point out
that Rogallo was for more than viewing local files). This, of course, wasn't
going to scale when &lt;a href="https://blog.davep.org/2026/07/24/rogallo-v1-1-0.html"&gt;I added Finger
support&lt;/a&gt;, and neither was it going to work
well for &lt;a href="https://blog.davep.org/2026/07/28/rogallo-v1-2-0.html"&gt;Gopher support&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The solution seemed obvious: use a lightweight local server for these
protocols. With this need in place &lt;a href="https://smolserve.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;SmolServe&lt;/a&gt;
was born. As mentioned &lt;a href="https://blog.davep.org/2026/08/05/rogallo-v1-5-0.html"&gt;when I released Rogallo
v1.5.0&lt;/a&gt;, this &lt;em&gt;isn't&lt;/em&gt; a project to build a
comprehensive &lt;a href="https://blog.davep.org/tag/smolweb/"&gt;smolweb&lt;/a&gt; server. The aim is to build myself a
minimal just-good-enough server that helps me with local testing and
documentation.&lt;/p&gt;
&lt;p&gt;As it stands, SmolServe supports Gemini, Gopher, Finger and Spartan. Or,
rather, it supports a just-enough-to-get-by version of each of those
protocols. None are implemented in a way that would serve as a "production"
server; they're implemented to allow me to generate screenshots for the
Rogallo documentation, involving any of the supported protocols, without the
need to rely on services I don't control and which aren't local.&lt;/p&gt;
&lt;p&gt;The big benefit of SmolServe is the &lt;code&gt;exec&lt;/code&gt; support. With this, you can run
up the server and then have it run another command. Once that command
finishes its work, SmolServe will close down too. This means that, when it
comes to producing the Rogallo documentation, I can just have the server
running when I need it. Pulling some snippets &lt;a href="https://github.com/davep/rogallo/blob/main/Makefile" rel="noopener noreferrer" target="_blank"&gt;from the Rogallo
&lt;code&gt;Makefile&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight" data-lang="makefile"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;run&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;uv&lt;span class="w"&gt; &lt;/span&gt;run
&lt;span class="nv"&gt;smol&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;run&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;smolserve&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;docs&lt;span class="k"&gt;)&lt;/span&gt;server/smolserve.toml
&lt;span class="nv"&gt;smolexec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;smol&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--
&lt;span class="nv"&gt;mkdocs&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;smolexec&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mkdocs

&lt;span class="c"&gt;##############################################################################&lt;/span&gt;
&lt;span class="c"&gt;# Documentation.&lt;/span&gt;
&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;
&lt;span class="nf"&gt;docs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mkdocs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build

&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rtfm&lt;/span&gt;
&lt;span class="nf"&gt;rtfm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mkdocs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;serve&lt;span class="w"&gt; &lt;/span&gt;--livereload

&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;publishdocs&lt;/span&gt;
&lt;span class="nf"&gt;publishdocs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;-&lt;span class="n"&gt;docs&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mkdocs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gh-deploy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The idea is that, when I build the documentation, I actually run
&lt;code&gt;smolserve&lt;/code&gt;, which in turn runs &lt;code&gt;mkdocs&lt;/code&gt;, which then produces the
documentation while the local server is available.&lt;/p&gt;
&lt;p&gt;I also use this sort of approach for local testing of the &lt;a href="https://github.com/davep/tilde-team-capsule" rel="noopener noreferrer" target="_blank"&gt;content of my
capsule&lt;/a&gt; that lives &lt;a href="gemini://tilde.team/~davep" rel="noopener noreferrer" target="_blank"&gt;over on
&lt;code&gt;tilde.team&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight" data-lang="makefile"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;
&lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;uv&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;smolserve&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;smolserve.toml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rogallo&lt;span class="w"&gt; &lt;/span&gt;open&lt;span class="w"&gt; &lt;/span&gt;gemini://localhost/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;My aim now is that, if I add any other protocols to Rogallo, I'll add a
just-good-enough version of them to SmolServe to help me with testing and
documentation. For the moment, though, I think it's in a stable and usable
state.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/09/smolserve-a-lightweight-multi-protocol-small-web-server.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="SmolServe"/>
    <category term="Spartan Protocol"/>
    <category term="finger"/>
    <category term="gopher"/>
    <category term="smolweb"/>
    <published>2026-08-09T14:05:08+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/08/rogallo-v1-6-0.html</id>
    <title>Rogallo v1.6.0</title>
    <updated>2026-08-08T16:21:19+01:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v160" rel="noopener noreferrer" target="_blank"&gt;v1.6.0&lt;/a&gt; is now available. This
release concentrates on the addition of a newly-supported protocol, and
improving what can be displayed in the viewer and how it looks.&lt;/p&gt;
&lt;p&gt;The headline change is the addition of support for the &lt;a href="https://portal.mozz.us/spartan/spartan.mozz.us/" rel="noopener noreferrer" target="_blank"&gt;Spartan
protocol&lt;/a&gt;. Having run into
a couple of sites that either offered this as an alternative access method
to their content, or the only access method, and noticing its vague
similarity to Gemini (and also its reliance on Gemtext as the main hypertext
language), it seemed like an obvious feature to add. So, &lt;a href="https://blog.davep.org/2026/08/07/sybaritic-a-spartan-protocol-library-for-python.html"&gt;having built a
library to handle the
low-level details&lt;/a&gt;,
I got to &lt;a href="https://rogallo.davep.dev/spartan/" rel="noopener noreferrer" target="_blank"&gt;adding support for this to
Rogallo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing the Spartan home page" height="1952" loading="lazy" src="https://blog.davep.org/attachments/2026/08/08/spartan.webp#centre" width="1766" /&gt;&lt;/p&gt;
&lt;p&gt;Anyone using Rogallo should find that &lt;code&gt;spartan://&lt;/code&gt; URIs are handled in just
the same way as &lt;code&gt;gemini://&lt;/code&gt; URIs are, so following them from within
documents, or entering them into the &lt;a href="https://rogallo.davep.dev/command-line/" rel="noopener noreferrer" target="_blank"&gt;command
line&lt;/a&gt; all works. On top of this,
Rogallo now supports Spartan's &lt;code&gt;=:&lt;/code&gt; line type in documents served from a
Spartan server. This means that this form of input is now supported.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Entering text to upload to a Spartan server" height="1952" loading="lazy" src="https://blog.davep.org/attachments/2026/08/08/spartan-input.webp#centre" width="1766" /&gt;&lt;/p&gt;
&lt;p&gt;So, just to recap, at this point, Rogallo &lt;a href="https://rogallo.davep.dev/protocols/" rel="noopener noreferrer" target="_blank"&gt;supports 4 different
protocols&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rogallo.davep.dev/finger/" rel="noopener noreferrer" target="_blank"&gt;Finger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rogallo.davep.dev/gemini/" rel="noopener noreferrer" target="_blank"&gt;Gemini&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rogallo.davep.dev/gopher/" rel="noopener noreferrer" target="_blank"&gt;Gopher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rogallo.davep.dev/spartan/" rel="noopener noreferrer" target="_blank"&gt;Spartan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I suspect this won't be the last of them, but I sense I'm close to adding
the most useful ones.&lt;/p&gt;
&lt;p&gt;The two other changes in this release are closely related. Rogallo has
always handed off any MIME types that it can't directly handle, and the
types it could handle were set to a very narrow collection -- Gemtext,
Gopher maps and plain text, pretty much. With this release the list has been
expanded to anything &lt;code&gt;text/*&lt;/code&gt;. Working on the (pretty safe) assumption that
any &lt;code&gt;text/&lt;/code&gt; MIME type can be displayed as text, this seemed like a sensible
switch to make.&lt;/p&gt;
&lt;p&gt;Working in conjunction with this, Rogallo will now also attempt to infer
what kind of text is being shown, and apply some syntax highlighting where
appropriate. So, for example, if you visit a text file that is Python code,
it will be highlighted as Python code (&lt;em&gt;if&lt;/em&gt; the server tells us that we're
looking at Python code).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Viewing some Python code" height="1952" loading="lazy" src="https://blog.davep.org/attachments/2026/08/08/python-code.webp#centre" width="1766" /&gt;&lt;/p&gt;
&lt;p&gt;One final change in this release is a small fix to Gopher support. Rogallo
lets you configure a connection timeout value, but this wasn't being used
for Gopher support. This is now fixed.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/08/rogallo-v1-6-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="Spartan Protocol"/>
    <category term="smolweb"/>
    <published>2026-08-08T16:21:19+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/08/05/rogallo-v1-5-0.html</id>
    <title>Rogallo v1.5.0</title>
    <updated>2026-08-05T15:55:32+01:00</updated>
    <content type="html">&lt;p&gt;After a short break &lt;a href="https://blog.davep.org/2026/08/02/fossil-hunting-in-whitby.html"&gt;to do some fossil
hunting&lt;/a&gt;, I'm back tinkering with
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;. The main change in
&lt;a href="https://rogallo.davep.dev/changelog/#v150" rel="noopener noreferrer" target="_blank"&gt;v1.5.0&lt;/a&gt; is the addition of
&lt;a href="https://rogallo.davep.dev/custom-themes/" rel="noopener noreferrer" target="_blank"&gt;support for custom themes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before I get to that though, there's a small number of other fixes,
additions and tweaks. The first is a small change to the Gopher support. As
of this version, if there's a type &lt;code&gt;8&lt;/code&gt; item in a Gopher menu, it will now be
turned into a &lt;code&gt;telnet://&lt;/code&gt; URI rather than being left as a &lt;code&gt;gopher://&lt;/code&gt; URI.
This should help in handing off such an item to the correct application in
your environment.&lt;/p&gt;
&lt;p&gt;I've also added a new command: &lt;code&gt;PipeDocument&lt;/code&gt;. This is bound to
&lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;p&lt;/kbd&gt; by default. If you're viewing
a document and run this command, you'll be prompted for a shell command that
the source of the document will be piped through. This could be useful for
transforming the source and passing it on elsewhere. For example:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Piping a document" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/05/pipe-document.webp#centre" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;One small fix in this release is the correction of a typo in the code that
resulted in a misspelled item in the configuration file. The
&lt;code&gt;bookmarks_visble&lt;/code&gt; configuration setting has been changed to
&lt;code&gt;bookmarks_visible&lt;/code&gt; (the spelling of &lt;em&gt;visible&lt;/em&gt; was wrong). Technically this
is a breaking change but, because the impact is almost zero, I'm running
with it. The worst possible outcome after installing v1.5.0 is that the
bookmarks aren't showing in the sidebar when they were before; calling them
back up will fix the issue.&lt;/p&gt;
&lt;p&gt;Now on to the main change: custom themes. Rogallo has always had theme
support, and the themes that were made available were most of the themes
built into &lt;a href="https://blog.davep.org/tag/textual/"&gt;Textual&lt;/a&gt;. There &lt;a href="https://github.com/davep/rogallo/discussions/225" rel="noopener noreferrer" target="_blank"&gt;was a
request&lt;/a&gt; to be able to
create additional themes, and so, &lt;a href="https://rogallo.davep.dev/custom-themes/" rel="noopener noreferrer" target="_blank"&gt;here's that
feature&lt;/a&gt;. Using this, if you want
to have Rogallo look &lt;em&gt;just so&lt;/em&gt;, you can now follow the documentation, or
look over the
&lt;a href="https://github.com/davep/rogallo/tree/main/example-themes" rel="noopener noreferrer" target="_blank"&gt;examples&lt;/a&gt;, and
have a play. So if you fancied a version of Rogallo that looked like it was
running on a good old green terminal:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Green example theme" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/05/green.webp#centre" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;Or perhaps an amber terminal is more your thing?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Amber example theme" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/05/amber.webp#centre" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;Maybe you hanker after the days of MS-DOS and those Turbo IDEs?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Something more Turbo" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/05/turbo.webp#centre" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;Even better: perhaps the CBM64 was your thing back in the day?&lt;/p&gt;
&lt;p&gt;&lt;img alt="A theme that evokes the CBM64" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/08/05/cbm64.webp#centre" width="916" /&gt;&lt;/p&gt;
&lt;p&gt;Note that none of these themes are part of Rogallo itself, and don't ship
&lt;em&gt;with&lt;/em&gt; it; they're just examples of what you could do if you wished. I don't
even offer them as good examples of what you could do (for example: I can
see that I've managed to end up with the jump labels being far too dim to be
readable). I'm sure other people with more talent for design than I have
will be able to do far better. If anyone wants to make their own themes and
share them, I've &lt;a href="https://github.com/davep/rogallo/discussions/categories/custom-themes" rel="noopener noreferrer" target="_blank"&gt;created a spot just for
that&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One last thing: while it's not a feature of this version of Rogallo, I've
also done some work on &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;the site&lt;/a&gt; to try and add
a little more detail about using Rogallo. This process will be ongoing. The
main additions here are some background on &lt;a href="https://rogallo.davep.dev/protocols/" rel="noopener noreferrer" target="_blank"&gt;the supported
protocols&lt;/a&gt; and &lt;a href="https://rogallo.davep.dev/ui/" rel="noopener noreferrer" target="_blank"&gt;some help on the key
UI elements&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The documentation is also greatly improved with better examples thanks to
&lt;a href="https://smolserve.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;smolserve&lt;/a&gt; -- this is a little helper project
I've been tinkering with. Note that this is &lt;em&gt;not&lt;/em&gt; and will never be intended
to be an actual small web server; it is and always will be a tool to help
development and to support &lt;a href="https://github.com/davep/rogallo/tree/main/docs" rel="noopener noreferrer" target="_blank"&gt;the production of Rogallo's
documentation&lt;/a&gt;.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/08/05/rogallo-v1-5-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="gemtext"/>
    <category term="smolserve"/>
    <category term="smolweb"/>
    <published>2026-08-05T15:55:32+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/07/31/rogallo-v1-4-0.html</id>
    <title>Rogallo v1.4.0</title>
    <updated>2026-07-31T08:53:27+01:00</updated>
    <content type="html">&lt;p&gt;I've updated &lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt; to
&lt;a href="https://rogallo.davep.dev/changelog/#v140" rel="noopener noreferrer" target="_blank"&gt;v1.4.0&lt;/a&gt;. The main change in this
release is to how server certificates are handled, which in turn should
solve a bit of friction Rogallo had when using some popular Gemini capsules.&lt;/p&gt;
&lt;p&gt;Until now, Rogallo simply used a
&lt;a href="https://en.wikipedia.org/wiki/Trust_on_first_use" rel="noopener noreferrer" target="_blank"&gt;TOFU&lt;/a&gt; approach for all
capsules it encountered. In part, this was because that's all I'd really
read about until that point, and also in part because, as Rogallo became
more capable and I started to use it as my daily-driver, it just worked.
Then, within the space of about a week, I had two popular capsules
apparently change their fingerprint. I wasn't expecting that so soon (hence
&lt;a href="https://github.com/davep/rogallo/issues/148" rel="noopener noreferrer" target="_blank"&gt;one issue about dealing with
this&lt;/a&gt; still needing to be
worked on).&lt;/p&gt;
&lt;p&gt;With this in mind, &lt;a href="https://github.com/davep/rogallo/issues/221" rel="noopener noreferrer" target="_blank"&gt;I made a note about
this&lt;/a&gt;, and carried on. When
&lt;a href="gemini://bbs.geminispace.org/s/Astrobotany/46479" rel="noopener noreferrer" target="_blank"&gt;someone else also noticed the fingerprint change for
AstroBotany&lt;/a&gt;, this made me
want to try and actually sort this out. And so here's v1.4.0, which I think
will (if I've understood things correctly) address the problem and make the
journey a lot smoother.&lt;/p&gt;
&lt;p&gt;From this version, Rogallo uses a kind of "hybrid" approach to validating
the certificate of a capsule. Simply put, here's how it goes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can we check with a certificate authority? If so, perform that check and
  raise an error if there's a problem.&lt;/li&gt;
&lt;li&gt;If, on the other hand, the certificate is self-signed, use the TOFU route.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To help keep an eye on this approach, and because it's just generally handy
to know, I've added a small new element to the UI of Rogallo: a verification
badge. This can be seen up in the top-left corner of the viewer. It has
three states:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It will show &lt;code&gt;⛉&lt;/code&gt; if we're visiting a capsule that was validated using a CA&lt;/li&gt;
&lt;li&gt;It will show &lt;code&gt;✓&lt;/code&gt; if we're visiting a capsule that was validated using TOFU&lt;/li&gt;
&lt;li&gt;It will show no icon if we're visiting a location where this isn't
  applicable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is alongside the already-existing &lt;code&gt;⚿&lt;/code&gt; icon that is shown if we're
making use of a client certificate.&lt;/p&gt;
&lt;p&gt;While I've not documented them yet (I need to do a round of website
updates), each of these icons can be changed if you prefer something
different. Just take a look in the &lt;code&gt;configuration.json&lt;/code&gt; file for Rogallo.&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"client_certificate_used_icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u26bf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"verified_ca_icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u26c9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"verified_tofu_icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2713"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"verified_off_icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\u2717"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"verified_none_icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that under normal circumstances the &lt;code&gt;off&lt;/code&gt; icon there should never be
needed or seen. That's just more for testing.&lt;/p&gt;
&lt;p&gt;All of this ends up looking something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing the new icons" height="868" loading="lazy" src="https://blog.davep.org/attachments/2026/07/31/showing-icons.webp#centre" width="780" /&gt;&lt;/p&gt;
&lt;p&gt;To help test and keep an eye on this, I've also added a new command to
Rogallo: &lt;code&gt;AboutThisPage&lt;/code&gt;, bound to &lt;kbd&gt;F7&lt;/kbd&gt; by default. With it you can
check on some information about the current page, and also the certificate
that was checked when acquiring it.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing info on a CA-certified page" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/07/31/ca-info.webp#centre" width="852" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing info on a self-signed page" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/07/31/self-signed-info.webp#centre" width="852" /&gt;&lt;/p&gt;
&lt;p&gt;Note that if a page is loaded from cache you &lt;em&gt;won't&lt;/em&gt; see certificate
information in this dialog, as that isn't (currently) recorded in the
metadata in the cache. I &lt;em&gt;might&lt;/em&gt; do that at some point in the future, but it
didn't seem necessary for now.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/07/31/rogallo-v1-4-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="gemtext"/>
    <category term="smolweb"/>
    <published>2026-07-31T08:53:27+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/07/29/rogallo-v1-3-0.html</id>
    <title>Rogallo v1.3.0</title>
    <updated>2026-07-29T19:29:05+01:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt; has been updated to
&lt;a href="https://rogallo.davep.dev/changelog/#v130" rel="noopener noreferrer" target="_blank"&gt;v1.3.0&lt;/a&gt;. This release adds an
extra cosmetic feature to the Gopher support, and also extends what the
internal command line is capable of.&lt;/p&gt;
&lt;p&gt;Both of the changes come from suggestions made by
&lt;a href="https://redterminal.org" rel="noopener noreferrer" target="_blank"&gt;-fab-&lt;/a&gt;, who's been an avid tester of Rogallo and a
good source of pointers and ideas. The first change comes from a mention
they made of how some &lt;a href="https://blog.davep.org/tag/gopher/"&gt;Gopher&lt;/a&gt; clients will prefix links in a
map with a three-letter ID to give a clue as to what the linked resource is.
&lt;code&gt;TXT&lt;/code&gt; for a text file, &lt;code&gt;SND&lt;/code&gt; for any audio file, &lt;code&gt;MNU&lt;/code&gt; for a link to a
further map, that sort of thing. While I didn't add that &lt;a href="https://blog.davep.org/2026/07/28/rogallo-v1-2-0.html"&gt;when I initially
added Gopher support&lt;/a&gt;, it did seem like a
useful option to provide.&lt;/p&gt;
&lt;p&gt;However, this being a "modern" TUI application, with access to a wee bit
more than plain old ASCII, I thought I'd mix it up a little. By default,
little "icons" or "badges" are shown with each link. So to take the examples
given above, I'm using 📄 for a text file, 🎵 for an audio file, and 📁 for
a menu.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Rogallo showing a Gopher hole" height="1952" loading="lazy" src="https://blog.davep.org/attachments/2026/07/29/gopher-site.webp#centre" width="1766" /&gt;&lt;/p&gt;
&lt;p&gt;Of course, some people might not want this, and this can be &lt;a href="https://rogallo.davep.dev/configuration/#gopher-item-badges" rel="noopener noreferrer" target="_blank"&gt;turned off
entirely in the configuration
file&lt;/a&gt; by
setting &lt;code&gt;gopher_show_type_badges&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;. However, it might be that
someone wants this, but not the emoji. That's where &lt;code&gt;gopher_type_badges&lt;/code&gt;
comes in. This is an association of Gopher types with text to use as the
"badge". If three-letter all-ASCII "badges" are what you want:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"gopher_type_badges"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(TXT)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(DIR)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(CSO)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(ERR)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(HQX)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(DOS)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"6"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(UUE)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"7"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(FND)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"8"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(TEL)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"9"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(BIN)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(INF)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"g"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(GIF)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"I"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(IMG)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"h"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(WEB)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"d"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(DOC)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"s"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(SND)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"P"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(PDF)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"X"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(XML)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(???)"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The other feature springs from &lt;a href="https://github.com/davep/rogallo/discussions/252" rel="noopener noreferrer" target="_blank"&gt;another suggestion -fab-
made&lt;/a&gt;. This time it was
the idea of adding direct command-line support for Gemini and Gopher search
engines. This struck me as an excellent idea, but I got to thinking that it
could be a little more generic than that. So I've added support for
declaring simple command-line aliases. There's now a section in the
configuration file&lt;sup id="fnref:389-1"&gt;&lt;a class="footnote-ref" href="#fn:389-1"&gt;1&lt;/a&gt;&lt;/sup&gt; called &lt;code&gt;aliases&lt;/code&gt;. It's an association of a command
alias and an expansion. The alias itself must be a single "word" of
characters, and the expansion the actual command that will be used. It can
be any other command-line command, or a URI. Anything that the command line
can normally handle.&lt;/p&gt;
&lt;p&gt;When the user types something into the command line, the input will be split
on the first space. If the first half matches an alias, it will be
substituted for the input, and the tail of the input will be made available
as a parameter to the expansion.&lt;/p&gt;
&lt;p&gt;There are three placeholders that do the expansion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{q}&lt;/code&gt; -- The tail of the command quoted for use in a URI&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{qp}&lt;/code&gt; -- As above, but spaces will be &lt;code&gt;+&lt;/code&gt; rather than &lt;code&gt;%20&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{r}&lt;/code&gt; -- The raw, unquoted, tail of the command&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've probably done a bad job of explaining it. But hopefully the following
default set of aliases will nicely illustrate it:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"aliases"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"fg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gopher://gopher.floodgap.com/1/v2/vs?{q}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"gp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini://gemi.dev/cgi-bin/wp.cgi/search?{q}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"ken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini://kennedy.gemi.dev/search?{q}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;"tlgs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini://tlgs.one/search?{q}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Given this, if you type &lt;code&gt;ken test search&lt;/code&gt;, the actual command that gets
input is &lt;code&gt;gemini://kennedy.gemi.dev/search?test%20search&lt;/code&gt;. As I said, it's
not just about search engines; you can also expand to other built-in
commands. For example:&lt;/p&gt;
&lt;div class="highlight" data-lang="json"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;"whois"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!finger {r}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Would have &lt;code&gt;whois davep@plan.cat&lt;/code&gt; expand to &lt;code&gt;!finger davep@plan.cat&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I feel this nicely solves the original request &lt;em&gt;and&lt;/em&gt; adds an extra layer of
utility to the internal command line.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:389-1"&gt;
&lt;p&gt;Which I totally forgot to document when putting together this release.
It'll come to the docs soon.&amp;#160;&lt;a class="footnote-backref" href="#fnref:389-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content>
    <link href="https://blog.davep.org/2026/07/29/rogallo-v1-3-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="gemtext"/>
    <category term="gopher"/>
    <category term="smolweb"/>
    <category term="textual"/>
    <published>2026-07-29T19:29:05+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/07/28/rogallo-v1-2-0.html</id>
    <title>Rogallo v1.2.0</title>
    <updated>2026-07-28T08:39:19+01:00</updated>
    <content type="html">&lt;p&gt;&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;
&lt;a href="https://rogallo.davep.dev/changelog/#v120" rel="noopener noreferrer" target="_blank"&gt;v1.2.0&lt;/a&gt; is now available. The
main change in this release is the kick-off of support for the &lt;a href="https://en.wikipedia.org/wiki/Gopher_(protocol)" rel="noopener noreferrer" target="_blank"&gt;Gopher
protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As I've mentioned before: Gopher is kind of an unknown to me, in terms of
actually using it. I'm aware of it, I've known about it ever since I first
got on the Internet back in the 1990s, I have a half-recalled memory of
dabbling with a Gopher client at some point back then, but I had no
conscious knowledge of its workings. So, when I say "kick-off" above, I say
it because I suspect there's going to be more work to do to make it work
"just so".&lt;/p&gt;
&lt;p&gt;However, right now, &lt;code&gt;gopher://&lt;/code&gt; URIs are supported in Rogallo.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Viewing a Gopher site" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/07/28/gopher-site.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;p&gt;The approach to supporting this is pretty simple: given a gophermap, as
pulled from a server, Rogallo &lt;a href="https://github.com/davep/rogallo/blob/e89d023ed6fb4f6961296368e6245399f2ef1df8/src/rogallo/widgets/viewer/gopher.py" rel="noopener noreferrer" target="_blank"&gt;converts it into
Gemtext&lt;/a&gt;
and then displays it using the normal Gemtext viewer.&lt;/p&gt;
&lt;p&gt;There is more to Gopher than just displaying the maps, of course: there's
access to all kinds of resources. Where possible, Rogallo will display
text-based resources within the viewer; all other kinds of resources are
handed off to the operating system as they probably need applications and
tools that Rogallo doesn't offer (viewing images, playing audio, etc).&lt;/p&gt;
&lt;p&gt;Searches (item type &lt;code&gt;7&lt;/code&gt;) are supported, and when following such a link, you
will be prompted for input, which will be used as the query.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Prompting for search input" height="948" loading="lazy" src="https://blog.davep.org/attachments/2026/07/28/searching.webp#centre" width="836" /&gt;&lt;/p&gt;
&lt;p&gt;Note that, for the moment, there is no support for extensions to the
protocol such as
&lt;a href="https://en.wikipedia.org/wiki/Gopher_(protocol)#Gopher+" rel="noopener noreferrer" target="_blank"&gt;Gopher+&lt;/a&gt;.
Doubtless I'll look into doing something with this in the future; Rogallo's
development is incremental and for me it's all about having fun
(re)discovering new/old things.&lt;/p&gt;
&lt;p&gt;There are two other notable changes in Rogallo v1.2.0:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I've modified the ordering of entries in the history search so that the
  items appear in most to least recent order. While being able to type in
  things to find back a location is the primary use, I also found I was
  often pulling it up to find something I'd visited very recently.&lt;/li&gt;
&lt;li&gt;I fixed the "view source" status being sticky during navigation. If I was
  viewing the source of a location, and then navigated to another location
  (by using the &lt;code&gt;Back&lt;/code&gt; command, for example), that other location would
  &lt;em&gt;also&lt;/em&gt; show the source. The status is now reset every time you navigate to
  somewhere else.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it for this release. There's still &lt;a href="https://github.com/davep/rogallo/issues?q=sort%3Aupdated-desc%20is%3Aissue%20state%3Aopen%20label%3ATODO" rel="noopener noreferrer" target="_blank"&gt;a good few things on the TODO
list&lt;/a&gt;
so I'll be tinkering and enhancing for some time to come. As always,
&lt;a href="https://github.com/davep/rogallo/discussions" rel="noopener noreferrer" target="_blank"&gt;questions or suggestions are very
welcome&lt;/a&gt;.&lt;/p&gt;</content>
    <link href="https://blog.davep.org/2026/07/28/rogallo-v1-2-0.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="gemtext"/>
    <category term="gopher"/>
    <category term="smolweb"/>
    <category term="textual"/>
    <published>2026-07-28T08:39:19+01:00</published>
  </entry>
  <entry>
    <id>https://blog.davep.org/2026/07/27/rogallo-v1-1-1.html</id>
    <title>Rogallo v1.1.1</title>
    <updated>2026-07-27T09:01:52+01:00</updated>
    <content type="html">&lt;p&gt;I've just made a small bug-fix release for
&lt;a href="https://rogallo.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Rogallo&lt;/a&gt;.
&lt;a href="https://rogallo.davep.dev/changelog/#v111" rel="noopener noreferrer" target="_blank"&gt;v1.1.1&lt;/a&gt; fixes two (mostly)
cosmetic issues &lt;a href="https://github.com/davep/rogallo/discussions/227" rel="noopener noreferrer" target="_blank"&gt;that were reported by a
user&lt;/a&gt;. From the ChangeLog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed &lt;code&gt;cosy_link_jumps&lt;/code&gt; not being loaded from configuration when Rogallo
  starts up. (&lt;a href="https://github.com/davep/rogallo/pull/230" rel="noopener noreferrer" target="_blank"&gt;#230&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fixed viewer status line being lost when &lt;code&gt;maximum_document_width&lt;/code&gt; is set
  to something other than &lt;code&gt;0&lt;/code&gt;.
  (&lt;a href="https://github.com/davep/rogallo/pull/231" rel="noopener noreferrer" target="_blank"&gt;#231&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to &lt;a href="gemini://redterminal.org/" rel="noopener noreferrer" target="_blank"&gt;fab&lt;/a&gt;&lt;sup id="fnref:376-1"&gt;&lt;a class="footnote-ref" href="#fn:376-1"&gt;1&lt;/a&gt;&lt;/sup&gt; for alerting me to these issues.&lt;/p&gt;
&lt;p&gt;One other small change in this release is that the version of
&lt;a href="https://port79.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Port79&lt;/a&gt; is included in the output from the
&lt;code&gt;diagnostics&lt;/code&gt; CLI command.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:376-1"&gt;
&lt;p&gt;See &lt;a href="https://redterminal.org" rel="noopener noreferrer" target="_blank"&gt;here&lt;/a&gt; if you don't have a Gemini client.&amp;#160;&lt;a class="footnote-backref" href="#fnref:376-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content>
    <link href="https://blog.davep.org/2026/07/27/rogallo-v1-1-1.html"/>
    <category term="Coding"/>
    <category term="Coding"/>
    <category term="Gemini Protocol"/>
    <category term="PyPI"/>
    <category term="Python"/>
    <category term="Rogallo"/>
    <category term="gemtext"/>
    <category term="smolweb"/>
    <category term="textual"/>
    <published>2026-07-27T09:01:52+01:00</published>
  </entry>
</feed>
