1 #+options: title:nil num:t
3 #+TITLE: Blog With Only Orgmode
4 #+DATE: <2020-03-15 Sun>
6 This blog is now being written with [[https://orgmode.org/][org-mode]] and [[https://www.gnu.org/software/emacs][Emacs]]. I have been
7 threatening to do so for a while now. I have previously used [[https://ikiwiki.info][ikiwiki]],
8 which is also a static site generator. I have switched to org-mode,
9 mainly because I like org markup better than [[https://en.wikipedia.org/wiki/Markdown][markdown]]. I write most
10 everything else in org-mode; the context switch, I think, kept me from
14 As I have decided that all I need is the [[https://orgmode.org/manual/Publishing.html][publishing features of
15 org-mode]], I had to structure the sources for the blog smartly. I think
16 I have come up with a structure that can be maintained and grokked
17 by ~(org-publish)~ without requiring too much additional [[https://en.wikipedia.org/wiki/Emacs_Lisp][Emacs Lisp]].
19 Another thing I am changing is not publishing directly from a
20 =git hook=. Not publishing directly from a =git hook= allows easier
21 writing across several computers. I have ~(org-publish)~ write to
22 =~/public_html/jamestechnotes.com= for local testing.
24 This is my setup, from which I borrowed heavily from [[https://ogbe.net/blog/blogging_with_org.html][Dennis Ogbe's
26 + All of my websites are beneath ~~/src/wikis~. This one is beneath
27 ~/src/wikis/jamestechnotes.com~. If you happen to be really
28 interested in the layout, all of the source is [[https://git.jamestechnotes.com/?p=jamestechnotes.com.git;a=summary][published]].[fn:2]
29 + The elisp that glues all of this together is in my [[https://git.jamestechnotes.com/?p=james/home/home-etc.git;a=blob;f=.emacs.d/config/org.el;h=bb3385aaf086305e389ae6b7251f4f735589dedc;hb=HEAD][emacs config]];
30 relevant sections will be detailed below.
31 + The blog files split into the following structure:
32 - =/pages/= --- Static pages, like the [[https://jamestechnotes.com][home page]], live here as org
34 - =/css/= --- css files live here.
35 - =/blog/entry/= --- individual blog posts live here.
36 - =/img/= -- (Not yet implemented) images would live here.
37 ** How does this help?
38 Hopefully, =/css/= and =/img/= are rather clear. They hold, well, css
39 files and images. The images bother me. As images are binary
40 artifacts, they are rather awkward[fn:3] to check into git. I suspect
41 if I start accumulating large images, I will look into using some like
42 [[https://git-annex.branchable.com][git annex]] to manage them.
44 Static pages, which don't change often, live out of the way beneath
45 =/pages/=. There is a separate publishing project just for these.
47 Individual blog entries live in their own org file in
48 =/blog/entry/=. If I actually start writing many post and the
49 directory get unwieldy, I will have to hash the entries, probably by
50 year. This section also has it's own publishing project, that also
51 generates a sitemap index. Elisp will be developed to coerce this
52 sitemap into a proper blog index.
54 I have an elisp function, =jr/prepare-pages=, which looks for a file
55 named =header.html= in the =base-directory= of the project. The
56 function is called when ~(org-publish)~ generates the preamble of each
57 page. I use this machinery to build the top navigation menu on the
60 A benefit of this layout, to which I did not pay attention, is the top
61 directory of the web site contains no content that is
62 publishable. Adding a todo.org file here will allow me to add [[https://www.orgmode.org/manual/TODO-Items.html][org todo
63 items]] with ideas for future blog post and have them show up in my
64 [[https://orgmode.org/manual/Agenda-Views.html][Agenda]]. I could also add actual todo headline in actual blog posts and
65 mark them =noexport= so they won't publish.
68 While ~(org-publish)~ already does a lot out of the box, a bit of help
69 is need to achieve the desired layout. First, links to stylesheets
70 need to be added to the =<head>= of the document. The variable
71 ~jr/html-head~ contains text which is inserted in the document.
72 #+BEGIN_SRC emacs-lisp
75 "<link rel=\"stylesheet\" href=\"/../css/org.css\" />\n" ;; start with org.css
76 "<link rel=\"stylesheet\" href=\"/../css/main.css\" />"))
78 =org.css= was copied from an exported html buffer. =main.css= contains
79 custom layouts which will override the defaults from =org.css= and
82 The =jr/prepare-pages= function mentioned earlier the inserts
83 =header.html= into the preamble is listed here:
84 #+BEGIN_SRC emacs-lisp
85 (defun jr/prepare-pages (plist)
86 (message "In the prepare pages.")
87 (message (plist-get plist :base-directory))
89 (file-name-as-directory
90 (plist-get plist :base-directory))
93 (when (file-exists-p header)
95 (insert-file-contents header)
99 Now comes the publishing project:
100 #+BEGIN_SRC emacs-lisp
101 (setq org-publish-project-alist
102 `(("jamestechnotes-com" :components ("jamestechnotes-com-css"
103 "jamestechnotes-com-entries"
104 "jamestechnotes-com-pages"))
105 ("jamestechnotes-com-css"
106 :base-directory "~/src/wikis/jamestechnotes.com/css"
107 :publishing-directory "~/public_html/jamestechnotes.com/css"
108 :base-extension "css"
109 :publishing-function org-publish-attachment)
110 ("jamestechnotes-com-entries"
111 :base-directory "~/src/wikis/jamestechnotes.com/blog"
112 :publishing-directory "~/public_html/jamestechnotes.com/blog"
114 :publishing-function org-html-publish-to-html
115 :preparation-function jr/prepare-pages
119 :html-doctype "xhtml5"
121 :html-head-include-default-style nil
122 :html-head-include-scripts nil
123 :html-head ,jr/html-head
124 :html-preamble jr/prepare-pages
127 :sitemap-filename "blog.org"
128 :sitemap-title "Blog articles"
129 :sitemap-sort-files anti-chronologically
132 ("jamestechnotes-com-pages"
133 :base-directory "~/src/wikis/jamestechnotes.com/pages"
134 :publishing-directory "~/public_html/jamestechnotes.com"
135 :publishing-function org-html-publish-to-html
136 :preparation-function jr/prepare-pages
140 :html-doctype "xhtml5"
142 :html-head-include-default-style nil
143 :html-head-include-scripts nil
144 :html-head ,jr/html-head
145 :html-preamble jr/prepare-pages
148 :sitemap-filename "blog.org"
149 :sitemap-title "Blog articles"
150 :sitemap-sort-files anti-chronologically
154 The interesting thing to note here is the use of quasiquote ~`~,
155 which allows use of unquote ~,~ for ~:html-head~. ~:html-head~
156 requires a string, not a variable containing a string. The ~unquote~
157 and ~quasiquote~ allows this to function.
159 * TODO adfadf :noexport:
165 [fn:3] Git handles binary artifacts reasonably well. I just think such
166 shouldn't be done in general.
168 [fn:2] All of the code I write (that isn't owned by others) lives in
169 [[https://git.jamestechnotes.com][my git repositories]], including source for my websites.
171 [fn:1]Well, at least that my excuse. ;)