Finding my blog posts with consult-omni

| emacs

Sometimes I just want to quickly get to a blog post by title. I use consult-omni for quick web searches that I can jump to or insert as a link. Sure, I can limit this search to my blog by specifying site:sachachua.com or using the code I wrote to search my blog, notes, and sketches with consult-ripgrep and consult-omni, but the search sometimes gets confused by other text on the page. When I publish my blog with Eleventy, I also create a JSON file with all my blog post URLs and titles. Here's how I can use that data as a consult-omni source.

(defun my-consult-omni-blog-data ()
  (let ((base (replace-regexp-in-string "/$" "" my-blog-base-url))
        (json-object-type 'alist)
        (json-array-type 'list))
    (mapcar
     (lambda (o)
       (list :url (concat base (alist-get 'permalink o))
             :title (alist-get 'title o)
             :date (alist-get 'date o)))
     (sort (json-read-file "~/sync/static-blog/_site/blog/all/index.json")
           (lambda (a b)
             (string< (or (alist-get 'date b) "")
                      (or (alist-get 'date a) "")))))))
(unless (get 'my-consult-omni-blog-data :memoize-original-function)
  (memoize #'my-consult-omni-blog-data "5 minutes"))

(defun my-consult-omni-blog-titles-builder (input &rest args &key callback &allow-other-keys)
  (let* ((quoted (when input (regexp-quote input)))
         (list
          (if quoted
              (seq-filter
               (lambda (o)
                 ;; TODO: Someday figure out orderless?
                 (string-match quoted (concat (plist-get o :title) " - " (plist-get o :title))))
               (my-consult-omni-blog-data))
            (my-consult-omni-blog-data)))
         (candidates
          (mapcar
           (lambda (o)
             (propertize
              (concat (plist-get o :title))
              :source "Blog"
              :date (plist-get o :date)
              :title (plist-get o :title)
              :url (plist-get o :url)))
           (if quoted (seq-take list 3) list))))
    (when callback (funcall callback candidates))
    candidates))

(defun my-consult-omni-blog-annotation (s)
  (format " (%s)"
          (propertize (substring (or (get-text-property 0 :date s) "") 0 4)
                      'face 'completions-annotations)))

(with-eval-after-load 'consult-omni
  (consult-omni-define-source
   "My blog"
   :narrow-char ?b
   :type 'sync
   :request #'my-consult-omni-blog-titles-builder
   :on-return 'my-consult-org-bookmark-visit
   :group #'consult-omni--group-function
   :annotate #'my-consult-omni-blog-annotation
   :min-input 3
   :sort nil
   :require-match t))

Here's what it looks like by itself when I call consult-omni-my-blog:

2025-07-21_23-24-09.png
Figure 1: Screenshot of a search through my blog post titles

Then I can add it as one of the sources used by consult-omni:

  (setq consult-omni-multi-sources
        '(consult-omni--source-google
          consult-omni--source-my-org-bookmarks
          consult-omni--source-my-blog))

Here's what it looks like when I call consult-omni to search my bookmarks, blog posts, and Google results at the same time.

2025-07-21_23-29-06.png
Figure 2: Screenshot of a consult-omni search with multiple sources

Then I can press RET to open the blog post in my browser or C-. i l to insert the link using Embark (my-consult-omni-embark-insert-link).

Related:

Next steps: I want to find out how to get :sort nil to be respected so that more recent blog posts are listed first. Also, it might be fun to define a similar source for the sections of my Emacs configuration, like the way I can use my dotemacs: Org Mode link type with completion.

This is part of my Emacs configuration.
View org source for this post