This blog post can also be found at 1ba87346. This short URL is designed to make sharing online more compact without having to use an external URL shortening service. The permalink for this post is 62 characters (plus base URL, everything following discounts the base URL), while the short URL is 11 characters. Every post will predictably be 11 characters since I’m using CRC32 hash of the permalink to generate the short link. My base domain is 8 characters including the dot so a fully qualified link will be 27 characters, which is acceptable. All the while resolving to a fully informative URL (date + topic).

Hugo provides an alias functionality to add one or more alias to every page through the front matter. There’s no built-in automation around this and I also use ox-hugo to generate my Hugo files from a single org file so I decided to add the functionality to the org-capture template that I have already customized to generate Hugo slugs for posts.

Generating a CRC32 hash is really straight-forward in Ubuntu (my build OS due to Emacs version requirement, yes it’s heavy for CI/CD), it’s just crc32 file.txt so a naive implementation would be:

1
2
3
4
echo "20240121_url-shortening-for-blog-links-natively-in-hugo" > slug.txt
crc32 slug.txt

ad734a45

But I didn’t want transient files being created so I found this super hacky and delightful way of doing it:

1
2
echo -n "20240121_url-shortening-for-blog-links-natively-in-hugo" | gzip -1 -c | tail -c8 | hexdump -n4 -e ' '"%08x"'
1ba87346%

So I made that into a script and glued it up with my org-capture template for Hugo.

1
2
3
(concat ":EXPORT_HUGO_CUSTOM_FRONT_MATTER: :aliases /s/"
                                                        (shell-command-to-string
                                                         (concat "~/dev/shom.dev/crc32Janky.sh " fname)))

As I mentioned in my previous post, my oldest draft is on that topic but since that’s never getting published, most of it is the capture template.

Here's the full configuration for ox-hugo (click arrow to expand):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(use-package ox-hugo
  :straight t
  :config
  ;; Org capture template for Hugo posts
  ;; https://ox-hugo.scripter.co/doc/org-capture-setup/
  (with-eval-after-load 'org-capture
      (defun org-hugo-new-subtree-post-capture-template ()
        "Returns `org-capture' template string for new Hugo post.
See `org-capture-templates' for more information."
        (let* ((title (read-from-minibuffer "Post Title: ")) ;Prompt to enter the post title
                       (fname (concat (format-time-string "%Y%m%d_") (org-hugo-slug title))))
              (mapconcat #'identity
                                 `(
                                       ,(concat "\n* DRAFT " title)
                                       ":PROPERTIES:\n:EXPORT_FILE_NAME: index"
                                       ,(concat ":EXPORT_HUGO_BUNDLE: " fname)
                                       ,(concat ":EXPORT_HUGO_CUSTOM_FRONT_MATTER: :aliases /s/"
                                                        (shell-command-to-string
                                                         (concat "~/dev/shom.dev/crc32Janky.sh " fname)))
                                       ,(concat ":EXPORT_HUGO_IMAGES: /posts/" fname "/image.jpg")
                                       ":EXPORT_HUGO_MENU:\n:END:"
                                       "%?\n")          ;Place the cursor here finally
                                 "\n")))

      (add-to-list 'org-capture-templates
                               '("h"                ;`org-capture' binding + h
                                 "Hugo post"
                                 entry
                                 ;; It is assumed that below file is present in `org-directory'
                                 ;; and that it has a "Blog Ideas" heading. It can even be a
                                 ;; symlink pointing to the actual location of all-posts.org!
                                 (file+olp "~/dev/shom.dev/content.org" "Content")
                                 (function org-hugo-new-subtree-post-capture-template)
                                 :prepend t))))

Now I need to make a nice fancy little sharing link and icon that is rendered on every page and go back and update the old posts. The downside of this approach is that it doesn’t generate all shortened links on build only at capture, which is generally better for not breaking links.

I don’t know much about theme-templating (have a few overrides and shortcodes) or using page data to create new elements so I’ll appreciate pointers and help in making my aliases as nice share-links automatically rendered by Hugo.

Share card image: "3D Strongest Link" by ccPixs.com is licensed under CC BY 2.0 CC iconBy icon of a stick figure person.