diff --git a/init.el b/init.el
index a255a83..3abc2ad 100644
--- a/init.el
+++ b/init.el
@@ -45,7 +45,7 @@
 (setq package-install-upgrade-built-in t)
 
 (require 'unravel-theme)
-;; (require 'unravel-essentials)
+(require 'unravel-essentials)
 ;; (require 'unravel-modeline)
 ;; (require 'unravel-completion)
 ;; (require 'unravel-search)
diff --git a/unravel-emacs.org b/unravel-emacs.org
index 65d9a75..b846388 100644
--- a/unravel-emacs.org
+++ b/unravel-emacs.org
@@ -172,7 +172,7 @@ Now we are ready to load our per-module configuration files:
 
 #+begin_src emacs-lisp :tangle "init.el"
   (require 'unravel-theme)
-  ;; (require 'unravel-essentials)
+  (require 'unravel-essentials)
   ;; (require 'unravel-modeline)
   ;; (require 'unravel-completion)
   ;; (require 'unravel-search)
@@ -738,3 +738,246 @@ Use the entry point ~M-x dictionary-search~
 #+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
 (provide 'unravel-langs)
 #+end_src
+
+* The ~unravel-essentials.el~ module
+
+** Basic configuration in ~unravel-essentials.el~
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el" :mkdirp yes
+  ;;; Essential configurations
+  (use-package emacs
+    :ensure nil
+    :demand t
+    :config
+  ;;;; General settings and common custom functions
+    (setq help-window-select t)
+    (setq next-error-recenter '(4)) ; center of the window
+    (setq find-library-include-other-files nil) ; Emacs 29
+    (setq tramp-connection-timeout (* 60 10)) ; seconds
+    (setq save-interprogram-paste-before-kill t)
+    (setq mode-require-final-newline t)
+    (setq-default truncate-partial-width-windows nil)
+    (setq eval-expression-print-length nil)
+    (setq kill-do-not-save-duplicates t)
+    (setq scroll-error-top-bottom t)
+    (setq echo-keystrokes-help t) ; Emacs 30
+    (setq epa-keys-select-method 'minibuffer)) ; Emacs 30
+#+end_src
+
+** Settings for ~recentf~: keeping track of recent files
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+(use-package recentf
+  :ensure nil
+  :hook (after-init . recentf-mode)
+  :config
+  (setq recentf-max-saved-items 100)
+  (setq recentf-max-menu-items 25) ; I don't use the `menu-bar-mode', but this is good to know
+  (setq recentf-save-file-modes nil)
+  (setq recentf-keep nil)
+  (setq recentf-auto-cleanup nil)
+  (setq recentf-initialize-file-name-history nil)
+  (setq recentf-filename-handlers nil)
+  (setq recentf-show-file-shortcuts-flag nil))
+#+end_src
+
+** Settings for Bookmarks
+:PROPERTIES:
+:CUSTOM_ID: h:581aa0ff-b136-4099-a321-3b86edbfbccb
+:END:
+
+Bookmarks are compartments that store arbitrary information about a file or buffer. The records are used to recreate that file/buffer inside of Emacs. Put differently, we can easily jump back to a file or directory (or anything that has a bookmark recorder+handler, really). Use the ~bookmark-set~ command (=C-x r m= by default) to record a bookmark and then visit one of your bookmarks with ~bookmark-jump~ (=C-x r b= by default).
+
+Also see [[#h:5685df62-4484-42ad-a062-d55ab19022e3][Settings for registers]].
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+;;;; Built-in bookmarking framework (bookmark.el)
+(use-package bookmark
+  :ensure nil
+  :commands (bookmark-set bookmark-jump bookmark-bmenu-list)
+  :hook (bookmark-bmenu-mode . hl-line-mode)
+  :config
+  (setq bookmark-use-annotations nil)
+  (setq bookmark-automatically-show-annotations nil)
+  (setq bookmark-fringe-mark nil) ; Emacs 29 to hide bookmark fringe icon
+  ;; Write changes to the bookmark file as soon as 1 modification is
+  ;; made (addition or deletion).  Otherwise Emacs will only save the
+  ;; bookmarks when it closes, which may never happen properly
+  ;; (e.g. power failure).
+  (setq bookmark-save-flag 1))
+#+end_src
+
+** Settings for registers
+:PROPERTIES:
+:CUSTOM_ID: h:5685df62-4484-42ad-a062-d55ab19022e3
+:END:
+
+Much like bookmarks, registers store data that we can reinstate quickly ([[#h:581aa0ff-b136-4099-a321-3b86edbfbccb][Settings for bookmarks]]). A common use-case is to write some text to a register and then insert that text by calling the given register. This is much better than relying on the ~kill-ring~, because registers are meant to be overwritten by the user, whereas the ~kill-ring~ accumulates lots of text that we do not necessarily need.
+
+To me, registers are essential for keyboard macros. By default, registers do not persist between Emacs sessions, though I do need to re-use them from time to time, hence the arrangement to record them with ~savehist-mode~ ([[#h:25765797-27a5-431e-8aa4-cc890a6a913a][Settings for saving the history (~savehist-mode~)]]).
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+;;;; Registers (register.el)
+(use-package register
+  :ensure nil
+  :defer t ; its commands are autoloaded, so this will be loaded then
+  :config
+  (setq register-preview-delay 0.8
+        register-preview-function #'register-preview-default)
+
+  (with-eval-after-load 'savehist
+    (add-to-list 'savehist-additional-variables 'register-alist)))
+#+end_src
+
+** Settings for ~delete-selection-mode~
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+;;;; Delete selection
+(use-package delsel
+  :ensure nil
+  :hook (after-init . delete-selection-mode))
+#+end_src
+
+** Settings for tooltips
+:PROPERTIES:
+:CUSTOM_ID: h:26afeb95-7920-45ed-8ff6-3648256c280b
+:END:
+
+With these settings in place, Emacs will use its own faces and frame infrastructure to display tooltips. I prefer it this way because then we can benefit from the text properties that can be added to these messages (e.g. a different colour or a slant).
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+;;;; Tooltips (tooltip-mode)
+(use-package tooltip
+  :ensure nil
+  :hook (after-init . tooltip-mode)
+  :config
+  (setq tooltip-delay 0.5
+        tooltip-short-delay 0.5
+        x-gtk-use-system-tooltips t
+        tooltip-frame-parameters
+        '((name . "tooltip")
+          (internal-border-width . 10)
+          (border-width . 0)
+          (no-special-glyphs . t))))
+#+end_src
+
+** Settings for the ~world-clock~
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+;;;; World clock (M-x world-clock)
+(use-package time
+  :ensure nil
+  :commands (world-clock)
+  :config
+  (setq display-time-world-list t)
+  (setq zoneinfo-style-world-list ; M-x shell RET timedatectl list-timezones
+        '(("America/Los_Angeles" "Los Angeles")
+          ("America/Vancouver" "Vancouver")
+          ("Canada/Pacific" "Canada/Pacific")
+          ("America/Chicago" "Chicago")
+          ("Brazil/Acre" "Rio Branco")
+          ("America/Toronto" "Toronto")
+          ("America/New_York" "New York")
+          ("Canada/Atlantic" "Canada/Atlantic")
+          ("Brazil/East" "Brasília")
+          ("UTC" "UTC")
+          ("Europe/Lisbon" "Lisbon")
+          ("Europe/Brussels" "Brussels")
+          ("Europe/Athens" "Athens")
+          ("Asia/Riyadh" "Riyadh")
+          ("Asia/Tehran" "Tehran")
+          ("Asia/Tbilisi" "Tbilisi")
+          ("Asia/Yekaterinburg" "Yekaterinburg")
+          ("Asia/Kolkata" "Kolkata")
+          ("Asia/Singapore" "Singapore")
+          ("Asia/Shanghai" "Shanghai")
+          ("Asia/Seoul" "Seoul")
+          ("Asia/Tokyo" "Tokyo")
+          ("Asia/Vladivostok" "Vladivostok")
+          ("Australia/Brisbane" "Brisbane")
+          ("Australia/Sydney" "Sydney")
+          ("Pacific/Auckland" "Auckland")))
+
+  ;; All of the following variables are for Emacs 28
+  (setq world-clock-list t)
+  (setq world-clock-time-format "%R %z (%Z)	%A %d %B")
+  (setq world-clock-buffer-name "*world-clock*") ; Placement handled by `display-buffer-alist'
+  (setq world-clock-timer-enable t)
+  (setq world-clock-timer-second 60))
+#+end_src
+
+** Run Emacs as a server
+
+The "server" is functionally like the daemon, except it is run by the first Emacs frame we launch. With a running server, we can connect to it through a new ~emacsclient~ call. This is useful if we want to launch new frames that share resources with the existing running process.
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+;;;; Emacs server (allow emacsclient to connect to running session)
+(use-package server
+  :ensure nil
+  :defer 1
+  :config
+  (setq server-client-instructions nil)
+  (unless (server-running-p)
+    (server-start)))
+#+end_src
+
+** ~expreg~ (tree-sitter mark syntactically)
+:PROPERTIES:
+:CUSTOM_ID: h:ceb193bf-0de3-4c43-8ab7-6daa50817754
+:END:
+
+The ~expreg~ package by Yuan Fu (aka casouri) uses the tree-sitter framework to incrementally expand the region from the smallest to the largest syntactic unit in the given context. This is a powerful feature, though it (i) requires Emacs to be built with tree-sitter support and (ii) for the user to be running a major mode that is designed for tree-sitter (Lisp seems to work regardless).
+
+The package offers the ~expreg-expand~ and ~expreg-contract~ commands.
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+  ;;; Mark syntactic constructs efficiently if tree-sitter is available (expreg)
+  (when (treesit-available-p)
+    (use-package expreg
+      :ensure t
+      :functions (prot/expreg-expand prot/expreg-expand-dwim)
+      :bind ("C-M-SPC" . prot/expreg-expand-dwim) ; overrides `mark-sexp'
+      :config
+      (defun prot/expreg-expand (n)
+        "Expand to N syntactic units, defaulting to 1 if none is provided interactively."
+        (interactive "p")
+        (dotimes (_ n)
+          (expreg-expand)))
+
+      (defun prot/expreg-expand-dwim ()
+        "Do-What-I-Mean `expreg-expand' to start with symbol or word.
+  If over a real symbol, mark that directly, else start with a
+  word.  Fall back to regular `expreg-expand'."
+        (interactive)
+        (let ((symbol (bounds-of-thing-at-point 'symbol)))
+          (cond
+           ((equal (bounds-of-thing-at-point 'word) symbol)
+            (prot/expreg-expand 1))
+           (symbol (prot/expreg-expand 2))
+           (t (expreg-expand)))))))
+#+end_src
+
+** Settings for Battery display
+:PROPERTIES:
+:CUSTOM_ID: h:080aa291-95b4-4d54-8783-d156b13190e9
+:END:
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+  ;;;; Show battery status on the mode line (battery.el)
+  (use-package battery
+    :ensure nil
+    :hook (after-init . display-battery-mode)
+    :config
+    (setq battery-mode-line-format
+          (cond
+           ((eq battery-status-function #'battery-linux-proc-acpi)
+            "⏻%b%p%%,%d°C ")
+           (battery-status-function
+            "⏻%b%p%% "))))
+#+end_src
+
+** Finally, we provide ~unravel-essentials.el~ module
+
+#+begin_src emacs-lisp :tangle "unravel-modules/unravel-essentials.el"
+(provide 'unravel-essentials)
+#+end_src
diff --git a/unravel-modules/unravel-essentials.el b/unravel-modules/unravel-essentials.el
new file mode 100644
index 0000000..57fcbcc
--- /dev/null
+++ b/unravel-modules/unravel-essentials.el
@@ -0,0 +1,165 @@
+;;; Essential configurations
+(use-package emacs
+  :ensure nil
+  :demand t
+  :config
+;;;; General settings and common custom functions
+  (setq help-window-select t)
+  (setq next-error-recenter '(4)) ; center of the window
+  (setq find-library-include-other-files nil) ; Emacs 29
+  (setq tramp-connection-timeout (* 60 10)) ; seconds
+  (setq save-interprogram-paste-before-kill t)
+  (setq mode-require-final-newline t)
+  (setq-default truncate-partial-width-windows nil)
+  (setq eval-expression-print-length nil)
+  (setq kill-do-not-save-duplicates t)
+  (setq scroll-error-top-bottom t)
+  (setq echo-keystrokes-help t) ; Emacs 30
+  (setq epa-keys-select-method 'minibuffer)) ; Emacs 30
+
+(use-package recentf
+  :ensure nil
+  :hook (after-init . recentf-mode)
+  :config
+  (setq recentf-max-saved-items 100)
+  (setq recentf-max-menu-items 25) ; I don't use the `menu-bar-mode', but this is good to know
+  (setq recentf-save-file-modes nil)
+  (setq recentf-keep nil)
+  (setq recentf-auto-cleanup nil)
+  (setq recentf-initialize-file-name-history nil)
+  (setq recentf-filename-handlers nil)
+  (setq recentf-show-file-shortcuts-flag nil))
+
+;;;; Built-in bookmarking framework (bookmark.el)
+(use-package bookmark
+  :ensure nil
+  :commands (bookmark-set bookmark-jump bookmark-bmenu-list)
+  :hook (bookmark-bmenu-mode . hl-line-mode)
+  :config
+  (setq bookmark-use-annotations nil)
+  (setq bookmark-automatically-show-annotations nil)
+  (setq bookmark-fringe-mark nil) ; Emacs 29 to hide bookmark fringe icon
+  ;; Write changes to the bookmark file as soon as 1 modification is
+  ;; made (addition or deletion).  Otherwise Emacs will only save the
+  ;; bookmarks when it closes, which may never happen properly
+  ;; (e.g. power failure).
+  (setq bookmark-save-flag 1))
+
+;;;; Registers (register.el)
+(use-package register
+  :ensure nil
+  :defer t ; its commands are autoloaded, so this will be loaded then
+  :config
+  (setq register-preview-delay 0.8
+        register-preview-function #'register-preview-default)
+
+  (with-eval-after-load 'savehist
+    (add-to-list 'savehist-additional-variables 'register-alist)))
+
+;;;; Delete selection
+(use-package delsel
+  :ensure nil
+  :hook (after-init . delete-selection-mode))
+
+;;;; Tooltips (tooltip-mode)
+(use-package tooltip
+  :ensure nil
+  :hook (after-init . tooltip-mode)
+  :config
+  (setq tooltip-delay 0.5
+        tooltip-short-delay 0.5
+        x-gtk-use-system-tooltips t
+        tooltip-frame-parameters
+        '((name . "tooltip")
+          (internal-border-width . 10)
+          (border-width . 0)
+          (no-special-glyphs . t))))
+
+;;;; World clock (M-x world-clock)
+(use-package time
+  :ensure nil
+  :commands (world-clock)
+  :config
+  (setq display-time-world-list t)
+  (setq zoneinfo-style-world-list ; M-x shell RET timedatectl list-timezones
+        '(("America/Los_Angeles" "Los Angeles")
+          ("America/Vancouver" "Vancouver")
+          ("Canada/Pacific" "Canada/Pacific")
+          ("America/Chicago" "Chicago")
+          ("Brazil/Acre" "Rio Branco")
+          ("America/Toronto" "Toronto")
+          ("America/New_York" "New York")
+          ("Canada/Atlantic" "Canada/Atlantic")
+          ("Brazil/East" "Brasília")
+          ("UTC" "UTC")
+          ("Europe/Lisbon" "Lisbon")
+          ("Europe/Brussels" "Brussels")
+          ("Europe/Athens" "Athens")
+          ("Asia/Riyadh" "Riyadh")
+          ("Asia/Tehran" "Tehran")
+          ("Asia/Tbilisi" "Tbilisi")
+          ("Asia/Yekaterinburg" "Yekaterinburg")
+          ("Asia/Kolkata" "Kolkata")
+          ("Asia/Singapore" "Singapore")
+          ("Asia/Shanghai" "Shanghai")
+          ("Asia/Seoul" "Seoul")
+          ("Asia/Tokyo" "Tokyo")
+          ("Asia/Vladivostok" "Vladivostok")
+          ("Australia/Brisbane" "Brisbane")
+          ("Australia/Sydney" "Sydney")
+          ("Pacific/Auckland" "Auckland")))
+
+  ;; All of the following variables are for Emacs 28
+  (setq world-clock-list t)
+  (setq world-clock-time-format "%R %z (%Z)	%A %d %B")
+  (setq world-clock-buffer-name "*world-clock*") ; Placement handled by `display-buffer-alist'
+  (setq world-clock-timer-enable t)
+  (setq world-clock-timer-second 60))
+
+;;;; Emacs server (allow emacsclient to connect to running session)
+(use-package server
+  :ensure nil
+  :defer 1
+  :config
+  (setq server-client-instructions nil)
+  (unless (server-running-p)
+    (server-start)))
+
+;;; Mark syntactic constructs efficiently if tree-sitter is available (expreg)
+(when (treesit-available-p)
+  (use-package expreg
+    :ensure t
+    :functions (prot/expreg-expand prot/expreg-expand-dwim)
+    :bind ("C-M-SPC" . prot/expreg-expand-dwim) ; overrides `mark-sexp'
+    :config
+    (defun prot/expreg-expand (n)
+      "Expand to N syntactic units, defaulting to 1 if none is provided interactively."
+      (interactive "p")
+      (dotimes (_ n)
+        (expreg-expand)))
+
+    (defun prot/expreg-expand-dwim ()
+      "Do-What-I-Mean `expreg-expand' to start with symbol or word.
+If over a real symbol, mark that directly, else start with a
+word.  Fall back to regular `expreg-expand'."
+      (interactive)
+      (let ((symbol (bounds-of-thing-at-point 'symbol)))
+        (cond
+         ((equal (bounds-of-thing-at-point 'word) symbol)
+          (prot/expreg-expand 1))
+         (symbol (prot/expreg-expand 2))
+         (t (expreg-expand)))))))
+
+;;;; Show battery status on the mode line (battery.el)
+(use-package battery
+  :ensure nil
+  :hook (after-init . display-battery-mode)
+  :config
+  (setq battery-mode-line-format
+        (cond
+         ((eq battery-status-function #'battery-linux-proc-acpi)
+          "⏻%b%p%%,%d°C ")
+         (battery-status-function
+          "⏻%b%p%% "))))
+
+(provide 'unravel-essentials)