Using org-publish
Table of Contents
Excerpt from config file
I use org-publish for my websites. This block has a lot going on:
- I set some default options for publishing projects.
- I use a custom function to generate postamble.
- Include my three sites in org-publish-project-alist.
(use-package ox-publish :defer t :config (use-package ox-jamzattack :demand :straight (ox-jamzattack :type git :repo "git@jamzattack.xyz:ox-jamzattack.git")) <<my-org-html-postamble-format>> (defvar my-org-publish-default-options '( <<my-org-publish-default-options>> ) "Default options for `org-publish-project-alist'. This variable must be spliced into `org-publish-project-alist' when set, i.e. (setq org-publish-project-alist `((\"project\" ,@my-org-publish-default-options)))") (setq org-html-postamble t ; needed to use custom format org-export-headline-levels 6 org-html-postamble-format (my-org-html-postamble-format "Author: %A") org-publish-timestamp-directory "~/.cache/org/timestamps/" org-html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\"/>" org-publish-project-alist `(("blog" ,@my-org-publish-default-options :base-directory "~/jamzattack.xyz/blog" :with-toc t :publishing-directory "~/jamzattack.xyz/out/blog" :html-postamble-format ,(my-org-html-postamble-format "Author: %A" "Date: %d (modified %M)" "Top: <a href=\"/index.html\">The Yeet Log</a>") :sitemap-filename "index.org" :sitemap-title "The Yeet Log" :sitemap-format-entry (lambda (entry style project) (cond ((not (directory-name-p entry)) (format "%s [[file:%s][%s]]" (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)) entry (org-publish-find-title entry project))) ((eq style 'tree) ;; Return only last subdir. (file-name-nondirectory (directory-file-name entry))) (t entry))) :sitemap-sort-files anti-chronologically) ("music" ,@my-org-publish-default-options :base-directory "~/jamzattack.xyz/music" :recursive t :html-postamble-format ,(my-org-html-postamble-format "Author: %A" "Top: <a href=\"/sitemap.html\">All projects</a>") :publishing-directory "~/jamzattack.xyz/out/music" :sitemap-title "My Music Projects") ("html" ,@my-org-publish-default-options :base-directory "~/jamzattack.xyz/html" :publishing-directory "~/jamzattack.xyz/out/html"))))
Generate postamble
A little function to generate postamble.
(defun my-org-html-postamble-format (&rest args) "Generate an html postamble using ARGS. This generates a paragraph for each item in ARGS. For format strings, see the docstring of `org-html-postamble-format'." (unless args (setq args '("Author: %a <%e>"))) (list (list "en" (mapconcat (lambda (str) (format "<p>%s</p>" str)) args "\n"))))
Default export options
A list of default export options.
:auto-sitemap t :publishing-function org-html-publish-to-html :html-metadata-timestamp-format "%Y-%m-%d" :with-toc nil :with-email t :with-drawers nil :section-numbers nil :with-todo-keywords nil
ox-jamzattack
I wrote the library ox-jamzattack in a vain attempt to make this section less dense, but it still has a lot going on.
In ox-jamzattack, I define a formatting function to replace org-html-format-spec. This allows me to extract the date that a file was last edited using git (as seen at the bottom of this page).
Publishing locally or via TRAMP?
I used to use TRAMP directories as the publishing directory for my website(s). This is actually really simple, and can just be done as though they were local directories:
(setq org-publish-project-alist '(("blog" :base-directory "~/jamzattack.xyz/blog" :publishing-directory "/ssh:jamzattack.xyz:/var/www/blog") ("music" :base-directory "~/jamzattack.xyz/music" :publishing-directory "/ssh:jamzattack.xyz:/var/www/music")))
This worked fine for a while, but I found it kind of awkward if I needed to make additional edits.
Now, I publish to a local directory and use rsync to send the files to my server:
(setq org-publish-project-alist '(("blog" :base-directory "~/jamzattack.xyz/blog" :publishing-directory "~/jamzattack.xyz/out/blog") ("music" :base-directory "~/jamzattack.xyz/music" :publishing-directory "~/jamzattack.xyz/out/music")))
rsync -rLv --exclude '*~' ~/jamzattack.xyz/out/* jamzattack.xyz:/var/www
This has a few benefits:
- I can check that everything works fine (links, images, etc.) before pushing to my server.
- I don't need to resort to any hackery to publish non-org files.
- I can use symlinks and have the server's directory mimic the local one. This is really useful for publishing my sheet music.
- I have offline access to all the exported html files.