<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title type="text">coopi&apos;s corner of the web!</title><id>https://coopi.neocities.org/</id><updated>2026-06-12T20:00:00Z</updated><link href="https://coopi.neocities.org/" rel="alternate" type="text/html"/><link href="https://coopi.neocities.org/feed.xml" rel="self" type="application/atom+xml"/><author><name>coopi</name></author><entry><title type="text">im removing my nix flakes vs guix post</title><id>https://coopi.neocities.org/posts/taking-down-nix-flakes-vs-guix.html</id><updated>2026-06-12T20:00:00Z</updated><published>2026-06-12T20:00:00Z</published><link href="https://coopi.neocities.org/posts/taking-down-nix-flakes-vs-guix.html"/><content type="html">&lt;header&gt;
&lt;h1 class=&quot;title&quot;&gt;im removing my nix flakes vs guix post&lt;/h1&gt;
&lt;/header&gt;&lt;p&gt;
if you&apos;re here looking for my &quot;nix flakes and their guix equivalents&quot; post, it&apos;s
gone.  i deleted it.
&lt;/p&gt;

&lt;div class=&quot;important&quot; id=&quot;org8c27aa6&quot;&gt;
&lt;p&gt;
this isn&apos;t a hate letter to andrew or anything like that.  i&apos;m writing this
because i want to make sure nobody thinks i deleted the post after getting
&quot;caught&quot; for &quot;using an llm&quot;.
&lt;/p&gt;

&lt;/div&gt;

&lt;hr&gt;

&lt;p&gt;
i wrote that post because i was curious about something and wanted to understand
it better.  i researched it a lot — clearly not enough, but still.  i was proud
of it.  i shared it with my friends because i thought it was cool and they might
think so too.
&lt;/p&gt;

&lt;p&gt;
just before eeping, i posted it in a few matrix chats.  i woke up, and it was
apparently on the &lt;a href=&quot;https://lobste.rs/s/fybei2/nix_flakes_their_guix_equivalents&quot;&gt;front page of lobste.rs&lt;/a&gt;!!  i had never ever imagined any of my
blog posts would get more than &lt;b&gt;three&lt;/b&gt; interested users let alone the attention it
had garnered now.  ludovic courtès — the literal founder of guix — &lt;a href=&quot;https://toot.aquilenet.fr/@civodul/116739238432127929&quot;&gt;made a toot
about it&lt;/a&gt; that got twelve boosts!!!  i was so excited meoww!!
&lt;/p&gt;

&lt;p&gt;
and then it turned out a last-minute javascript change i&apos;d made had broken the
site on mobile, and people couldn&apos;t even read it.  i fixed it as soon as it was
brought to my attention.  but by then people were already frustrated, and i
can&apos;t blame them.
&lt;/p&gt;

&lt;p&gt;
the next day, i come back from work, and a friend shares a link: andrew tropin
wrote a &lt;a href=&quot;https://trop.in/blog/quick-review-of-nix-flakes-and-their-guix-equivalents&quot;&gt;review of my post&lt;/a&gt;.  andrew tropin.  someone whose work i really respect.
i opened it so excited.  and three paragraphs in, he says he suspects i wrote it
with an llm.
&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;
to be clear: i&apos;m not upset about being critiqued.  i actually welcome that,
especially from someone as knowledgeable as andrew.  what broke me was the
accusation that i didn&apos;t write my own words.  and it&apos;s the very first thing he
says — before any of the technical points, before any of the corrections, the
very first thing i read is that i&apos;m suspected of being fake.
&lt;/p&gt;

&lt;p&gt;
if anyone is here expecting a response to the technical points of andrew&apos;s post,
then i&apos;m sorry but this isn&apos;t it.  i was too devastated to really process them.
i&apos;m sure his criticisms are valid and correct, but i&apos;m not really in the mood to
engage right now.
&lt;/p&gt;

&lt;p&gt;
what i can tell you is how that accusation made me feel.
&lt;/p&gt;

&lt;p&gt;
i put a lot of effort into the infrastructure of this site.  i made &lt;a href=&quot;https://codeberg.org/coopi/emacs-ox-atom&quot;&gt;​&lt;code&gt;ox-atom&lt;/code&gt;​&lt;/a&gt; to
power its feed.  i made &lt;a href=&quot;https://codeberg.org/coopi/emacs-neocities&quot;&gt;​&lt;code&gt;neocities.el&lt;/code&gt;​&lt;/a&gt; to talk to neocities.  i wrote the css and
javascript by hand.  there&apos;s a cat in the background pattern.  the section
headers have little sparkles.  the postamble says &lt;code&gt;~ meow ~&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
so after all that work, being told that arguably the most important part of my
blog — the text, the part that&apos;s supposed to be &lt;i&gt;me&lt;/i&gt; — sounds like it came from a
fancier markov chain, was destroying.
&lt;/p&gt;

&lt;p&gt;
i didn&apos;t use an llm.  but i cant prove a negative, and am anyways too tired to
try.
&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;
so im taking the post down  mraow :c
&lt;/p&gt;</content></entry><entry><title type="text">look!! look at my footer!! there are buttons now!!</title><id>https://coopi.neocities.org/posts/88x31badges.html</id><updated>2026-04-13T20:00:00Z</updated><published>2026-04-13T20:00:00Z</published><link href="https://coopi.neocities.org/posts/88x31badges.html"/><summary type="text">i added 88x31 badges to my footer and i am NOT normal about it</summary><content type="html">&lt;header&gt;
&lt;h1 class=&quot;title&quot;&gt;look!! look at my footer!! there are buttons now!!&lt;/h1&gt;
&lt;/header&gt;&lt;p&gt;
okay so. i added 88x31 buttons to my footer and i am FREAKING OUT
ABOUT IT!!  every page on the site!! automatically!! i am going to add
so many buttons!!  this is a threat!!
&lt;/p&gt;

&lt;p&gt;
if you&apos;ve been on &lt;a href=&quot;https://neocities.org&quot;&gt;Neocities&lt;/a&gt; for more than five minutes you&apos;ve seen
them — those tiny 88×31 pixel badges in people&apos;s footers.  little
glittery gifs pledging allegiance to firefox or linux or whatever
fandom they&apos;re in.  i have been eyeing them on every site i visit for
weeks now, quietly wanting them, and then it hit me: i could just.  do
that.  right now.  nothing was stopping me!!
&lt;/p&gt;

&lt;p&gt;
so i did!! and it was very shrimple:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-elisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defcustom&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;publish-badges&lt;/span&gt; &apos;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;List of 88x31 badges to display in the postamble.

Each entry is a cons cell of the form (SRC . ALT), where SRC is either a
local file path relative to the publish output directory
\(e.g. \&quot;badges/emacs.gif\&quot;), or a remote URL.  ALT is the alt text for
the image.

Note that while remote URLs are accepted, hotlinking is considered very
rude: every visitor to your page burns the badge host&apos;s bandwidth, not
yours.  The host can remove the image, move it, or replace it with
anything they like at any time, silently breaking or defacing your site.
Please download badges locally instead.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:type&lt;/span&gt; &apos;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;repeat &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;cons string string&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:group&lt;/span&gt; &apos;publish&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--badge-img&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return an &amp;lt;img&amp;gt; tag for badge ENTRY, a cons of (SRC . ALT).&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let*&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;alt&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;resolved&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;if&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;string-prefix-p&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;http&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;src&lt;/span&gt;
                     &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;img src=\&quot;%s\&quot; alt=\&quot;%s\&quot; width=\&quot;88\&quot; height=\&quot;31\&quot;&amp;gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;resolved&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--badges-html&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return the postamble HTML string with a scrollable strip of badges.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt;
   &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;div id=\&quot;badges\&quot;&amp;gt;&quot;&lt;/span&gt;
   &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;mapconcat&lt;/span&gt; #&apos;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--badge-img&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-badges&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;/div&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
a list of &lt;code&gt;(path . alt-text)&lt;/code&gt; cons cells, a function that spits out
&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags, the postamble swapped for a function call.  a tiny bit of
CSS for the scrolling.  done!! twenty minutes including getting
distracted looking at badges!!  (there are SO many badges.  i have a
problem now.  this is your fault, neocities!!)
&lt;/p&gt;

&lt;p&gt;
you can see what the footer looked like before &lt;a href=&quot;https://web.archive.org/web/20260414085225/https://coopi.neocities.org/&quot;&gt;in this archive snapshot&lt;/a&gt;.
it was just &quot;Made with Org-mode · 2026&quot;.  like.  fine!!  it was fine!!  but
it was so&amp;hellip; beige. so nothing.
&lt;/p&gt;

&lt;p&gt;
now look at the bottom of this very page!!  it went from beige to &lt;i&gt;mine&lt;/i&gt;
in twenty minutes and i genuinely cannot get over that.  this is what
i love about having your own little corner of the internet — you can
just do silly things because they make you happy and nobody can stop
you!!  the smallweb is so good actually!!  i love it here so much!!
okay i need to go find more badges now bye!!
&lt;/p&gt;</content></entry><entry><title type="text">publish.el — how this site gets built and deployed, as a literate program</title><id>https://coopi.neocities.org/posts/publish.html</id><updated>2026-04-11T20:00:00Z</updated><published>2026-04-11T20:00:00Z</published><link href="https://coopi.neocities.org/posts/publish.html"/><summary type="text">the ~500-line Emacs Lisp script that turns org files into a live Neocities site, explained from top to bottom.  tangle it and it works!!</summary><content type="html">&lt;header&gt;
&lt;h1 class=&quot;title&quot;&gt;publish.el — how this site gets built and deployed, as a literate program&lt;/h1&gt;
&lt;/header&gt;&lt;nav id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#the-big-picture_d9c1affbc2f3&quot;&gt;1. The big picture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#preamble_a3038e92af6e&quot;&gt;2. Preamble&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#requires_87dea1af6129&quot;&gt;3. Requires&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#configuration_37d376f0c9ac&quot;&gt;4. Configuration&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#the-group_b9ea44d6600b&quot;&gt;4.1. The group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#site-identity_4e2026237edc&quot;&gt;4.2. Site identity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#stylesheet_d77a1bc357f2&quot;&gt;4.3. Stylesheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#scripts_e3357bfb04d1&quot;&gt;4.4. Scripts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#hooks_6d118b880f7d&quot;&gt;5. Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#paths_e24f875105bf&quot;&gt;6. Paths&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#draft-support_8102c0b56d78&quot;&gt;7. Draft support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#html-export-settings_004f3673c547&quot;&gt;8. HTML export settings&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#head-fragment-helpers_55faa66f5271&quot;&gt;8.1. Head fragment helpers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#sitemap-the-post-index_c0ff1a7d4b22&quot;&gt;9. Sitemap (the post index)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#atom-feed_08319c4136d9&quot;&gt;10. Atom feed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#project-definition_700a05459683&quot;&gt;11. Project definition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deployment_c70d504a533a&quot;&gt;12. Deployment&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#collecting-local-files_6d54ff1ccec5&quot;&gt;12.1. Collecting local files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#diffing-against-neocities_615a0d910871&quot;&gt;12.2. Diffing against Neocities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#displaying-the-diff_4c089ddf231e&quot;&gt;12.3. Displaying the diff&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#entry-points_a53c07bf511e&quot;&gt;13. Entry points&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#footer_7b02c0909541&quot;&gt;14. Footer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#that-s-it_620e193536c8&quot;&gt;15. That&apos;s it!!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/nav&gt;
&lt;p&gt;
so, in my &lt;a href=&quot;./hello-world.html&quot;&gt;first post&lt;/a&gt; I said I&apos;d upload the code &quot;soon™&quot;.
&lt;/p&gt;

&lt;p&gt;
it&apos;s been a while.  but it&apos;s HERE now — and not just as a boring blob
you squint at.  I figured I&apos;d do something genuinely fun: write it as
a &lt;b&gt;literate program&lt;/b&gt;.  which means you are reading the source code RIGHT
NOW.  the actual &lt;code&gt;publish.el&lt;/code&gt; that runs this site is tangled directly
out of this org file.  if you do &lt;code&gt;M-x org-babel-tangle&lt;/code&gt; on this
document, you get the real, working script.  isn&apos;t that insane?!  the
blog post IS the program.
&lt;/p&gt;

&lt;p&gt;
(if you&apos;ve somehow stumbled here without knowing what org-mode is:
it&apos;s a markup/notes/calendar/spreadsheet/everything system built into
emacs.  I wrote a little about it on the &lt;a href=&quot;../index.html&quot;&gt;homepage&lt;/a&gt;.)
&lt;/p&gt;

&lt;p&gt;
okay!!  let&apos;s GO.
&lt;/p&gt;
&lt;div id=&quot;outline-container-the-big-picture_d9c1affbc2f3&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;the-big-picture_d9c1affbc2f3&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;1.&lt;/span&gt; The big picture&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-the-big-picture_d9c1affbc2f3&quot;&gt;
&lt;p&gt;
the script does three things:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;b&gt;Builds&lt;/b&gt; the site — takes &lt;code&gt;org/&lt;/code&gt; full of org files, spits out &lt;code&gt;public/&lt;/code&gt;
full of HTML&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Generates a feed&lt;/b&gt; — produces &lt;code&gt;public/feed.xml&lt;/code&gt; as a proper Atom 1.0
feed&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Deploys to Neocities&lt;/b&gt; — diffs what&apos;s live against what&apos;s local, then
uploads only what changed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
the Atom feed stuff lives in &lt;a href=&quot;https://codeberg.org/coopi/emacs-ox-atom&quot;&gt;emacs-ox-atom&lt;/a&gt; (my own package!!).  the
Neocities API stuff lives in &lt;a href=&quot;https://codeberg.org/coopi/emacs-neocities&quot;&gt;emacs-neocities&lt;/a&gt; (also mine!!).  this file
wires them together with &lt;code&gt;ox-publish&lt;/code&gt;, which is the built-in org-mode
publishing engine.  three separate things, one file to rule them all.
&lt;/p&gt;

&lt;p&gt;
the directory layout it expects looks like this:
&lt;/p&gt;

&lt;pre class=&quot;example&quot; id=&quot;orgb89d9f2&quot;&gt;
project/
├── publish.el        ; this file, tangled from publish.org
├── org/
│   ├── index.org     ; homepage
│   ├── style.css     ; stylesheet
│   └── posts/        ; one .org file per post
└── public/           ; generated output (auto-created)
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-preamble_a3038e92af6e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;preamble_a3038e92af6e&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;2.&lt;/span&gt; Preamble&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-preamble_a3038e92af6e&quot;&gt;
&lt;p&gt;
every emacs lisp file that&apos;s a proper package starts with a header.
the &lt;code&gt;-*- lexical-binding: t; -*-&lt;/code&gt; bit is NOT decorative — it switches on
lexical scoping, which makes closures work like you&apos;d expect and
avoids a whole class of subtle, maddening bugs.  (if you&apos;ve ever been
burned by dynamic binding in elisp you know exactly what I mean.  if
you haven&apos;t: trust me, you want this on.)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;publish.el --- Build and deploy blog -*- lexical-binding: t; -*-
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Homepage: https://coopi.neocities.org
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Commentary:
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Personal static blog generator.  Turns Org files into a styled
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;static site with a post index and Atom feed, and optionally
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;deploys to Neocities.
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;DIRECTORY LAYOUT
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;project/
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&amp;#9500;&amp;#9472;&amp;#9472; publish.el                 ; this file
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&amp;#9500;&amp;#9472;&amp;#9472; org/
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&amp;#9474;   &amp;#9500;&amp;#9472;&amp;#9472; index.org              ; homepage
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&amp;#9474;   &amp;#9500;&amp;#9472;&amp;#9472; style.css              ; site stylesheet (default)
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&amp;#9474;   &amp;#9492;&amp;#9472;&amp;#9472; posts/                 ; blog posts (*.org)
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&amp;#9492;&amp;#9472;&amp;#9472; public/                    ; generated output (auto-created)
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Any other org/*.org file becomes a top-level page.  Static assets
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;are copied verbatim.
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;WRITING POSTS
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;#+TITLE: My post
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;#+DATE: &amp;lt;YYYY-MM-DD&amp;gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;#+DESCRIPTION: optional summary for the Atom feed
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;#+DRAFT: t        ; skip from export, index, and feed
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;USAGE
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;M-x publish-build              incremental export
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;M-x publish-build-force        full rebuild
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;M-x publish-diff               show what would change on Neocities
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;M-x publish-deploy             diff, confirm, then upload to Neocities
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;M-x publish-build-and-deploy
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;CONFIGURATION
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;M-x customize-group RET publish RET
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Code&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-requires_87dea1af6129&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;requires_87dea1af6129&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;3.&lt;/span&gt; Requires&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-requires_87dea1af6129&quot;&gt;
&lt;p&gt;
nothing exotic here.  &lt;code&gt;cl-lib&lt;/code&gt; for common lisp goodies (&lt;code&gt;seq-take&lt;/code&gt;,
&lt;code&gt;cl-return-from&lt;/code&gt;, etc.).  &lt;code&gt;neocities&lt;/code&gt; and &lt;code&gt;ox-atom&lt;/code&gt; are my packages.  the
rest ship with emacs.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;require&lt;/span&gt;&lt;/span&gt; &apos;&lt;span class=&quot;org-constant&quot;&gt;&lt;span class=&quot;org-elisp-feature&quot;&gt;cl-lib&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;require&lt;/span&gt;&lt;/span&gt; &apos;&lt;span class=&quot;org-constant&quot;&gt;&lt;span class=&quot;org-elisp-feature&quot;&gt;neocities&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;require&lt;/span&gt;&lt;/span&gt; &apos;&lt;span class=&quot;org-constant&quot;&gt;&lt;span class=&quot;org-elisp-feature&quot;&gt;ox-atom&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;require&lt;/span&gt;&lt;/span&gt; &apos;&lt;span class=&quot;org-constant&quot;&gt;&lt;span class=&quot;org-elisp-feature&quot;&gt;ox-publish&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;require&lt;/span&gt;&lt;/span&gt; &apos;&lt;span class=&quot;org-constant&quot;&gt;&lt;span class=&quot;org-elisp-feature&quot;&gt;rx&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;require&lt;/span&gt;&lt;/span&gt; &apos;&lt;span class=&quot;org-constant&quot;&gt;&lt;span class=&quot;org-elisp-feature&quot;&gt;seq&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-configuration_37d376f0c9ac&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;configuration_37d376f0c9ac&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;4.&lt;/span&gt; Configuration&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-configuration_37d376f0c9ac&quot;&gt;
&lt;p&gt;
I use &lt;code&gt;defgroup&lt;/code&gt; / &lt;code&gt;defcustom&lt;/code&gt; here.  &lt;code&gt;defcustom&lt;/code&gt; is the modern standard for
user-facing variables in elisp — it registers the variable with the
type system and integrates with help.  I don&apos;t actually use the
customize UI, I just set things in my config. but using &lt;code&gt;defcustom&lt;/code&gt; is
the right thing to do and I am trying to have good habits.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-the-group_b9ea44d6600b&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;the-group_b9ea44d6600b&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;4.1.&lt;/span&gt; The group&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-the-group_b9ea44d6600b&quot;&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Configuration
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defgroup&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;publish&lt;/span&gt; nil
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Personal static blog generator.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:group&lt;/span&gt; &apos;tools&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-site-identity_4e2026237edc&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;site-identity_4e2026237edc&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;4.2.&lt;/span&gt; Site identity&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-site-identity_4e2026237edc&quot;&gt;
&lt;p&gt;
these three are the things most likely to change if someone else picks
up this script and uses it for their own site.  (idk why anyone would
want my shitty code tho)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defcustom&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;publish-site-url&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;https://coopi.neocities.org&quot;&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Base URL of the site, without trailing slash.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:type&lt;/span&gt; &apos;string
  &lt;span class=&quot;org-builtin&quot;&gt;:group&lt;/span&gt; &apos;publish&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defcustom&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;publish-site-title&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;coopi&apos;s corner of the web!&quot;&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Title used in the Atom feed and HTML head.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:type&lt;/span&gt; &apos;string
  &lt;span class=&quot;org-builtin&quot;&gt;:group&lt;/span&gt; &apos;publish&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defcustom&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;publish-site-author&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;coopi&quot;&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Author name used in Atom feed entries.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:type&lt;/span&gt; &apos;string
  &lt;span class=&quot;org-builtin&quot;&gt;:group&lt;/span&gt; &apos;publish&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-stylesheet_d77a1bc357f2&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;stylesheet_d77a1bc357f2&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;4.3.&lt;/span&gt; Stylesheet&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-stylesheet_d77a1bc357f2&quot;&gt;
&lt;p&gt;
this one is a bit fancy.  it accepts three different shapes:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;code&gt;nil&lt;/code&gt; — no stylesheet at all&lt;/li&gt;
&lt;li&gt;a string like &lt;code&gt;&quot;style.css&quot;&lt;/code&gt; — a local file, resolved relative to the
&lt;code&gt;org/&lt;/code&gt; directory, copied verbatim to &lt;code&gt;public/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a cons cell &lt;code&gt;(url . sri-hash)&lt;/code&gt; — an external stylesheet with
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity&quot;&gt;Subresource Integrity&lt;/a&gt;, so the browser can verify it wasn&apos;t tampered
with&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I&apos;m currently using a local &lt;code&gt;style.css&lt;/code&gt;.  the SRI option is there for
external stylesheets — and note that if you use the cons cell form,
the SRI hash is &lt;b&gt;mandatory&lt;/b&gt;, not optional.  this is intentional!!  if
you&apos;re loading something from a CDN you should be verifying it.  im
not going to make it easy for you not to.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defcustom&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;publish-stylesheet&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;style.css&quot;&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;The stylesheet used on every page.

This can be one of the following options: nil, which means no stylesheet
link is emitted; a string, which should be the path to a local CSS file
relative to the project root (the file must reside under the `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;org/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;
directory so it can be copied to `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;public/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;); or a cons cell (URL
. SRI-HASH), which specifies an external stylesheet loaded with
Subresource Integrity.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:type&lt;/span&gt; &apos;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;choice &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;const &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;None&quot;&lt;/span&gt; nil&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;string &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Local file (relative to project root)&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;cons &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;External URL with SRI&quot;&lt;/span&gt;
                       &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;string &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;URL&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;string &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;SRI hash&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:group&lt;/span&gt; &apos;publish&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-scripts_e3357bfb04d1&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;scripts_e3357bfb04d1&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;4.4.&lt;/span&gt; Scripts&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-scripts_e3357bfb04d1&quot;&gt;
&lt;p&gt;
same idea as the stylesheet but a list, because you might want
multiple scripts.  each entry is either a local path or a
&lt;code&gt;(url . sri-hash)&lt;/code&gt; cons.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defcustom&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;publish-scripts&lt;/span&gt; nil
  &lt;span class=&quot;org-doc&quot;&gt;&quot;List of scripts to include on every page.

Each element is either a string (a path to a local JS file relative to
the `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;org/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos; directory) or a cons cell of the form (URL . SRI-HASH) for an
external script loaded with Subresource Integrity.  Scripts are emitted
in list order, just before the closing head content.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:type&lt;/span&gt; &apos;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;repeat &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;choice &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;string &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Local file (relative to org/ directory)&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;cons &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;External URL with SRI&quot;&lt;/span&gt;
                               &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;string &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;URL&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
                               &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;string &lt;span class=&quot;org-builtin&quot;&gt;:tag&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;SRI hash&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-builtin&quot;&gt;:group&lt;/span&gt; &apos;publish&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I discover scripts from a &lt;code&gt;org/scripts/&lt;/code&gt; directory and add them to the
list automatically.  since all my scripts live there, I just evaluate
this once whenever I add a new one:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;dolist&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;f &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;directory-files &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;expand-file-name &lt;span class=&quot;org-string&quot;&gt;&quot;scripts/&quot;&lt;/span&gt; publish--org-dir&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt; nil &lt;span class=&quot;org-string&quot;&gt;&quot;\\.js$&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;add-to-list &apos;publish-scripts &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;concat &lt;span class=&quot;org-string&quot;&gt;&quot;scripts/&quot;&lt;/span&gt; f&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt; t&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
(this doesn&apos;t go into &lt;code&gt;publish.el&lt;/code&gt;.  it&apos;s a little snippet I evaluate
interactively when needed, not something that runs automatically.)
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-hooks_6d118b880f7d&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;hooks_6d118b880f7d&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;5.&lt;/span&gt; Hooks&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-hooks_6d118b880f7d&quot;&gt;
&lt;p&gt;
standard emacs hook variables.  nothing is registered here by default
— these are just the slots where you&apos;d hang your own code if you
wanted to, say, minify CSS after a build, or ping a webhook after a
deploy, or play a victory sound effect.  (I have considered the
victory sound effect.)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Hooks
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;defvar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;&lt;span class=&quot;org-elisp-defvar&quot;&gt;publish-before-build-hook&lt;/span&gt;&lt;/span&gt; nil
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Hook run before exporting Org files.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;defvar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;&lt;span class=&quot;org-elisp-defvar&quot;&gt;publish-after-build-hook&lt;/span&gt;&lt;/span&gt; nil
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Hook run after exporting Org files.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;defvar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;&lt;span class=&quot;org-elisp-defvar&quot;&gt;publish-before-deploy-hook&lt;/span&gt;&lt;/span&gt; nil
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Hook run before uploading files to the host.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;defvar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;&lt;span class=&quot;org-elisp-defvar&quot;&gt;publish-after-deploy-hook&lt;/span&gt;&lt;/span&gt; nil
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Hook run after uploading files to the host.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-paths_e24f875105bf&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;paths_e24f875105bf&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;6.&lt;/span&gt; Paths&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-paths_e24f875105bf&quot;&gt;
&lt;p&gt;
three path variables that everything else derives from.  the key one
is &lt;code&gt;publish--root&lt;/code&gt;: it figures out where &lt;b&gt;this file&lt;/b&gt; lives, regardless of
what the working directory is when it gets loaded.  no more &quot;it worked
on my machine&quot; nonsense.
&lt;/p&gt;

&lt;p&gt;
the double-dash convention (&lt;code&gt;publish--root&lt;/code&gt; vs &lt;code&gt;publish-root&lt;/code&gt;) is emacs
lisp&apos;s way of marking something as private to the package.  the
language doesn&apos;t enforce it — it&apos;s purely a naming convention — but
everyone follows it, and it&apos;s a useful signal that you&apos;re not supposed
to touch these from outside.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Paths
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;defvar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;&lt;span class=&quot;org-elisp-defvar&quot;&gt;publish--root&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;file-name-directory&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;or&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;load-file-name&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;buffer-file-name&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;default-directory&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Project root directory.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;defvar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;&lt;span class=&quot;org-elisp-defvar&quot;&gt;publish--org-dir&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;org/&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--root&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Directory containing Org source files.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;defvar&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;&lt;span class=&quot;org-elisp-defvar&quot;&gt;publish--pub-dir&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;public/&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--root&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Directory where exported HTML is written.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-draft-support_8102c0b56d78&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;draft-support_8102c0b56d78&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;7.&lt;/span&gt; Draft support&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-draft-support_8102c0b56d78&quot;&gt;
&lt;p&gt;
posts with &lt;code&gt;#+DRAFT: t&lt;/code&gt; at the top should be invisible everywhere: not
exported, not in the index, not in the feed.  &lt;code&gt;org-collect-keywords&lt;/code&gt;
reads the file&apos;s keyword metadata without doing a full parse, which is
fast enough to call on every single file without slowing everything to
a crawl.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Draft support
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--draft-p&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return non-nil if FILENAME contains #+DRAFT: t.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;keywords&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-collect-keywords&lt;/span&gt; &apos;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;DRAFT&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt; nil &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;assoc&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;DRAFT&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--publish-unless-draft&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;plist&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;pub-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Like `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;org-html-publish-to-html&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;, but skip files with #+DRAFT: t.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;if&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--draft-p&lt;/span&gt; filename&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot; SKIP (draft) %s&quot;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;file-name-nondirectory&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-html-publish-to-html&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;plist&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;pub-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-html-export-settings_004f3673c547&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;html-export-settings_004f3673c547&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;8.&lt;/span&gt; HTML export settings&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-html-export-settings_004f3673c547&quot;&gt;
&lt;p&gt;
these &lt;code&gt;setq&lt;/code&gt; calls configure the global org-html exporter.  let me call
out the interesting ones:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;code&gt;org-html-html5-fancy&lt;/code&gt; enables semantic HTML5 elements (&lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;,
&lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;, etc.) instead of plain &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; soup.  more meaningful markup
for basically free!!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;org-html-head-include-scripts&lt;/code&gt; and
&lt;code&gt;org-html-head-include-default-style&lt;/code&gt; are both &lt;code&gt;nil&lt;/code&gt; because I&apos;m
supplying my own CSS and do NOT want org&apos;s default stylesheet
leaking through.  (it&apos;s not bad per se — it&apos;s just extremely
minimal, basically bare bones, and I have opinions about how things
should look.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;org-html-htmlize-output-type &apos;css&lt;/code&gt; means syntax-highlighted source
blocks get CSS classes instead of inline &lt;code&gt;style&lt;/code&gt; attributes, so my
stylesheet controls the colours rather than having them hardcoded
everywhere&lt;/li&gt;
&lt;li&gt;&lt;code&gt;org-html-divs&lt;/code&gt; is the spicy one — it remaps the
preamble/content/postamble wrappers to &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;, and
&lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; respectively.  more semantic, better for accessibility, and
WAY nicer to target with CSS selectors&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;HTML export settings
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;setq&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-doctype&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;html5&quot;&lt;/span&gt;
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-html5-fancy&lt;/span&gt; t
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-head-include-scripts&lt;/span&gt; nil
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-head-include-default-style&lt;/span&gt; nil
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-htmlize-output-type&lt;/span&gt; &apos;css
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-validation-link&lt;/span&gt; nil
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-export-with-toc&lt;/span&gt; nil
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-export-with-section-numbers&lt;/span&gt; nil
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-self-link-headlines&lt;/span&gt; t
      &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-html-divs&lt;/span&gt; &apos;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;preamble  &lt;span class=&quot;org-string&quot;&gt;&quot;nav&quot;&lt;/span&gt;     &lt;span class=&quot;org-string&quot;&gt;&quot;preamble&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;content   &lt;span class=&quot;org-string&quot;&gt;&quot;article&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;postamble &lt;span class=&quot;org-string&quot;&gt;&quot;footer&quot;&lt;/span&gt;  &lt;span class=&quot;org-string&quot;&gt;&quot;postamble&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-head-fragment-helpers_55faa66f5271&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;head-fragment-helpers_55faa66f5271&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;8.1.&lt;/span&gt; Head fragment helpers&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-head-fragment-helpers_55faa66f5271&quot;&gt;
&lt;p&gt;
&lt;code&gt;publish--stylesheet-link&lt;/code&gt; and &lt;code&gt;publish--script-tags&lt;/code&gt; just turn the
customization variables into HTML strings.  boring but necessary —
someone has to do the string formatting.
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;publish--html-head&lt;/code&gt; assembles the full &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; fragment that gets
injected into every exported page.  it also sticks a &lt;code&gt;&amp;lt;link rel​=​&quot;me&quot;&amp;gt;&lt;/code&gt;
pointing at the site root in there, which is how &lt;a href=&quot;https://indieweb.org/rel-me&quot;&gt;IndieAuth rel=me
verification&lt;/a&gt; works.  (tiny detail, but I love it.)
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--stylesheet-link&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return the &amp;lt;link&amp;gt; tag for `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;publish-stylesheet&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;, or an empty string.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;cond&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-stylesheet&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;stringp&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-stylesheet&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;link rel=\&quot;stylesheet\&quot; href=\&quot;/%s\&quot;&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-stylesheet&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;consp&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-stylesheet&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;link rel=\&quot;stylesheet\&quot; href=\&quot;%s\&quot; integrity=\&quot;%s\&quot; crossorigin=\&quot;anonymous\&quot;&amp;gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-stylesheet&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-stylesheet&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--script-tags&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return &amp;lt;script&amp;gt; tags for every entry in `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;publish-scripts&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;mapconcat&lt;/span&gt;
   &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;cond&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;stringp&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;script src=\&quot;/%s\&quot;&amp;gt;&amp;lt;/script&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;consp&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;script src=\&quot;%s\&quot; integrity=\&quot;%s\&quot; crossorigin=\&quot;anonymous\&quot;&amp;gt;&amp;lt;/script&amp;gt;&quot;&lt;/span&gt;
               &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-scripts&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--html-head&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return the &amp;lt;head&amp;gt; fragment for every page.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;scripts&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--script-tags&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;%s%s
&amp;lt;link rel=\&quot;me\&quot; href=\&quot;%s\&quot;&amp;gt;
&amp;lt;meta name=\&quot;generator\&quot; content=\&quot;Org-mode\&quot;&amp;gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--stylesheet-link&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;if&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;string-empty-p&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;scripts&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;scripts&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-site-url&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-sitemap-the-post-index_c0ff1a7d4b22&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;sitemap-the-post-index_c0ff1a7d4b22&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;9.&lt;/span&gt; Sitemap (the post index)&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-sitemap-the-post-index_c0ff1a7d4b22&quot;&gt;
&lt;p&gt;
&lt;code&gt;ox-publish&lt;/code&gt;&apos;s built-in sitemap feature generates a &lt;code&gt;posts/index.org&lt;/code&gt;
automatically from your posts directory.  (it&apos;s not a sitemap in the
XML sense — it&apos;s literally just an org file with a list of links,
which then gets exported to HTML like everything else.  I love a good
reuse of existing infrastructure.)
&lt;/p&gt;

&lt;p&gt;
I customize two things:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;code&gt;publish--sitemap-entry&lt;/code&gt; — controls how each post appears in the
list.  I format them as &lt;code&gt;YYYY-MM-DD — [[link][Title]]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;publish--sitemap-format&lt;/code&gt; — controls the overall structure of the
index file.  I filter out draft entries here — and here&apos;s the fun
part: they arrive as the literal &lt;b&gt;string&lt;/b&gt; &lt;code&gt;&quot;nil&quot;&lt;/code&gt;​.  yes, the &lt;i&gt;string&lt;/i&gt;
&lt;code&gt;&quot;nil&quot;&lt;/code&gt;​, not the value &lt;code&gt;nil&lt;/code&gt;.  that&apos;s what org-publish gives you when
&lt;code&gt;publish--sitemap-entry&lt;/code&gt; returns nil.  I love elisp.  I hate elisp.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
there&apos;s also &lt;code&gt;publish--ensure-sitemap-placeholder&lt;/code&gt; which creates an
empty &lt;code&gt;posts/index.org&lt;/code&gt; if it doesn&apos;t exist yet, because org-publish
will error out on a fresh clone where that file is missing.  the kind
of tiny papercut that takes an hour to debug and two lines to fix.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Sitemap (auto-generated post index)
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--ensure-sitemap-placeholder&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;_plist&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Create an empty posts/index.org if it does not exist.
Prevents `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;org-publish&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos; from erroring on the first build.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;posts/index.org&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--org-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;file-exists-p&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;make-empty-file&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Created placeholder %s&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--sitemap-entry&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;_style&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Format ENTRY as \&quot;YYYY-MM-DD &amp;#8212; Title\&quot;.  Skip directories and drafts.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;directory-name-p&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;abs&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:base-directory&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--draft-p&lt;/span&gt; abs&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;%s &amp;#8212; [[file:%s][%s]]&quot;&lt;/span&gt;
                &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format-time-string&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;%Y-%m-%d&quot;&lt;/span&gt;
                                    &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-publish-find-date&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt;
                &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-publish-find-title&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--sitemap-format&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Build sitemap Org string from TITLE and LIST, filtering out drafts.
Drafts arrive as the literal string \&quot;nil\&quot; from org-publish.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;entries&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;seq-remove&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;equal&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;nil&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;cdr&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;#+TITLE: &quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n#+OPTIONS: title:t\n\n&quot;&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;if&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entries&lt;/span&gt;
                &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-list-to-org&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;org-string&quot;&gt;&quot;(No posts yet.)\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-atom-feed_08319c4136d9&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;atom-feed_08319c4136d9&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;10.&lt;/span&gt; Atom feed&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-atom-feed_08319c4136d9&quot;&gt;
&lt;p&gt;
this is where &lt;a href=&quot;https://codeberg.org/coopi/emacs-ox-atom&quot;&gt;emacs-ox-atom&lt;/a&gt; comes in!!  &lt;code&gt;org-atom-write-feed&lt;/code&gt; takes a
list of entry plists and serializes them into a valid Atom 1.0 XML
file.  &lt;code&gt;org-atom-entries-from-files&lt;/code&gt; does the scanning — it reads each
post&apos;s &lt;code&gt;#+TITLE&lt;/code&gt;, &lt;code&gt;#+DATE&lt;/code&gt;, &lt;code&gt;#+DESCRIPTION&lt;/code&gt;, etc. and builds the entry data
from those.
&lt;/p&gt;

&lt;p&gt;
the function is registered as a &lt;code&gt;:completion-function&lt;/code&gt; on the posts
project, so it runs automatically &lt;b&gt;after&lt;/b&gt; all posts have been exported
to HTML.  that ordering matters: &lt;code&gt;org-atom-entries-from-files&lt;/code&gt; reads the
HTML output to populate the &lt;code&gt;&amp;lt;content&amp;gt;&lt;/code&gt; elements, so the HTML has to
exist first.  get the ordering wrong and you get an empty feed.  ask
me how I know.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Atom feed
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--generate-atom-feed&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-type&quot;&gt;&lt;span class=&quot;org-elisp-ampersand&quot;&gt;&amp;amp;rest&lt;/span&gt;&lt;/span&gt; _&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Write Atom 1.0 feed to public/feed.xml via ox-atom.
Called as a :completion-function after the posts project is exported.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let*&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;posts-dir&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;posts/&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--org-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;html-dir&lt;/span&gt;  &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;posts/&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--pub-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;seq-remove&lt;/span&gt;
                 &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;string=&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;file-name-nondirectory&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;index.org&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;directory-files&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;posts-dir&lt;/span&gt; t &lt;span class=&quot;org-string&quot;&gt;&quot;\\.org$&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-atom-write-feed&lt;/span&gt;
     &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:file&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;feed.xml&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--pub-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:title&lt;/span&gt;&lt;/span&gt;   &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-site-title&lt;/span&gt;
     &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:id&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-site-url&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:link&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-site-url&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:self&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-site-url&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;/feed.xml&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:authors&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:name&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-site-author&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:entries&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-atom-entries-from-files&lt;/span&gt;
               &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;files&lt;/span&gt;
               &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:base-url&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-site-url&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;/posts/&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:html-dir&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;html-dir&lt;/span&gt;
               &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:exclude-drafts&lt;/span&gt;&lt;/span&gt; t&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-project-definition_700a05459683&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;project-definition_700a05459683&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;11.&lt;/span&gt; Project definition&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-project-definition_700a05459683&quot;&gt;
&lt;p&gt;
okay, HERE we go!!  &lt;code&gt;org-publish-project-alist&lt;/code&gt; is the central registry
that tells &lt;code&gt;ox-publish&lt;/code&gt; what to build and how.  I define four projects:
&lt;/p&gt;

&lt;dl class=&quot;org-dl&quot;&gt;
&lt;dt&gt;pages&lt;/dt&gt;&lt;dd&gt;top-level &lt;code&gt;.org&lt;/code&gt; files (the homepage, any standalone pages)&lt;/dd&gt;
&lt;dt&gt;(no term)&lt;/dt&gt;&lt;dd&gt;&lt;b&gt;posts&lt;/b&gt; — the &lt;code&gt;posts/&lt;/code&gt; subdirectory, with the sitemap and Atom feed
hooked in&lt;/dd&gt;
&lt;dt&gt;static&lt;/dt&gt;&lt;dd&gt;non-org assets (CSS, images, JS, &amp;hellip;) copied verbatim&lt;/dd&gt;
&lt;dt&gt;site&lt;/dt&gt;&lt;dd&gt;a meta-project that builds all three with a single command&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;
the &lt;code&gt;:base-extension&lt;/code&gt; for the static project is an enormous &lt;code&gt;rx&lt;/code&gt;
expression — that&apos;s every single file type Neocities allows on the
&lt;a href=&quot;https://neocities.org/site_files/allowed_types&quot;&gt;free tier&lt;/a&gt;.  unfortunately, im too broke to be a supporter.  so that
list is exactly what I&apos;ve got to work with, and I copy all of it
verbatim.
&lt;/p&gt;

&lt;p&gt;
the preamble and postamble are little HTML snippets — the nav bar and
footer — injected into every page.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Publish project definition
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--setup-projects&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Configure `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;org-publish-project-alist&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos; for this site.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;head&lt;/span&gt;     &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--html-head&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;preamble&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt;
                   &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;a href=\&quot;/\&quot;&amp;gt;Home&amp;lt;/a&amp;gt;\n&quot;&lt;/span&gt;
                   &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;a href=\&quot;/posts/\&quot;&amp;gt;Posts&amp;lt;/a&amp;gt;\n&quot;&lt;/span&gt;
                   &lt;span class=&quot;org-string&quot;&gt;&quot;&amp;lt;a href=\&quot;/feed.xml\&quot;&amp;gt;Feed&amp;lt;/a&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;postamble&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Made with Org-mode &amp;amp;middot; %C&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;setq&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;org-publish-project-alist&lt;/span&gt;
          `&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;pages&quot;&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:base-directory&lt;/span&gt;       ,publish--org-dir
             &lt;span class=&quot;org-builtin&quot;&gt;:base-extension&lt;/span&gt;       &lt;span class=&quot;org-string&quot;&gt;&quot;org&quot;&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:recursive&lt;/span&gt;            nil
             &lt;span class=&quot;org-builtin&quot;&gt;:publishing-directory&lt;/span&gt; ,publish--pub-dir
             &lt;span class=&quot;org-builtin&quot;&gt;:publishing-function&lt;/span&gt;  org-html-publish-to-html
             &lt;span class=&quot;org-builtin&quot;&gt;:html-head&lt;/span&gt;            ,head
             &lt;span class=&quot;org-builtin&quot;&gt;:html-preamble&lt;/span&gt;        ,preamble
             &lt;span class=&quot;org-builtin&quot;&gt;:html-postamble&lt;/span&gt;       ,postamble&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;posts&quot;&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:base-directory&lt;/span&gt;       ,&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;expand-file-name &lt;span class=&quot;org-string&quot;&gt;&quot;posts/&quot;&lt;/span&gt; publish--org-dir&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:base-extension&lt;/span&gt;       &lt;span class=&quot;org-string&quot;&gt;&quot;org&quot;&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:recursive&lt;/span&gt;            nil
             &lt;span class=&quot;org-builtin&quot;&gt;:publishing-directory&lt;/span&gt; ,&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;expand-file-name &lt;span class=&quot;org-string&quot;&gt;&quot;posts/&quot;&lt;/span&gt; publish--pub-dir&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:publishing-function&lt;/span&gt;  publish--publish-unless-draft
             &lt;span class=&quot;org-builtin&quot;&gt;:html-head&lt;/span&gt;            ,head
             &lt;span class=&quot;org-builtin&quot;&gt;:html-preamble&lt;/span&gt;        ,preamble
             &lt;span class=&quot;org-builtin&quot;&gt;:html-postamble&lt;/span&gt;       ,postamble
             &lt;span class=&quot;org-builtin&quot;&gt;:preparation-function&lt;/span&gt; publish--ensure-sitemap-placeholder
             &lt;span class=&quot;org-builtin&quot;&gt;:auto-sitemap&lt;/span&gt;         t
             &lt;span class=&quot;org-builtin&quot;&gt;:sitemap-filename&lt;/span&gt;     &lt;span class=&quot;org-string&quot;&gt;&quot;index.org&quot;&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:sitemap-title&lt;/span&gt;        &lt;span class=&quot;org-string&quot;&gt;&quot;Posts&quot;&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:sitemap-sort-files&lt;/span&gt;   anti-chronologically
             &lt;span class=&quot;org-builtin&quot;&gt;:sitemap-format-entry&lt;/span&gt; publish--sitemap-entry
             &lt;span class=&quot;org-builtin&quot;&gt;:sitemap-function&lt;/span&gt;     publish--sitemap-format
             &lt;span class=&quot;org-builtin&quot;&gt;:completion-function&lt;/span&gt;  publish--generate-atom-feed&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;static&quot;&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:base-directory&lt;/span&gt;       ,publish--org-dir
             &lt;span class=&quot;org-builtin&quot;&gt;:base-extension&lt;/span&gt;       ,&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;rx&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;apng&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;asc&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;atom&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;avif&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;bin&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;cjs&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;css&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;csv&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;dae&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;eot&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;epub&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;geojson&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;gif&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;glb&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;glsl&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;gltf&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;gpg&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;htm&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;html&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;ico&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;jpeg&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;jpg&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;js&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;json&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;jxl&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;key&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;kml&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;knowl&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;less&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;manifest&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;map&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;markdown&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;md&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;mf&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;mid&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;midi&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;mjs&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;mtl&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;obj&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;opml&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;osdx&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;otf&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;pdf&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;pgp&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;pls&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;png&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;py&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;rdf&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;resolveHandle&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;rss&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;sass&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;scss&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;sf2&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;svg&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;toml&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;ts&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;tsv&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;ttf&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;txt&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;webapp&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;webmanifest&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;webp&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;woff&quot;&lt;/span&gt;
                                            &lt;span class=&quot;org-string&quot;&gt;&quot;woff2&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;xcf&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;xml&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;yaml&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;yml&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-builtin&quot;&gt;:recursive&lt;/span&gt;            t
             &lt;span class=&quot;org-builtin&quot;&gt;:publishing-directory&lt;/span&gt; ,publish--pub-dir
             &lt;span class=&quot;org-builtin&quot;&gt;:publishing-function&lt;/span&gt;  org-publish-attachment&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;site&quot;&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;:components&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;&quot;pages&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;posts&quot;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;static&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-deployment_c70d504a533a&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;deployment_c70d504a533a&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;12.&lt;/span&gt; Deployment&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-deployment_c70d504a533a&quot;&gt;
&lt;p&gt;
now for the REALLY fun part: actually getting the site onto
Neocities!!
&lt;/p&gt;

&lt;p&gt;
Neocities has a &lt;a href=&quot;https://neocities.org/api&quot;&gt;REST API&lt;/a&gt;.  my &lt;a href=&quot;https://codeberg.org/coopi/emacs-neocities&quot;&gt;emacs-neocities&lt;/a&gt; package wraps it.  the
deployment workflow is:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;list all files in &lt;code&gt;public/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;fetch the live file listing from Neocities (including SHA-1 hashes)&lt;/li&gt;
&lt;li&gt;compare: find what&apos;s new, what&apos;s changed, what&apos;s been deleted&lt;/li&gt;
&lt;li&gt;show a diff, ask for confirmation&lt;/li&gt;
&lt;li&gt;upload changed files in batches of 20&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
the batching matters — Neocities&apos;s API has limits on how much you can
shove into one request, so I chunk it up.  20 at a time feels good.
&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-collecting-local-files_6d54ff1ccec5&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;collecting-local-files_6d54ff1ccec5&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;12.1.&lt;/span&gt; Collecting local files&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-collecting-local-files_6d54ff1ccec5&quot;&gt;
&lt;p&gt;
&lt;code&gt;publish--collect-files&lt;/code&gt; returns an alist of &lt;code&gt;(remote-path . local-path)&lt;/code&gt;
pairs.  the remote path is the relative path under &lt;code&gt;public/&lt;/code&gt; with a
leading slash, to match the format Neocities uses in its API
responses.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Deployment
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--collect-files&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return an alist of (REMOTE-PATH . LOCAL-PATH) for `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;publish--pub-dir&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;file-name-as-directory&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--pub-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;mapcar&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;file-relative-name&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;directory-files-recursively&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--pub-dir&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;.*&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-diffing-against-neocities_615a0d910871&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;diffing-against-neocities_615a0d910871&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;12.2.&lt;/span&gt; Diffing against Neocities&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-diffing-against-neocities_615a0d910871&quot;&gt;
&lt;p&gt;
&lt;code&gt;publish--sha1-file&lt;/code&gt; computes the SHA-1 of a local file.
&lt;code&gt;publish--remote-index&lt;/code&gt; fetches the Neocities file listing and dumps it
into a hash table keyed by remote path.  then &lt;code&gt;publish--compute-diff&lt;/code&gt;
walks the local files, compares hashes, and returns a plist with three
keys: &lt;code&gt;:new&lt;/code&gt;, &lt;code&gt;:modified&lt;/code&gt;, &lt;code&gt;:deleted&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
this means deploys are fast even if you have a lot of files — you only
upload what actually changed.  no more &quot;upload everything and hope&quot;
vibes.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Diff support
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--sha1-file&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return the lowercase hex SHA-1 digest of the file at PATH.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;with-temp-buffer&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;insert-file-contents-literally&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;secure-hash&lt;/span&gt; &apos;sha1 &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;current-buffer&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--remote-index&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Fetch the Neocities file listing and return a hash table.
Keys are remote path strings (e.g. \&quot;/index.html\&quot;).
Values are SHA-1 hex strings.  Directories are excluded.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;make-hash-table&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:test&lt;/span&gt;&lt;/span&gt; #&apos;&lt;span class=&quot;org-elisp-function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;neocities-response-files&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;neocities-list&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;seq-doseq&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;entry files&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;eq &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;alist-get &apos;is_directory entry&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt; t&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;alist-get &apos;path  entry&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;sha1 &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;alist-get &apos;sha1_hash entry&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;and&lt;/span&gt; path sha1&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;puthash path sha1 table&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--compute-diff&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Compare local public/ files against the live Neocities site.
Returns a plist with three keys:
  :new      &amp;#8212; list of remote paths that do not exist on the site yet
  :modified &amp;#8212; list of remote paths whose SHA-1 differs
  :deleted  &amp;#8212; list of remote paths present on the site but not locally&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;file-directory-p&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish--pub-dir&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-warning&quot;&gt;&lt;span class=&quot;org-elisp-non-local-exit&quot;&gt;user-error&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;public/ does not exist &amp;#8212; run publish-build first&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Fetching remote file listing from Neocities...&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let*&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;remote&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--remote-index&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;local&lt;/span&gt;  &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--collect-files&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;seen&lt;/span&gt;   &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;make-hash-table&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:test&lt;/span&gt;&lt;/span&gt; #&apos;&lt;span class=&quot;org-elisp-function&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;modified&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;deleted&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Classify each local file.
&lt;/span&gt;    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;dolist&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;pair local&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;rel         &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;car pair&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;abs         &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;cdr pair&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;remote-path &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;concat &lt;span class=&quot;org-string&quot;&gt;&quot;/&quot;&lt;/span&gt; rel&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;remote-sha1 &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;gethash remote-path remote&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;puthash remote-path t seen&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;cond&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;null remote-sha1&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;push&lt;/span&gt; remote-path new&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;not &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;string= remote-sha1 &lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;(&lt;/span&gt;publish--sha1-file abs&lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;push&lt;/span&gt; remote-path modified&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Any remote path not seen locally is a candidate for deletion.
&lt;/span&gt;    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;maphash&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;_sha1&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;gethash&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;seen&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;push&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;remote&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:new&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;new&lt;/span&gt;      #&apos;&lt;span class=&quot;org-elisp-function&quot;&gt;string&amp;lt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:modified&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;modified&lt;/span&gt; #&apos;&lt;span class=&quot;org-elisp-function&quot;&gt;string&amp;lt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:deleted&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt;  #&apos;&lt;span class=&quot;org-elisp-function&quot;&gt;string&amp;lt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-displaying-the-diff_4c089ddf231e&quot; class=&quot;outline-3&quot;&gt;
&lt;h3 id=&quot;displaying-the-diff_4c089ddf231e&quot;&gt;&lt;span class=&quot;section-number-3&quot;&gt;12.3.&lt;/span&gt; Displaying the diff&lt;/h3&gt;
&lt;div class=&quot;outline-text-3&quot; id=&quot;text-displaying-the-diff_4c089ddf231e&quot;&gt;
&lt;p&gt;
&lt;code&gt;publish--format-diff&lt;/code&gt; turns the plist into a human-readable string.
&lt;code&gt;publish--show-diff-buffer&lt;/code&gt; pops it up in a &lt;code&gt;*publish-diff*&lt;/code&gt; buffer using
&lt;code&gt;special-mode&lt;/code&gt; — that&apos;s a built-in minor mode that makes the buffer
read-only and binds &lt;code&gt;q&lt;/code&gt; to quit.  perfect for &quot;show something, user
reads it, user presses &lt;code&gt;q&lt;/code&gt;&quot;.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--format-diff&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;diff&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Return a human-readable string summarising DIFF (as from `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;publish--compute-diff&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos;).&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;new&lt;/span&gt;      &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:new&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;modified&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:modified&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;deleted&lt;/span&gt;  &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:deleted&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;lines&lt;/span&gt; nil&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;if&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;and&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-string&quot;&gt;&quot;No changes &amp;#8212; site is already up to date.&quot;&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;when&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;new&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;push&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;New (%d):\n%s&quot;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;mapconcat&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;  + &quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;when&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;modified&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;push&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Modified (%d):\n%s&quot;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;mapconcat&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;  ~ &quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;modified&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;when&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;push&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Deleted (%d):\n%s&quot;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;mapconcat&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;lambda&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;  - &quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-9&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;mapconcat&lt;/span&gt; #&apos;&lt;span class=&quot;org-elisp-function&quot;&gt;identity&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;nreverse&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish--show-diff-buffer&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;diff&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Pop up a *publish-diff* buffer displaying DIFF.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;get-buffer-create&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;*publish-diff*&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;with-current-buffer&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;buf&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-shadowing-variable&quot;&gt;inhibit-read-only&lt;/span&gt; t&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;erase-buffer&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;publish diff &amp;#8212; local public/ vs. live Neocities site\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;make-string&lt;/span&gt; 54 ?&amp;#9472;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--format-diff&lt;/span&gt; diff&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;special-mode&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;goto-char&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;point-min&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;display-buffer&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-entry-points_a53c07bf511e&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;entry-points_a53c07bf511e&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;13.&lt;/span&gt; Entry points&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-entry-points_a53c07bf511e&quot;&gt;
&lt;p&gt;
these are the interactive commands — the things you actually call from
&lt;code&gt;M-x&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;publish-build&lt;/code&gt; runs the full ox-publish pipeline.  &lt;code&gt;publish-build-force&lt;/code&gt;
is the same but nukes the timestamp cache first, forcing everything to
re-export even if nothing changed.  you want this when you&apos;ve tweaked
a stylesheet or nav template and need every page to pick up the new
&lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;publish-diff&lt;/code&gt; fetches the remote listing and shows you what would
change.  it does NOT upload anything.  purely informational.  I use
this constantly.
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;publish-deploy&lt;/code&gt; is the main event.  it runs the diff, shows it, asks
for confirmation, then uploads in batches.  with a prefix argument
(&lt;code&gt;C-u M-x publish-deploy&lt;/code&gt;) it skips the diff and goes straight to
uploading — for when you just want it done.
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;publish-build-and-deploy&lt;/code&gt; chains them.  one command, whole pipeline.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Entry points
&lt;/span&gt;
&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish-build&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-type&quot;&gt;&lt;span class=&quot;org-elisp-ampersand&quot;&gt;&amp;amp;optional&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Export Org files to public/.
With prefix argument FORCE, rebuild everything.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;interactive&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;P&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;run-hooks&lt;/span&gt; &apos;&lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-before-build-hook&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--setup-projects&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;org-publish-all&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Build complete.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;run-hooks&lt;/span&gt; &apos;&lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-after-build-hook&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish-build-force&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Export all Org files, ignoring the timestamp cache.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;interactive&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish-build&lt;/span&gt; t&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish-diff&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Show what would change if you deployed public/ to Neocities now.
Opens a *publish-diff* buffer with new, modified, and deleted files.
Does not upload anything.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;interactive&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;neocities-api-key&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;neocities-fetch-api-key&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--compute-diff&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--show-diff-buffer&lt;/span&gt; diff&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;diff&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish-deploy&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-type&quot;&gt;&lt;span class=&quot;org-elisp-ampersand&quot;&gt;&amp;amp;optional&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;skip-diff&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Upload public/ to Neocities, showing a diff and asking for confirmation first.
With prefix argument SKIP-DIFF, bypass the diff check and upload immediately
\(equivalent to the old behaviour).
Prompts for credentials if `&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&lt;span class=&quot;org-constant&quot;&gt;neocities-api-key&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-doc&quot;&gt;&apos; is nil.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;interactive&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;P&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;run-hooks&lt;/span&gt; &apos;&lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-before-deploy-hook&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;neocities-api-key&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;neocities-fetch-api-key&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;skip-diff&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let*&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;diff&lt;/span&gt;     &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--compute-diff&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;new&lt;/span&gt;      &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:new&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;modified&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:modified&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;deleted&lt;/span&gt;  &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;plist-get&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;org-builtin&quot;&gt;&lt;span class=&quot;org-elisp-constant&quot;&gt;:deleted&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;if&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;and&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;progn&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;publish-deploy: site is already up to date, nothing to upload.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;run-hooks&lt;/span&gt; &apos;&lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-after-deploy-hook&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;cl-return-from&lt;/span&gt;&lt;/span&gt; publish-deploy&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--show-diff-buffer&lt;/span&gt; diff&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;yes-or-no-p&lt;/span&gt;
                 &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Deploy %d new, %d modified, %d deleted file(s) to Neocities? &quot;&lt;/span&gt;
                         &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;deleted&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-8&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Deploy cancelled.&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;run-hooks&lt;/span&gt; &apos;&lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-after-deploy-hook&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;cl-return-from&lt;/span&gt;&lt;/span&gt; publish-deploy&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let*&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;files&lt;/span&gt;      &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish--collect-files&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;total&lt;/span&gt;      &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;batch-size&lt;/span&gt; 20&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;uploaded&lt;/span&gt;   0&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;unless&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;files&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-warning&quot;&gt;&lt;span class=&quot;org-elisp-non-local-exit&quot;&gt;user-error&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;public/ is empty &amp;#8212; run publish-build first&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Deploying %d files to Neocities...&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;while&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;files&lt;/span&gt;
      &lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;let*&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;batch&lt;/span&gt;    &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;seq-take&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;batch-size&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-binding-variable&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;neocities-upload&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;batch&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;setq&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;files&lt;/span&gt;    &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;seq-drop&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;batch-size&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;uploaded&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;uploaded&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;batch&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-7&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot; batch %d/%d &amp;#8594; %s&quot;&lt;/span&gt;
                 &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;uploaded&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;total&lt;/span&gt;
                 &lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;neocities-response-result&lt;/span&gt; &lt;span class=&quot;org-elisp-bound-variable&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-6&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-5&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-4&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-3&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;Deploy complete (%d files).&quot;&lt;/span&gt; &lt;span class=&quot;org-elisp-free-variable&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;run-hooks&lt;/span&gt; &apos;&lt;span class=&quot;org-elisp-free-variable&quot;&gt;publish-after-deploy-hook&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-macro&quot;&gt;defun&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;&lt;span class=&quot;org-elisp-defun&quot;&gt;publish-build-and-deploy&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-type&quot;&gt;&lt;span class=&quot;org-elisp-ampersand&quot;&gt;&amp;amp;optional&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-elisp-binding-variable&quot;&gt;force&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-doc&quot;&gt;&quot;Build the site, then deploy to Neocities.
With prefix argument FORCE, rebuild everything.&quot;&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-special-form&quot;&gt;interactive&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;P&quot;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish-build&lt;/span&gt; force&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-elisp-unknown-call&quot;&gt;publish-deploy&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-2&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-footer_7b02c0909541&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;footer_7b02c0909541&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;14.&lt;/span&gt; Footer&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-footer_7b02c0909541&quot;&gt;
&lt;p&gt;
every emacs lisp library ends with a &lt;code&gt;provide&lt;/code&gt; call and a comment
footer.  this is how &lt;code&gt;require&lt;/code&gt; knows what it loaded.  deeply unsexy.
completely essential.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-emacs-lisp&quot;&gt;&lt;code&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;&lt;span class=&quot;org-elisp-function&quot;&gt;provide&lt;/span&gt;&lt;/span&gt; &apos;&lt;span class=&quot;org-constant&quot;&gt;&lt;span class=&quot;org-elisp-feature&quot;&gt;publish&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;org-rainbow-delimiters-depth-1&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;;;; &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;publish.el ends her&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;e&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-that-s-it_620e193536c8&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;that-s-it_620e193536c8&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;15.&lt;/span&gt; That&apos;s it!!&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-that-s-it_620e193536c8&quot;&gt;
&lt;p&gt;
THAT&apos;S THE WHOLE THING!!  ~500 lines!!  a static site generator, an
Atom feed, and a deployment pipeline, all wired together in elisp, all
tangled out of this very post!!
&lt;/p&gt;

&lt;p&gt;
if you want to use this yourself (u shouldnt, it&apos;s extremely
opinionated, but okay):
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;grab &lt;a href=&quot;https://codeberg.org/coopi/emacs-ox-atom&quot;&gt;emacs-ox-atom&lt;/a&gt; and &lt;a href=&quot;https://codeberg.org/coopi/emacs-neocities&quot;&gt;emacs-neocities&lt;/a&gt; and put them on your
&lt;code&gt;load-path&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;tangle this file with &lt;code&gt;M-x org-babel-tangle&lt;/code&gt; (or just download
&lt;code&gt;publish.el&lt;/code&gt; directly if you can&apos;t be bothered)&lt;/li&gt;
&lt;li&gt;set up the directory layout from the top of this post&lt;/li&gt;
&lt;li&gt;meow at the nearest cat (this is IMPORTANT)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-x load-file RET publish.el RET&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-x publish-build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;M-x publish-deploy&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
and yes!!  this post itself is being built and deployed using the very
script it describes.  the blog post IS the program, the program builds
the blog post, it&apos;s turtles all the way down.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</content></entry><entry><title type="text">Houston, we are online!</title><id>https://coopi.neocities.org/posts/hello-world.html</id><updated>2026-03-31T20:00:00Z</updated><published>2026-03-31T20:00:00Z</published><link href="https://coopi.neocities.org/posts/hello-world.html"/><summary type="text">First post — getting set up with Org-mode on Neocities. ADHD brain finally commits to something???</summary><content type="html">&lt;header&gt;
&lt;h1 class=&quot;title&quot;&gt;Houston, we are online!&lt;/h1&gt;
&lt;/header&gt;&lt;nav id=&quot;table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;div id=&quot;text-table-of-contents&quot; role=&quot;doc-toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#this-should-have-been-done-ages-ago_1c35f3876907&quot;&gt;1. this should have been done ages ago!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#how-did-we-get-here_a6dc9e3b266c&quot;&gt;2. how did we get here??&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#down-the-rabbit-hole_08b15499f41c&quot;&gt;3. down the rabbit hole&amp;hellip;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#emacs-side-the-quest-for-ox-publish-and-ox-rss_22979a866734&quot;&gt;4. emacs-side: the quest for &lt;code&gt;ox-publish&lt;/code&gt; and &lt;code&gt;ox-rss&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deployment-to-neocities_f56f20a01c26&quot;&gt;5. deployment to neocities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#so-how-does-everything-work_94c7f2f487fc&quot;&gt;6. so, how does everything work?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/nav&gt;
&lt;p&gt;
&amp;hellip;.hello?  is this thing on?  Hello, world!
&lt;/p&gt;

&lt;p&gt;
so, yeah!  this is my first post!  it&apos;s written inside emacs with org
mode.  very cool!!
&lt;/p&gt;
&lt;div id=&quot;outline-container-this-should-have-been-done-ages-ago_1c35f3876907&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;this-should-have-been-done-ages-ago_1c35f3876907&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;1.&lt;/span&gt; this should have been done ages ago!&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-this-should-have-been-done-ages-ago_1c35f3876907&quot;&gt;
&lt;p&gt;
according to the neocities stats, my site was apparently updated one
month ago.  what did this update bring, you may ask??  well, i had
just created my account and set up this generic placeholder:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-html&quot;&gt;&lt;code&gt;&amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;lang&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;en&quot;&lt;/span&gt;&amp;gt;
  &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;head&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;title&lt;/span&gt;&amp;gt;&lt;span class=&quot;org-underline&quot;&gt;&lt;span class=&quot;org-bold&quot;&gt;coopi&apos;s corner of the web!&lt;/span&gt;&lt;/span&gt;&amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;title&lt;/span&gt;&amp;gt;
  &amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;head&lt;/span&gt;&amp;gt;
  &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;body&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;h1&lt;/span&gt;&amp;gt;&lt;span class=&quot;org-underline&quot;&gt;&lt;span class=&quot;org-bold&quot;&gt;Welcome to my little haven!&lt;/span&gt;&lt;/span&gt;&amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;h1&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;./avatar.png&quot;&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;alt&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;coopi&apos;s Avatar&quot;&lt;/span&gt;&amp;gt;

    &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;div&lt;/span&gt;&amp;gt;
      &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;p&lt;/span&gt;&amp;gt;Unfortunately, there&apos;s nothing here; you came here before I had a chance to decorate it.&amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;p&lt;/span&gt;&amp;gt;
      &amp;lt;&lt;span class=&quot;org-function-name&quot;&gt;p&lt;/span&gt;&amp;gt;Feel free to come back later though: I can&apos;t wait to share more about my projects, interests, and more!&amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;p&lt;/span&gt;&amp;gt;
    &amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;div&lt;/span&gt;&amp;gt;
  &amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;body&lt;/span&gt;&amp;gt;
&amp;lt;/&lt;span class=&quot;org-function-name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;org-whitespace-missing-newline-at-eof&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&amp;hellip;and then abandoned the site.
&lt;/p&gt;

&lt;p&gt;
apparently, &lt;i&gt;a hundred people&lt;/i&gt; saw this boring page.  which is wild,
honestly.
&lt;/p&gt;

&lt;p&gt;
but then, ive now gotten randomly interested again, and here we are!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-how-did-we-get-here_a6dc9e3b266c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;how-did-we-get-here_a6dc9e3b266c&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;2.&lt;/span&gt; how did we get here??&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-how-did-we-get-here_a6dc9e3b266c&quot;&gt;
&lt;dl class=&quot;org-dl&quot;&gt;
&lt;dt&gt;&lt;b&gt;the original plan&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;use org mode for my site.  why? because i live
in emacs—email, notes, code, 3am thoughts—so blogging should too.
it&apos;s the &lt;i&gt;only&lt;/i&gt; way i function.&lt;/dd&gt;

&lt;dt&gt;&lt;b&gt;the problem&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;&lt;p&gt;
i didn&apos;t know where to start.  i knew org mode had
publishing capabilities, but not what they were.  and while there
are packages that make org blogging easy, i thought: why not use the
built-in stuff instead?
&lt;/p&gt;

&lt;p&gt;
i also wanted a syndication feed, which org mode supposedly
provided.
&lt;/p&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-down-the-rabbit-hole_08b15499f41c&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;down-the-rabbit-hole_08b15499f41c&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;3.&lt;/span&gt; down the rabbit hole&amp;hellip;&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-down-the-rabbit-hole_08b15499f41c&quot;&gt;
&lt;p&gt;
first, i needed styling.  org mode&apos;s default output is just plain
html.  super minimal.  basically what you&apos;d expect from someone who
took &lt;a href=&quot;https://motherfuckingwebsite.com/&quot;&gt;motherfuckingwebsite.com&lt;/a&gt; too seriously.
&lt;/p&gt;

&lt;p&gt;
i went on a hunt for pre-existing stylesheets—something minimal and
nice.  i found &lt;a href=&quot;https://edwardtufte.github.io/tufte-css/&quot;&gt;tufte css&lt;/a&gt;, designed by edward tufte—​&lt;i&gt;the&lt;/i&gt; edward tufte,
master of informational design.  it looked &lt;i&gt;perfect&lt;/i&gt;.  clean, minimal,
elegant.  but there was a catch: tufte&apos;s design uses classes;
org-mode&apos;s html export doesn&apos;t use them by default.  i &lt;i&gt;could&lt;/i&gt; fix that
with some elisp—org-mode is infinitely extensible after all—but that
seemed like more hassle than worth it.
&lt;/p&gt;

&lt;p&gt;
but i thought, &quot;maybe i can just adapt it.&quot; so i did.  my css isn&apos;t
perfect, but it&apos;s functional.  i basically took tufte&apos;s minimalism,
tweaked it to work with org-mode output, and added a few extras.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-emacs-side-the-quest-for-ox-publish-and-ox-rss_22979a866734&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;emacs-side-the-quest-for-ox-publish-and-ox-rss_22979a866734&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;4.&lt;/span&gt; emacs-side: the quest for &lt;code&gt;ox-publish&lt;/code&gt; and &lt;code&gt;ox-rss&lt;/code&gt;&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-emacs-side-the-quest-for-ox-publish-and-ox-rss_22979a866734&quot;&gt;
&lt;p&gt;
now that css was sorted, i turned to org-mode&apos;s &lt;code&gt;ox-publish&lt;/code&gt;.  the
built-in publishing tool that can:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;scan directories for &lt;code&gt;.org&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;export them to html&lt;/li&gt;
&lt;li&gt;cache timestamps (only re-exports changed files)&lt;/li&gt;
&lt;li&gt;copy static assets to output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
pretty solid! but then i checked on the rss feature.
&lt;/p&gt;

&lt;p&gt;
turns out, org-mode &lt;i&gt;used to&lt;/i&gt; provide &lt;code&gt;ox-rss&lt;/code&gt;, but it got split into its
own package and is barely maintained now.  at first i had been like,
&quot;okay, org-mode does rss—let me just use it.&quot; but after diving in, it
felt like a hassle.  i wasn&apos;t &lt;i&gt;feeling&lt;/i&gt; it.
&lt;/p&gt;

&lt;p&gt;
now, i have my preferences when it comes to syndication feed formats.
i like atom feeds more than rss feeds.  as ive told, &lt;code&gt;ox-rss&lt;/code&gt; just
didn&apos;t have the flair i was hoping for. so, my format preferences
combined with &lt;code&gt;ox-rss&lt;/code&gt;&apos;s dismal maintenance status, i figured i&apos;d just
make something that worked the way i wanted.  which is exactly what i
did: this website has an atom feed for u to follow!
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-deployment-to-neocities_f56f20a01c26&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;deployment-to-neocities_f56f20a01c26&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;5.&lt;/span&gt; deployment to neocities&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-deployment-to-neocities_f56f20a01c26&quot;&gt;
&lt;p&gt;
last thing i needed was deployment.  neocities has an api, so it was
pretty easy.  the approach for straightforward: &lt;code&gt;url.el&lt;/code&gt; for making
requests, my neocities api key for authentication, and boom—automated
uploads.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-so-how-does-everything-work_94c7f2f487fc&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;so-how-does-everything-work_94c7f2f487fc&quot;&gt;&lt;span class=&quot;section-number-2&quot;&gt;6.&lt;/span&gt; so, how does everything work?&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-so-how-does-everything-work_94c7f2f487fc&quot;&gt;
&lt;p&gt;
here&apos;s the breakdown:
&lt;/p&gt;

&lt;dl class=&quot;org-dl&quot;&gt;
&lt;dt&gt;&lt;b&gt;building the site&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;org-mode scans the &lt;code&gt;org/&lt;/code&gt; directory, looks for
&lt;code&gt;.org&lt;/code&gt; files, and exports them to &lt;code&gt;public/&lt;/code&gt; as html.  it also grabs
static assets (images, css) and sticks them there.&lt;/dd&gt;
&lt;dt&gt;&lt;b&gt;publishing&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;the site gets built in emacs, then pushed to
neocities via api call.  simple &lt;code&gt;url.el&lt;/code&gt; request with my credentials,
and boom, site is live.&lt;/dd&gt;
&lt;dt&gt;&lt;b&gt;syndication&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt;i wrote my own atom feed generator!!  it pulls from
the same &lt;code&gt;.org&lt;/code&gt; files, spits out the feed.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;
and yeah, i ended up writing a ~500 line &lt;code&gt;publish.el&lt;/code&gt; package. so much
for using &lt;code&gt;ox-publish&lt;/code&gt; and &lt;i&gt;not&lt;/i&gt; using a pipeline&amp;hellip;
&lt;/p&gt;

&lt;p&gt;
anyways, i&apos;ll upload the code &lt;i&gt;soon™&lt;/i&gt;, but it&apos;s staying private for now.
it&apos;s not clean enough yet, and i&apos;d rather release something i&apos;m proud
of.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</content></entry></feed>