My Personal Website
  • Emacs Lisp 66.9%
  • HTML 15.6%
  • Python 9.2%
  • CSS 7.3%
  • Makefile 0.6%
  • Other 0.4%
Find a file
Pierre-antoine Comby eeee5f5ae2
update talks
2026-04-22 15:43:35 +02:00
.github/workflows update 2024-04-10 15:11:54 +02:00
archetypes Initial commit 2022-11-07 21:12:06 +00:00
assets update talk and setup 2026-03-04 21:23:15 +01:00
config/_default update april 26 2026-04-22 15:04:07 +02:00
content-org update talks 2026-04-22 15:43:35 +02:00
layouts update talk and setup 2026-03-04 21:23:15 +01:00
lisp update talk and setup 2026-03-04 21:23:15 +01:00
resume@a2bc1ff71a bump CV 2025-08-29 13:30:02 +02:00
static update late august 2025-08-30 12:07:45 +02:00
themes update talk and setup 2026-03-04 21:23:15 +01:00
.DS_Store added multi-lang example 2024-01-04 23:11:25 +00:00
.gitignore update 2024-09-03 19:53:24 +02:00
.gitmodules update 2024-04-10 15:11:54 +02:00
.hugo_build.lock added multi-lang example 2024-01-04 23:11:25 +00:00
build.el update april 26 2026-04-22 15:04:07 +02:00
build.sh update 2024-04-11 22:28:42 +02:00
LICENSE Initial commit 2022-11-07 21:12:06 +00:00
Makefile udpate 2024-11-01 10:00:59 +01:00
README.org update april 26 2026-04-22 15:04:07 +02:00
update.sh updated theme 2023-08-15 10:54:50 +01:00

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

  1. Have emacs , git , make , hugo and rclone installed
  2. Clone the repository
  3. Run the bootstrap command:
emacs -Q --batch --eval "(progn (require 'ob-tangle) (org-babel-tangle-file "'"'"README.org"'"'"))"
  1. Run make to build the website and the resume
make
  1. Run make deploy to deploy the website. This requires rclone to 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
  :pin melpa
)

(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]]")
                                )
      )
((icon . @@hugo:{{< icon "$1" >}}@@) (katex . @@hugo:{{< katex >}}@@) (github . @@hugo:{{< mygithub repo="$1" >}}@@) (gitlab-raw . @@hugo:{{< gitlab repo=$1", server="$2" >}}@@) (gitea . @@hugo:{{<gitea repo="$1" server="$2"  >}}@@) (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)))))
+org-xkcd-export

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-content (split-string path ":"))
         (icon (if (cadr path-content) (car path-content) "download"))
         (path (if (cadr path-content) (cadr path-content) (car path-content)))
         (path (org-hugo--attachment-rewrite-maybe (expand-file-name path) info)))
               ;; use our shortcode
               (format "{{< mykeyword icon=\"%s\" link=\"%s\" >}} %s {{< /mykeyword >}}" icon path (or desc "file"))))
         (t (format "[[file:%s][%s]]" path (or desc path)))))
+org-hugo-export-keywords

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-html-with-latex t
      
      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))
pac/org-hugo-publish

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).

https://ox-hugo.scripter.co/

https://blowfish.page/docs/shortcodes/