Post about blogging with org.
[jamestechnotes.com.git] / blog / entry / blog-with-only-orgmode.org
blob9f290241bf55a5f6afe64040ba2dbc14bd9ad280
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
11 writing.[fn:1]
13 * Blog files setup
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
25 writeup]]: 
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
33     files.
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
58 pages.
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.
67 * Show me the code
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
73   (setq jr/html-head
74         (concat
75          "<link rel=\"stylesheet\" href=\"/../css/org.css\" />\n" ;; start with org.css
76          "<link rel=\"stylesheet\" href=\"/../css/main.css\" />"))
77 #+END_SRC
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
80 required.
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))
88     (let ((header (concat
89                    (file-name-as-directory
90                     (plist-get plist :base-directory))
91                    "header.html")))
92       (message header)
93       (when (file-exists-p header)
94         (with-temp-buffer
95           (insert-file-contents header)
96           (buffer-string)))))
97 #+END_SRC
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"
113            :recursive t
114            :publishing-function org-html-publish-to-html
115            :preparation-function jr/prepare-pages
116            :htmlized-source t
117            :with-toc nil
118            :section-numbers nil
119            :html-doctype "xhtml5"
120            :html-html5-fancy t
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
126            :auto-sitemap t
127            :sitemap-filename "blog.org"
128            :sitemap-title "Blog articles"
129            :sitemap-sort-files anti-chronologically
131            :makeindex t)
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
137            :htmlized-source t
138            :with-toc nil
139            :section-numbers nil
140            :html-doctype "xhtml5"
141            :html-html5-fancy t
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
147            :auto-sitemap t
148            :sitemap-filename "blog.org"
149            :sitemap-title "Blog articles"
150            :sitemap-sort-files anti-chronologically
152            :makeindex t)))
153 #+END_SRC
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:
160 afdafdafsfas
163 * Footnotes
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. ;)