My Personal Website
| .github/workflows | ||
| archetypes | ||
| assets | ||
| config/_default | ||
| content-org | ||
| layouts | ||
| lisp | ||
| resume@a2bc1ff71a | ||
| static | ||
| themes | ||
| .DS_Store | ||
| .gitignore | ||
| .gitmodules | ||
| .hugo_build.lock | ||
| build.el | ||
| build.sh | ||
| LICENSE | ||
| Makefile | ||
| README.org | ||
| update.sh | ||
My Website build using Orgmode and Hugo
This repository hosts the sources for /paquiteau/website/src/branch/main/pierre-antoine-comby.fr, my personal website
- 🛠️ It is built using Hugo, a static site generator, and Org mode, an Emacs mode for notes, planning, and authoring.
- 🔗 Connecting the two is done using ox-hugo, an Emacs package that provides an export backend for Org mode to Hugo.
- ✨ The theme used is Blowfish, a beautiful and minimal theme for Hugo.
Building the website
TL;DR
- Have
emacs,git,make,hugoandrcloneinstalled - Clone the repository
- Run the bootstrap command:
emacs -Q --batch --eval "(progn (require 'ob-tangle) (org-babel-tangle-file "'"'"README.org"'"'"))"
- Run
maketo build the website and the resume
make
- Run
make deployto deploy the website. This requiresrcloneto be configured (and it remains my secret).
make deploy
Build dependencies
(setq package-user-dir (expand-file-name "./.packages"))
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("elpa" . "https://elpa.gnu.org/packages/")))
;; Initialize the package system
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(use-package ox-hugo
:ensure t
:pin melpa
:after ox)
(use-package citeproc
:ensure t
:pin melpa)
(use-package emacsql
:ensure t)
(use-package xkcd
:ensure t
:pin melpa)
;; (require 'citeproc)
(require 'ox-publish)
;; custom packages
(load (expand-file-name "lisp/xkcd-extras.el"))
;; (load (expand-file-name "lisp/lorem.el"))
;; a single line fix is required for custom link type to work with info backend.
(load (expand-file-name "lisp/custom-org-hugo-link.el"))
A Custom export backend for blowfish
Expanding the capabilities of ox-hugo and tweaking it for using blowfish template.
(setq pac/blowfish-paired-shortcodes '("alert"
"article"
"badge"
"button"
"carousel"
"codeimporter"
"codeberg"
"figure"
"forgejo"
"gallery"
"keyword"
"keywordList"
"lead"
"mdimporter"
"mermaid"
"timeline")
pac/blowfish-shortcodes '("lead" "icon" "katex" "github" "gitlab" "gitea" "forgejo" "codeberg" "codeimporter" "youtubeLite"))
(setq org-hugo-paired-shortcodes (string-join pac/blowfish-paired-shortcodes " "))
(setq org-export-global-macros '(
("icon" . "@@hugo:{{< icon \"$1\" >}}@@")
("katex" . "@@hugo:{{< katex >}}@@")
("github" . "@@hugo:{{< mygithub repo=\"$1\" >}}@@")
("gitlab-raw" . "@@hugo:{{< gitlab repo=\$1\", server=\"$2\" >}}@@") ;; FIXME
("gitea" . "@@hugo:{{<gitea repo=\"$1\" server=\"$2\" >}}@@")
;; 2nd level
("gitea-comby" . "{{{gitea($1, https://git.comby.xyz)}}}")
("gitlab-crans" . "{{{gitlab-raw($1, https://gitlab.crans.org)}}}")
("gitlab" . "{{{gitlab-raw($1, https://gitlab.com)}}}")
("chaithyagr". "[[https://chaithyagr.github.io/][Chaithya GR]]")
) )
Custom link types
XKCD
(org-link-set-parameters "xkcd"
:image-data-fun #'+org-xkcd-image-fn
:follow #'+org-xkcd-open-fn
:export #'+org-xkcd-export
:complete #'+org-xkcd-complete)
(defun +org-xkcd-open-fn (link)
(+org-xkcd-image-fn nil link nil))
(defun +org-xkcd-image-fn (protocol link description)
"Get image data for xkcd num LINK"
(let* ((xkcd-info (+xkcd-fetch-info (string-to-number link)))
(img (plist-get xkcd-info :img))
(alt (plist-get xkcd-info :alt)))
(message alt)
(+org-image-file-data-fn protocol (xkcd-download img (string-to-number link)) description)))
(defun +org-xkcd-export (num desc backend &optional _com)
"Convert xkcd to html/LaTeX form"
(let* ((xkcd-info (+xkcd-fetch-info (string-to-number num)))
(img (plist-get xkcd-info :img))
(alt (plist-get xkcd-info :alt))
(title (plist-get xkcd-info :title))
(file (xkcd-download img (string-to-number num))))
;; TODO add cond ox-hugo
(cond ((org-export-derived-backend-p backend 'md)
(format "{{< figure src=\"%s\" alt=\"%s\" caption=\"%s\" >}}" img (subst-char-in-string 34 8220 alt) (or desc title)))
;; ((org-export-derived-backend-p backend 'html)
;; (format "<img class='invertible center' src='%s' title=\"%s\" alt='%s'>" img (subst-char-in-string 34 8220 alt) title)) ;; "" --> “”
((org-export-derived-backend-p backend 'latex)
(format "\\begin{figure}[!htb]
\\centering
\\includegraphics[scale=0.4]{%s}%s
\\end{figure}" file (if (equal desc (format "xkcd:%s" num)) ""
(format "\n \\caption*{\\label{xkcd:%s} %s}"
num
(or desc
(format "\\textbf{%s} %s" title alt))))))
(t (format "https://xkcd.com/%s" num)))))
Highlighted files
We put the file in a keyword box with a nice box
(org-link-set-parameters "hfile"
:complete #'org-link-complete-file
:follow #'org-link-open-in-emacs
:face 'org-link
:help-echo "Open file"
:export #'+org-hugo-export-keywords)
(defun +org-hugo-export-keywords (path desc backend info)
"Export a hfile link."
(cond ((org-export-derived-backend-p backend 'md)
;; call org-hugo-link for doing the heavy lifting for us
(let* (
(path (org-hugo--attachment-rewrite-maybe (expand-file-name path) info)))
;; use our shortcode
(format "{{< mykeyword icon=\"download\" link=\"%s\" >}} %s {{< /mykeyword >}}" path (or desc "file"))))
(t (format "[[file:%s][%s]]" path (or desc path)))))
Referencing standards and development
(org-link-set-parameters "pep"
:export (lambda (link desc backend _protocol)
(let ((desc (or desc (format "PEP %s" link))))
(cond ((org-export-derived-backend-p backend 'md)
(format "[%s](https://peps.python.org/pep-%s/)" desc link))
(t (format "https://peps.python.org/pep-%s/" link)))))
:follow (lambda (link)
(browse-url (format "https://peps.python.org/pep-%s/" link)))
:help-echo "Open PEP"
:face 'org-linrightdoubk)
Export
And this is how we do the export:
(setq org-hugo-citations-plist '(:bibliography-section-heading "")
org-hugo-base-dir (expand-file-name ".")
org-hugo-section "post"
org-export-html-date-format-string "%Y-%m-%d"
)
(defun pac/org-hugo-publish (plist filename pub-dir)
(org-open-file filename)
(org-hugo-export-wim-to-md t))
Customizing the bibliography export
Just a little tweak to highlight my name in the bibliography.
(defvar org-hugo--highlight-bibliography-regex (rx (or "comby" "Pierre-Antoine" "P-A" "P.-A." "Comby"))
"list of strings to highlight in the bibliography")
(defun org-hugo--org-cite-export-bibliography (orig-fun &rest args)
"Insert a heading before the exported bibliography.
ORIG-FUN is the original function `org-cite-export-bibliography'
that this function is designed to advice using `:around'. ARGS
are the arguments of the ORIG-FUN."
(let ((bib (apply orig-fun args)))
(let ((case-fold-search t))
(setq bib (replace-regexp-in-string org-hugo--highlight-bibliography-regex "<span class=\"font-bold\">\\&</span>" bib t nil)))
(when (org-string-nw-p bib)
;; Auto-inject Bibliography heading.
(let ((info (nth 2 args)) ;(org-cite-export-bibliography KEYWORD _ INFO)
(bib-heading (or (plist-get org-hugo-citations-plist :bibliography-section-heading) "References")))
(when bib-heading
(let* ((bib-heading (org-blackfriday--translate nil info bib-heading))
(loffset (string-to-number
(or (org-entry-get nil "EXPORT_HUGO_LEVEL_OFFSET" :inherit)
(plist-get info :hugo-level-offset))))
(level-mark (make-string (+ loffset 1) ?#)))
(format "%s %s\n\n%s" level-mark bib-heading bib)))))))
org-hugo--org-cite-export-bibliography
Plumbing ox-hugo with org-publish
(setq org-export-with-broken-links t)
(setq org-publish-project-alist `(("mainsite"
:base-directory ,(expand-file-name "content-org")
:recursive t
:exclude "intro.org"
:publishing-directory "content"
:publishing-function pac/org-hugo-publish)))
(message "default directory %s" default-directory)
(org-publish-all '(4))
(message "Export done")
Some nice to have
These are not use in the build process, but help with the writing and local exporting.
local variable for emacs
((nil . (
(org-hugo-section . "post")
(org-hugo-use-code-for-kbd . t)
))
("content-org/"
. ((org-mode . (
(org-hugo-base-dir . "..")
;; (eval . (org-hugo-auto-export-mode))
)))))
Automate things with a makefile
build: build_resume org_files
hugo
org_files: $(wildcard content-org/*.org)
# rm -rf content/
emacs -Q --script build.el
build_resume:
cd resume; latexmk -pdf CV2.tex
cp resume/CV2.pdf assets/CV2.pdf
deploy: cleanall build
hugo --gc --minify
rclone sync public/ blog:www/ --delete-before
cleanall:
rm -rf public/*
rm -rf content/*
TODO Use CI to handle the deployment
For now I do it manually, but it would be nice to have a CI pipeline to do it automatically.
How to write a blog post
I use Ox-Hugo for the export from org mode to md (to html/css/js with Hugo).