diff --git a/output/about.html b/output/about.html index a35d157..062da79 100644 --- a/output/about.html +++ b/output/about.html @@ -3,208 +3,27 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + About Me - - - - - +
- -
Updated: 2025-08-07 Thu 17:59
+ + +
Updated: 2025-08-07 Thu 17:59

About Me

@@ -212,30 +31,30 @@

Table of Contents

-
-

About Me đź‘‹

-
+
+

1. About Me đź‘‹

+

I'm building a personal site using Emacs, Org-mode, and Cloudflare Pages.

@@ -245,9 +64,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl

-
-

Interests

-
+
+

2. Interests

+
  • Linux
  • Open source
  • @@ -256,9 +75,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

3. Interests

+
  • Linux
  • Open source
  • @@ -267,9 +86,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

4. Interests

+
  • Linux
  • Open source
  • @@ -278,9 +97,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

5. Interests

+
  • Linux
  • Open source
  • @@ -289,9 +108,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

6. Interests

+
  • Linux
  • Open source
  • @@ -300,9 +119,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

7. Interests

+
  • Linux
  • Open source
  • @@ -311,9 +130,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

8. Interests

+
  • Linux
  • Open source
  • @@ -322,9 +141,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

9. Interests

+
  • Linux
  • Open source
  • @@ -333,9 +152,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

10. Interests

+
  • Linux
  • Open source
  • @@ -344,9 +163,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

11. Interests

+
  • Linux
  • Open source
  • @@ -355,9 +174,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

12. Interests

+
  • Linux
  • Open source
  • @@ -366,9 +185,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

13. Interests

+
  • Linux
  • Open source
  • @@ -377,9 +196,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

14. Interests

+
  • Linux
  • Open source
  • @@ -388,9 +207,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

15. Interests

+
  • Linux
  • Open source
  • @@ -399,9 +218,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

16. Interests

+
  • Linux
  • Open source
  • @@ -410,9 +229,9 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Interests

-
+
+

17. Interests

+
  • Linux
  • Open source
  • @@ -421,8 +240,8 @@ I'm building a personal site using Emacs, Org-mode, and Cloudfl
-
-

Back to Home

+
+

18. Back to Home

diff --git a/output/assets/gr.png b/output/assets/gr.png new file mode 100644 index 0000000..c8314b3 Binary files /dev/null and b/output/assets/gr.png differ diff --git a/output/script.js b/output/assets/script.js similarity index 100% rename from output/script.js rename to output/assets/script.js diff --git a/output/style.css b/output/assets/style.css similarity index 70% rename from output/style.css rename to output/assets/style.css index f9f7184..3f35a07 100644 --- a/output/style.css +++ b/output/assets/style.css @@ -47,23 +47,51 @@ a:hover { color: var(--code-bg); } -/* Nav styling */ -nav { +.banner-header { + display: flex; + align-items: center; + justify-content: flex-start; + flex-wrap: wrap; /* allow items to wrap on small screens */ + background-color: var(--banner-bg, #fff); + padding: 0.5rem 1rem; border-radius: 6px; - margin-bottom: 1rem; +} + +.banner-logo { + height: 80px; + width: auto; + margin-right: 1.5rem; + border-radius: 50%; +} + +/* Keep nav horizontal on desktop */ +nav { + display: flex; + gap: 1rem; font-weight: 600; font-size: 1.1rem; } -nav a { - color: var(--link); - text-decoration: none; - font-weight: 600; +/* Mobile styles */ +@media (max-width: 600px) { + .banner-header { + flex-direction: column; /* stack logo + nav */ + align-items: center; + text-align: center; + } + + .banner-logo { + margin: 0 0 0.5rem 0; /* space under logo */ + } + + nav { + flex-wrap: wrap; /* allow nav links to wrap */ + justify-content: center; + gap: 0.5rem; + font-size: 1rem; /* slightly smaller text */ + } } -nav a:hover { - text-decoration: underline; -} /* Footer styling */ footer { @@ -123,3 +151,6 @@ pre.src { li { margin-bottom: 8px; } + + + diff --git a/output/blogs/2025/08/zettelkasten.html b/output/blogs/2025/08/zettelkasten.html new file mode 100644 index 0000000..cffbdbd --- /dev/null +++ b/output/blogs/2025/08/zettelkasten.html @@ -0,0 +1,74 @@ + + + + + + + +Zettelkasten Method + + + + + +
+ + +
Updated: 2025-08-08 Fri 18:17
+
+
+

Zettelkasten Method

+
+

The Zettelkasten Method

+
+

+This Zettelkasten method is growing in popularity for taking notes. Ever felt as though there's too much pieces of information but you don't know how to deal with it? This method solves exactly that problem and more. Think of it as forming a second brain, where you can jot down ideas and information whilst simultaneously being able to connect them together. +

+ +

+The official website describes in detail exactly what the Zettelkasten method is, providing use cases and benefits to this method. The part I wanted to highlighted in this is the following paragraph, where the author depicts how this concept would be explained to someone unfamiliar with it: +

+ +
+

+A Zettelkasten is a personal tool for thinking and writing. It has hypertextual features to make a web of thoughts possible. The difference to other systems is that you create a web of thoughts instead of notes of arbitrary size and form, and emphasize connection, not a collection. +

+
+ +

+This web of thoughts is exactly what makes it useful, it takes on the seemingly cluttered mess of information and is able to link the nodes together to create something meaningful and useful. +

+ +

+There are many personal knowledge management systems' (PKMS) out there that allow you to practice this method; the most common ones being Obsidian and Org Roam. After using Org Roam with Emacs for about a year or so, I realised how useful this method really is. A random idea can be jotted down and later connected to a bigger project or note system. The following picture below is a screenshot of a graph generated UI for all the nodes created in my Org Roam folder: +

+ + +
+

org-roam-ui-graph.png +

+
+
+
+
+
+
+ +
+Created with Emacs 30.1 (Org mode 9.7.11) on Arch GNU/Linux +
+
+
+ + diff --git a/output/blogs/blogs-intro.html b/output/blogs/blogs-intro.html index 0e44366..5c73db1 100644 --- a/output/blogs/blogs-intro.html +++ b/output/blogs/blogs-intro.html @@ -3,215 +3,33 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Blogs Introduction - - - - - +
- -
Updated: 2025-08-07 Thu 22:24
+ + +
Updated: 2025-08-08 Fri 17:31

Blogs Introduction

-
-

Introduction

-
+
+

Introduction

+

In this section you will find posts that are not as structured as the ones found in here. Mainly these will deal with findings, research, assorted writings and random bits and blobs.

diff --git a/output/blogs/blogs-list.html b/output/blogs/blogs-list.html index 008d309..5262a58 100644 --- a/output/blogs/blogs-list.html +++ b/output/blogs/blogs-list.html @@ -3,218 +3,39 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Blogs List - - - - - +
- -
Updated: 2025-08-07 Thu 22:36
+ + +
Updated: 2025-08-08 Fri 18:26

Blogs List

-
-

Posts:

-
+

+See the categories: Categories +

+
+

Blogs:

+
diff --git a/output/blogs/zettelkasten.html b/output/blogs/zettelkasten.html deleted file mode 100644 index 8dea7b5..0000000 --- a/output/blogs/zettelkasten.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - - -Zettelkasten Method - - - - - - - - -
- -
Updated: 2025-08-07 Thu 22:22
-
-
-

Zettelkasten Method

-
-

The Zettelkasten Method

-
-

-This Zettelkasten method is growing in popularity for taking notes. Ever felt as though there's too much pieces of information but you don't know how to deal with it? This method solves exactly that problem and more. Think of it as forming a second brain, where you can jot down ideas and information whilst simultaneously being able to connect them together. -

- -

-The official website describes in detail exactly what the Zettelkasten method is, providing use cases and benefits to this method. The part I wanted to highlighted in this is the following paragraph, where the author depicts how this concept would be explained to someone unfamiliar with it: -

- -
-

-A Zettelkasten is a personal tool for thinking and writing. It has hypertextual features to make a web of thoughts possible. The difference to other systems is that you create a web of thoughts instead of notes of arbitrary size and form, and emphasize connection, not a collection. -

-
- -

-This web of thoughts is exactly what makes it useful, it takes on the seemingly cluttered mess of information and is able to link the nodes together to create something meaningful and useful. -

- -

-There are many personal knowledge management systems' (PKMS) out there that allow you to practice this method; the most common ones being Obsidian and Org Roam. After using Org Roam with Emacs for about a year or so, I realised how useful this method really is. A random idea can be jotted down and later connected to a bigger project or note system. The following picture below is a screenshot of a graph generated UI for all the nodes created in my Org Roam folder: -

- - -
-

org-roam-ui-graph.png -

-
-
-
-
-
-
- -
-Created with Emacs 30.1 (Org mode 9.7.11) on Arch GNU/Linux -
-
-
- - diff --git a/output/categories.html b/output/categories.html new file mode 100644 index 0000000..ab9a372 --- /dev/null +++ b/output/categories.html @@ -0,0 +1,50 @@ + + + + + + + +Categories + + + + + +
+ + +
Updated: 2025-08-08 Fri 18:26
+
+
+
+

Categories (Includes both blogs and posts)

+
+ +
+
+
+
+
+ +
+Created with Emacs 30.1 (Org mode 9.7.11) on Arch GNU/Linux +
+
+
+ + diff --git a/output/contact.html b/output/contact.html index 735aa1e..9b79709 100644 --- a/output/contact.html +++ b/output/contact.html @@ -3,214 +3,33 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + Contact - - - - - +
- -
Updated: 2025-08-07 Thu 17:53
+ + +
Updated: 2025-08-07 Thu 17:53

Contact

-
-

Contact Using the Following:

-
+
+

Contact Using the Following:

+

> LinkedIn: LinkedIn

diff --git a/output/index.html b/output/index.html index 2afa56e..081c9d8 100644 --- a/output/index.html +++ b/output/index.html @@ -3,214 +3,32 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + -Zaine Qayyum +Home Page - - - - - +
- -
Updated: 2025-08-07 Thu 22:32
+ + +
Updated: 2025-08-08 Fri 16:09
-

Zaine Qayyum

-
-

Welcome! 🌱

-
+
+

Welcome! 🌱

+

This is a website built using Emacs Org-mode and published using org-publish.

@@ -224,12 +42,13 @@ Feel free to explore:
  • Posts Page
  • Blogs Page
  • Setup Page
  • +
  • Sitemap
  • -
    -

    How to publish web pages using org-publish

    -
    +
    +

    How to publish web pages using org-publish

    +

    This website is heavily inspired by some people who have decided to use org-publish as a way to convert org files into html. I came across a few that took the plunge and decided to migrate from platforms like Wordpress and instead opted for a more transparent, text-based workflow.

    @@ -246,6 +65,9 @@ So how does one go about publishing web pages through Emacs's org-publish< The first thing we will want to do is edit our init.el file, which is the initialization file. In this file we want to add the following:

    +

    +This is a simple and quick way of getting this setup, although there is a better and more scalable approach to this, where we have a build script that runs each time we want to generate the project. See here for more details. +

    @@ -320,9 +142,9 @@ And there we go! The files are now being hosted on http://localhost:8000/<
     

    -
    -

    Contact

    -
    +
    +

    Contact

    +

    Feel free to reach out on GitHub: https://github.com/zainezq

    diff --git a/output/posts.html b/output/posts.html index c1e634d..d616889 100644 --- a/output/posts.html +++ b/output/posts.html @@ -3,222 +3,43 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + Posts -
    - -
    Updated: 2025-08-06 Wed 21:03
    + + +
    Updated: 2025-08-06 Wed 21:03

    Posts

    -
    -

    Links

    -
    +
    +

    Links

    +
    -
    -

    Posts Introduction   intro

    +
    +

    Posts Introduction   intro

    -
    -

    Zettelkasten Method   education

    -
    +
    +

    Zettelkasten Method   education

    +

    <2025-08-06 Wed>

    diff --git a/output/posts/posts-intro.html b/output/posts/posts-intro.html index 862b7b0..1e1cf74 100644 --- a/output/posts/posts-intro.html +++ b/output/posts/posts-intro.html @@ -3,215 +3,33 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Posts Introduction - - - - - +
    - -
    Updated: 2025-08-07 Thu 21:58
    + + +
    Updated: 2025-08-07 Thu 21:58

    Posts Introduction

    -
    -

    Introduction

    -
    +
    +

    Introduction

    +

    In this section you will find posts related to both technical and non-technical topics. As Einstein said: “If you can’t explain it simply you don’t understand it well enough”, thus the goal with these posts is to develop the skill of being able to deliver habitual high quality explanations as well as reinforcing the topic(s) learnt.

    diff --git a/output/posts/posts-list.html b/output/posts/posts-list.html index c062a29..cf77548 100644 --- a/output/posts/posts-list.html +++ b/output/posts/posts-list.html @@ -3,215 +3,36 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + Posts List - - - - - +
    - -
    Updated: 2025-08-07 Thu 22:36
    + + +
    Updated: 2025-08-08 Fri 18:26

    Posts List

    -
    -

    Posts:

    -
    +

    +See the categories: Categories +

    +
    +

    Posts:

    +
    diff --git a/output/setup.html b/output/setup.html index e78bf6a..35cc4ee 100644 --- a/output/setup.html +++ b/output/setup.html @@ -3,214 +3,33 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + Setup - - - - - +
    - -
    Updated: 2025-08-07 Thu 22:36
    + + +
    Updated: 2025-08-08 Fri 18:26

    Setup

    -
    -

    Introduction

    -
    +
    +

    Introduction

    +

    This page will highlight the build-script.el used to generate this website. This entire website is generated through org files using the command:

    @@ -221,45 +40,36 @@ This page will highlight the build-script.el used to generate this
    -
    -

    The script

    -
    +
    +

    The script

    +

    -The script is as follows, at the start I have commented out pieces of code (somewhat relevant to the script but never really used), followed by package management. Then there's the declaration of variables and functions and finally the org-publish-project-alist which handles nearly all of the project generation instructions. +The script is as follows, at the start I have some metadata relating to the file, followed by package management,then the declaration of variables/functions and finally the org-publish-project-alist which handles nearly all of the project generation instructions.

    -;; Commented out things:
    +;;; build-site.el --- Publish my website using org-publish -*- lexical-binding: t; -*-
     
    -;; (defvar z-head
    -;;   "<link rel=\"stylesheet\" type=\"text/css\" href=\"https://gongzhitaao.org/orgcss/org.css\" />
    -;; <link rel=\"stylesheet\" href=\"/style.css\" />")
    +;; Author: Zaine Qayyum <zaineulabideen@outlook.com>
    +;; Created: 2025-08-08
    +;; Purpose: Build and publish my static site from Org files.
     
    -;; (setq org-html-validation-link nil
    -;;       org-html-head-include-scripts nil
    -;;       org-html-head-include-default-style nil
    -;;       org-html-head z-head)
    +;;; Commentary:
    +;; Run this file with:
    +;; emacs -Q --script build-site.el
     
    -;; (type-of (car '(rose violet daisy buttercup)))
    -;; (cadr (assoc "FILETAGS" (org-collect-keywords '("FILETAGS"))))
    +;;; Code:
     
    -;; (let ((list '(("post1.org") ("post2.org"))))
    -;;   (mapconcat (lambda (entry)
    -;;                (format "- [[file:%s]]" (car entry)))
    -;;              list
    -;;              "\n"))
    -
    -
    -
    -;;BEGIN:
    -;; Set the package installation directory so that packages aren't stored in the
    -;; ~/.emacs.d/elpa path.
    -(require 'package)
    +(require 'package)
     (setq package-user-dir (expand-file-name "./.packages"))
     (setq package-archives '(("melpa" . "https://melpa.org/packages/")
                              ("elpa" . "https://elpa.gnu.org/packages/")))
     
    +(require 'ox-publish)
    +(require 'cl-lib)
    +(require 'org)
    +
     ;; Initialize the package system
     (package-initialize)
     (unless package-archive-contents
    @@ -269,17 +79,25 @@ The script is as follows, at the start I have commented out pieces of code (some
     (package-install 'htmlize)
     
     ;; Load the publishing system
    -(require 'ox-publish)
    -(setq org-html-htmlize-output-type 'css)
    +(setq org-html-htmlize-output-type 'css)
    +(setq org-html-head-include-default-style nil)
    +
    +(defvar z-shared-head
    +      "
    +<link rel=\"stylesheet\" href=\"https://gongzhitaao.org/orgcss/org.css\" /> <link rel=\"stylesheet\" href=\"/assets/style.css\" /> <script src=\"/assets/script.js\" defer></script> ")
     
     (defvar z-preamble
    -  "<nav>
    -  <a href=\"/\">Home | </a>
    -  <a href=\"/posts/posts-list.html\">Posts | </a>
    -  <a href=\"/blogs/blogs-list.html\">Blogs | </a>
    -  <a href=\"/contact.html\">Contact</a>
    -</nav>
    -<div id=\"updated\">Updated: %C</div>"
    +  "
    +<div class=\"banner-header\">
    +  <a href=\"/\"> <img src=\"/assets/gr.png\" alt=\"Site Logo\" class=\"banner-logo\" /> </a>
    +  <nav>
    +    <a href=\"/\">Home | </a>
    +    <a href=\"/posts/posts-list.html\">Posts | </a>
    +    <a href=\"/blogs/blogs-list.html\">Blogs | </a>
    +    <a href=\"/contact.html\">Contact</a>
    +  </nav>
    +  </div>
    +  <div id=\"updated\">Updated: %C</div>"
     )
     
     (defvar z-postamble
    @@ -299,6 +117,7 @@ Created with %c on <a href=\"https://www.archlinux.org/\">Arch</a> &
       (concat
        "#+TITLE: " title "\n"
        "#+OPTIONS: toc:nil num:nil \n\n"
    +   "See the categories: @@html:<a href=\"../categories.html\">Categories</a>@@\n\n"
        "* Posts:\n"
        (mapconcat
         (lambda (entry)
    @@ -336,7 +155,8 @@ Created with %c on <a href=\"https://www.archlinux.org/\">Arch</a> &
       (concat
        "#+TITLE: " title "\n"
        "#+OPTIONS: toc:nil num:nil \n\n"
    -   "* Posts:\n"
    +   "See the categories: @@html:<a href=\"../categories.html\">Categories</a>@@\n\n"
    +   "* Blogs:\n"
        (mapconcat
         (lambda (entry)
           (let* ((link (car entry))
    @@ -368,9 +188,120 @@ Created with %c on <a href=\"https://www.archlinux.org/\">Arch</a> &
         "\n")))
     
     
    +
    +(defun z/categories-sitemap (title _list)
    +  "Generate a categories page by scanning tags across org-posts and org-blogs."
    +  (let* ((expanded (org-publish-expand-projects org-publish-project-alist))
    +         (posts    (assoc "org-posts" expanded))
    +         (blogs    (assoc "org-blogs" expanded))
    +         ;; DO NOT set :exclude to "" — it excludes everything
    +         (files (cl-remove-duplicates
    +                 (append (and posts (org-publish-get-base-files posts))
    +                         (and blogs (org-publish-get-base-files blogs)))
    +                 :test #'file-equal-p))
    +         ;; optional: drop the generated sitemaps
    +         (files (cl-remove-if
    +                 (lambda (f)
    +                   (member (file-name-nondirectory f)
    +                           '("posts-list.org" "blogs-list.org" "sitemap.org" "categories.org")))
    +                 files))
    +         (counts (make-hash-table :test 'equal)))
    +    ;;(message "files I will scan: %S" files)
    +    (dolist (f files)
    +      (when (file-readable-p f)
    +        (with-temp-buffer
    +          (insert-file-contents f)
    +          (org-mode)
    +          (let* ((kw (org-collect-keywords '("FILETAGS" "TAGS")))
    +                 (raw (car (or (cdr (assoc "FILETAGS" kw))
    +                               (cdr (assoc "TAGS" kw))))))
    +            (when raw
    +              (dolist (tag (split-string raw ":" t))
    +                (puthash tag (1+ (gethash tag counts 0)) counts)))))))
    +
    +    (let (tags)
    +      (maphash (lambda (k _) (push k tags)) counts)
    +      (setq tags (sort tags #'string-lessp))
    +      (concat
    +       "#+TITLE: " title "\n#+OPTIONS: toc:nil num:nil title:nil\n\n* Categories (Includes both blogs and posts)\n"
    +       (if tags
    +           (mapconcat
    +            (lambda (tag)
    +              (format "- [[file:tags/%s.org][@@html:<span class=\"post-tag\">%s</span>@@]] (%d)"
    +                      (z/tag-slug tag) tag (gethash tag counts))
    +              )
    +            tags
    +            "\n")
    +         "_No tags found yet._")))))
    +
    +
    +(defun z/tag-slug (s)
    +  "Turn a tag into a safe filename."
    +  (let ((down (downcase s)))
    +    (replace-regexp-in-string "[^a-z0-9]+" "-" down)))
    +
    +(defun z/collect-post-files ()
    +  "Return all .org files from org-posts and org-blogs."
    +  (let* ((expanded (org-publish-expand-projects org-publish-project-alist))
    +         (posts    (assoc "org-posts" expanded))
    +         (blogs    (assoc "org-blogs" expanded)))
    +    (cl-remove-duplicates
    +     (append (and posts (org-publish-get-base-files posts))
    +             (and blogs (org-publish-get-base-files blogs)))
    +     :test #'file-equal-p)))
    +
    +(defun z/gather-tag-index ()
    +  "Return hash: tag -> list of (FILE TITLE DATE-ISO)."
    +  (let ((idx (make-hash-table :test 'equal)))
    +    (dolist (f (z/collect-post-files))
    +      (when (and (string-match-p "\\.org\\'" f)
    +                 (file-readable-p f)
    +                 ;; ignore generated lists
    +                 (not (member (file-name-nondirectory f)
    +                              '("posts-list.org" "blogs-list.org" "sitemap.org" "categories.org"))))
    +        (with-temp-buffer
    +          (insert-file-contents f)
    +          (org-mode)
    +          (let* ((kw (org-collect-keywords '("TITLE" "FILETAGS" "TAGS" "DATE")))
    +                 (title (or (car (cdr (assoc "TITLE" kw)))
    +                            (file-name-base f)))
    +                 (date  (or (car (cdr (assoc "DATE" kw))) "")) ;; optional
    +                 (raw   (car (or (cdr (assoc "FILETAGS" kw))
    +                                 (cdr (assoc "TAGS" kw))))))
    +            (when raw
    +              (dolist (tag (split-string raw ":" t))
    +                (push (list f title date) (gethash tag idx))))))))
    +    idx))
    +
    +(defun z/write-tag-pages ()
    +  "Generate tags/*.org pages listing posts for each tag."
    +  (let* ((site-root (expand-file-name "~/master-folder/org_files/org_web/"))
    +         (tags-dir  (expand-file-name "tags" site-root)))
    +    (unless (file-directory-p tags-dir)
    +      (make-directory tags-dir t))
    +    (let ((idx (z/gather-tag-index)))
    +      (maphash
    +       (lambda (tag items)
    +         (let* ((slug (z/tag-slug tag))
    +                (outfile (expand-file-name (format "%s.org" slug) tags-dir)))
    +           (with-temp-file outfile
    +             (insert (format "#+TITLE: Tag: %s\n#+OPTIONS: toc:nil num:nil title:nil \n\n* Posts tagged %s\n"
    +                             tag tag))
    +             ;; sort newest first if DATE present
    +             (setq items (sort items (lambda (a b) (string> (nth 2 a) (nth 2 b)))))
    +             (dolist (it items)
    +               (let* ((file (nth 0 it))
    +                      (title (nth 1 it))
    +                      (rel   (file-relative-name file tags-dir)))
    +                 ;; link to the source .org; org-publish will rewrite to the .html
    +                 (insert (format "- [[file:%s][%s]]\n" rel title)))))))
    +       idx)
    +      )))
    +
    +
     ;; Define the publishing project
     (setq org-publish-project-alist
    -      `(("org-notes"
    +      `(("org-main"
              :recursive t
              :base-directory "~/master-folder/org_files/org_web/"
              :publishing-function org-html-publish-to-html
    @@ -381,17 +312,27 @@ Created with %c on <a href=\"https://www.archlinux.org/\">Arch</a> &
              :base-extension "org"
              :section-numbers nil
              :time-stamp-file nil
    +         :auto-sitemap t
    +         :sitemap-filename "sitemap.org"
    +         :sitemap-title "Sitemap"
    +         :sitemap-sort-files chronologically
              :html-preamble ,z-preamble
              :html-postamble ,z-postamble
    -         :html-head "
    -<link rel=\"stylesheet\" type=\"text/css\" href=\"https://gongzhitaao.org/orgcss/org.css\" />
    -<link rel=\"stylesheet\" href=\"style.css\" />
    -<script src=\"script.js\" defer></script>
    -"
    -        )
    +         :html-head ,z-shared-head)
    +        ("org-categories-sitemap"
    +         :recursive t
    +         :base-directory "~/master-folder/org_files/org_web/"
    +         :publishing-directory "~/master-folder/org_files/org_web/output"
    +         :base-extension "org"
    +         :auto-sitemap t
    +         :sitemap-filename "categories.org"
    +         :sitemap-title "Categories"
    +         :sitemap-function z/categories-sitemap
    +         :html-preamble ,z-preamble
    +         :html-postamble ,z-postamble
    +         :html-head ,z-shared-head)
             ("org-posts"
              :base-directory "~/master-folder/org_files/org_web/posts"
    -         :base-extension "org"
              :publishing-directory "~/master-folder/org_files/org_web/output/posts/"
              :recursive t
              :base-extension "org"
    @@ -408,15 +349,9 @@ Created with %c on <a href=\"https://www.archlinux.org/\">Arch</a> &
              :sitemap-title "Posts List"
              :sitemap-style list
              :sitemap-function z/posts-sitemap
    -         :html-head "
    -<link rel=\"stylesheet\" type=\"text/css\" href=\"https://gongzhitaao.org/orgcss/org.css\" />
    -<link rel=\"stylesheet\" href=\"../style.css\" />
    -<script src=\"../script.js\" defer></script>
    -"
    -         )
    +         :html-head ,z-shared-head)
             ("org-blogs"
              :base-directory "~/master-folder/org_files/org_web/blogs"
    -         :base-extension "org"
              :publishing-directory "~/master-folder/org_files/org_web/output/blogs/"
              :recursive t
              :base-extension "org"
    @@ -424,8 +359,6 @@ Created with %c on <a href=\"https://www.archlinux.org/\">Arch</a> &
              :with-author nil
              :with-creator nil
              :html-validation-link nil
    -         :with-toc t
    -         :section-numbers t
              :html-preamble ,z-preamble
              :html-postamble ,z-postamble
              :auto-sitemap t
    @@ -433,46 +366,45 @@ Created with %c on <a href=\"https://www.archlinux.org/\">Arch</a> &
              :sitemap-title "Blogs List"
              :sitemap-style list
              :sitemap-function z/blogs-sitemap
    -         :html-head "
    -<link rel=\"stylesheet\" type=\"text/css\" href=\"https://gongzhitaao.org/orgcss/org.css\" />
    -<link rel=\"stylesheet\" href=\"../style.css\" />
    -<script src=\"../script.js\" defer></script>
    -"
    -         )
    -
    -
    +         :html-head ,z-shared-head)
    +        ("org-tags"
    +         :base-directory "~/master-folder/org_files/org_web/tags"
    +         :publishing-directory "~/master-folder/org_files/org_web/output/tags"
    +         :recursive t
    +         :base-extension "org"
    +         :publishing-function org-html-publish-to-html
    +         :with-author nil
    +         :with-creator nil
    +         :html-preamble ,z-preamble
    +         :html-postamble ,z-postamble
    +         :html-head ,z-shared-head)
             ("org-assets"
              :base-directory "~/master-folder/org_files/org_web/assets/"
              :base-extension "css\\|js\\|png\\|jpg\\|gif\\|svg\\|pdf\\|woff\\|woff2\\|ttf"
              :publishing-directory "~/master-folder/org_files/org_web/output/assets/"
              :recursive t
              :publishing-function org-publish-attachment)
    -        ("org-static"
    -         :base-directory "~/master-folder/org_files/org_web/"
    -         :base-extension "css\\|js"
    -         :publishing-directory "~/master-folder/org_files/org_web/output"
    -         :recursive t
    -         :publishing-function org-publish-attachment)
    +        ))
     
    -        ("website"
    -         :components ("org-notes" "org-assets" "org-posts" "org-blogs" "org-static"))))
    -
    -;; Delete the output before generating the new one
    -(delete-directory "~/master-folder/org_files/org_web/output/" t)
    +(delete-directory "~/master-folder/org_files/org_web/output/" t)
    +(delete-directory "~/master-folder/org_files/org_web/tags/" t)
     (message "Directory deleted")
     
     ;; Generate the site output
    -(org-publish-all t)
    +(z/write-tag-pages)
    +(org-publish-all t)
     
     (message "Build complete!")
     
    +;;; build-site.el ends here
    +
     
    -
    -

    Publish Script

    -
    +
    +

    Publish Script

    +

    As the project is hosted on Github, I have created a small script that is able to push changes to the remote repository, which Cloudflare will automatically detect and rebuild the website:

    diff --git a/output/sitemap.html b/output/sitemap.html new file mode 100644 index 0000000..24e394e --- /dev/null +++ b/output/sitemap.html @@ -0,0 +1,65 @@ + + + + + + + +Sitemap + + + + + +
    + + +
    Updated: 2025-08-08 Fri 18:26
    +
    + +
    +
    + +
    +Created with Emacs 30.1 (Org mode 9.7.11) on Arch GNU/Linux +
    +
    +
    + + diff --git a/output/tags/education.html b/output/tags/education.html new file mode 100644 index 0000000..812d977 --- /dev/null +++ b/output/tags/education.html @@ -0,0 +1,49 @@ + + + + + + + +Tag: education + + + + + +
    + + +
    Updated: 2025-08-08 Fri 18:26
    +
    +
    +
    +

    Posts tagged education

    + +
    +
    +
    +
    + +
    +Created with Emacs 30.1 (Org mode 9.7.11) on Arch GNU/Linux +
    +
    +
    + + diff --git a/output/tags/introduction.html b/output/tags/introduction.html new file mode 100644 index 0000000..74e7e94 --- /dev/null +++ b/output/tags/introduction.html @@ -0,0 +1,50 @@ + + + + + + + +Tag: introduction + + + + + +
    + + +
    Updated: 2025-08-08 Fri 18:26
    +
    +
    +
    +

    Posts tagged introduction

    + +
    +
    +
    + +
    + +