_______________________

                       HOW THIS SITE IS MADE

                           Nicolas Herry
                      _______________________


                            2017/11/10





1 How this site is made
=======================

  We are at the end of 2017, and blogging software is still a major
  topic of discussion among geeks. Well, not really, let's say I
  still find it interesting. Hmm... Actually, no, it's not even
  that; I guess I just wanted to brag a bit about my setup. Is
  there anything worth bragging about in my setup? I'm not even
  sure. Still, please keep reading!

  My objective with this site was to keep things simple: I wanted
  an easy and comfortable way to write the posts, minimal fuss when
  putting them online and as little server-side software as
  possible.


1.1 Writing posts
~~~~~~~~~~~~~~~~~

  I naturally use emacs to write the posts for this website. I
  actually use emacs for almost everything, as [I said here
  before]. I use [org mode] for that, and each post is a separate
  `.org' file. I only use a reduced set of properties, where I
  indicate the date the post was written, the author name, and the
  title. This means each post begins with the following preamble:

  ,----
  | #+TITLE: How this site is made
  | #+AUTHOR: Nicolas Herry
  | #+DATE: 2017/11/10
  | #+OPTIONS: toc:nil
  `----

  By default, org mode generates a table of contents, and although
  this might come in handy for some very long posts, it's generally
  useless to me here. The property `OPTIONS: toc:nil' disables this
  behaviour.

  Since I didn't want to type all this at the beginning of each and
  every file, I looked for a simple solution to insert it
  dynamically for me. There are many completion frameworks, and I
  could have written my own set of functions to do that, but there
  is already something called [yasnippet] which does an impressive
  job as a templating system. yasnippet is already part of my
  normal setup; all I had to do was create a template for my
  posts. This turned out to be very simple:

  ,----
  | # -*- mode: snippet -*-
  | # name: beastieboy
  | # key: BBP
  | # condition: (string-prefix-p "/home/kafka/org" (buffer-file-name))
  | # --
  | #+TITLE: $1
  | #+AUTHOR: Nicolas Herry
  | #+DATE: `(format-time-string "%Y/%m/%d")`
  | #+OPTIONS: toc:nil
  | 
  | * $1
  | 
  | $0
  `----

  In the above, I give this snippet a name, `beastieboy', as well
  as a key that I will be typing in the buffer to trigger the
  insertion of this template (`BBP', which seemed a rare enough
  combination of letters that any conflict with a real acronym
  should be avoided). I also control the insertion with a
  condition: yasnippet will only insert the template if the elisp
  code in the condition returns non-nil. Here, since I use org mode
  for many things, I wanted to contrain this template only to the
  posts for this website. An easy way to do this is to check the
  path of the buffer being edited. If it contains the directory
  where the posts are stored, then the template can be expanded,
  otherwise, yasnippet will just do nothing. The drawback here is
  that I am not being very subtle, and I have the path hardcoded
  and not even stored as a variable or anything. I will do the
  right thing; for now, it's good enough.

  The template continues with a separator, `--', which indicates
  that all that comes after it is the actual meat of the
  template. We find the preamble I presented above, with some code
  to dynamically generate the date. We also find three odd markers:
  one `$0' and two `$1'. The former indicates where the cursor
  should be put once the template has been inserted and filled, and
  the latter marks field the user must fill in. When the template
  is inserted, the cursor will first be positioned in the line
  `#+TITLE: _', instead of the `$1', and I will type in a title for
  the post. Since I have put more than one `$1' marker, yasnippet
  will automatically update the other markers with the same number
  with my typing. This trick allows me to store the title as a
  property for org mode as well as a header, without having to type
  it twice. When I'm done filling this field, pressing `TAB' takes
  me to the next field, or, if there aren't any, to where the `$0'
  is. I can then start typing the post.


[I said here before] <gopher://gopher.beastieboy.net/0/stuffiuse2017.txt>

[org mode] <http://orgmode.org/>

[yasnippet] <https://github.com/joaotavora/yasnippet>


1.2 Publishing
~~~~~~~~~~~~~~

  I publish the site in two steps, and everything here is once
  again done with emacs. I have defined two sets of projects for
  org mode in my configuration:

  ,----
  | (setq org-publish-project-alist
  |       `(
  | 	("org"
  | 	 :base-directory "~/org/beastieboy.net"
  | 	 :publishing-directory "~/beastieboy.net/"
  | 	 :publishing-function org-html-publish-to-html
  | 	 :recursive t
  | 	 :section-numbers nil
  | 	 :with-toc nil
  | 	 :base-extension "org"
  | 	 :html-head ,beastieboy-header
  | 	 :html-preamble ,beastieboy-preamble
  | 	 :html-postamble ,beastieboy-footer)
  | 	("org-images"
  | 	 :base-directory "~/org/beastieboy.net/images"
  | 	 :publishing-directory "~/beastieboy.net/images/"
  | 	 :base-extension "png\\|jpg\\|gif"
  | 	 :publishing-function org-publish-attachment
  | 	 :recursive t)
  | 	("org-js"
  | 	 :base-directory "~/org/beastieboy.net/js"
  | 	 :publishing-directory "~/beastieboy.net/js/"
  | 	 :base-extension "js"
  | 	 :publishing-function org-publish-attachment
  | 	 :recursive t)
  | 	("org-css"
  | 	 :base-directory "~/org/beastieboy.net/css"
  | 	 :publishing-directory "~/beastieboy.net/css/"
  | 	 :base-extension "css"
  | 	 :publishing-function org-publish-attachment
  | 	 :recursive t)
  | 	("org-remote"
  | 	 :base-directory "~/org/beastieboy.net"
  | 	 :publishing-directory "/ssh:beastieboy@beastieboy.net:/usr/local/www/beastieboy.net/"
  | 	 :publishing-function org-html-publish-to-html
  | 	 :recursive t
  | 	 :section-numbers nil
  | 	 :with-toc nil
  | 	 :base-extension "org"
  | 	 :html-head ,beastieboy-header
  | 	 :html-preamble ,beastieboy-preamble
  | 	 :html-postamble ,beastieboy-footer)
  | 	("org-images-remote"
  | 	 :base-directory "~/org/beastieboy.net/images"
  | 	 :publishing-directory "/ssh:beastieboy@beastieboy.net:/usr/local/www/beastieboy.net/images/"
  | 	 :base-extension "png\\|jpg\\|gif"
  | 	 :publishing-function org-publish-attachment
  | 	 :recursive t)
  | 	("org-js-remote"
  | 	 :base-directory "~/org/beastieboy.net/js"
  | 	 :publishing-directory "/ssh:beastieboy@beastieboy.net:/usr/local/www/beastieboy.net/js/"
  | 	 :base-extension "js"
  | 	 :publishing-function org-publish-attachment
  | 	 :recursive t)
  | 	("org-css-remote"
  | 	 :base-directory "~/org/beastieboy.net/css"
  | 	 :publishing-directory "/ssh:beastieboy@beastieboy.net:/usr/local/www/beastieboy.net/css/"
  | 	 :base-extension "css"
  | 	 :publishing-function org-publish-attachment
  | 	 :recursive t)
  | 	("beastieboy" :components ("org" "org-images" "org-js" "org-css"))
  | 	("beastieboy-remote" :components ("org-remote" "org-images-remote" "org-js-remote" "org-css-remote"))))
  `----

  The first set comprises `org', `org-images', `org-js' and
  `org-css'. They all point to different locations in the tree
  where I store all my data for this website. The first one deals
  with the posts, the next three configure org mode to just copy
  the files verbatim to their destination. All this is then
  regrouped under the composite project `beastieboy'. I use this
  first set of projects as a kind of pre-production: I generate the
  site locally on my PC, and I check how it looks, proofread the
  post, and so on.

  When I am happy with what I have, I trigger the publication of
  the second set of projects, those ending with `-remote' and
  grouped under `beastieboy-remote'. The configuration is
  identical, except for the fact that the destination folder is an
  ssh path to my server. org mode is then kind enough to call
  [tramp], the emacs mode for transparently accessing remote files,
  as the documentation says. In my case, tramp pushes everything
  recursively to my server, and the website is published.

  org mode allows the user to specify headers and footers for the
  generated pages, which is how I hook up the CSS bits to the
  articles. My configuration, in a dedicated `.el' file under
  `~/.emacs.d/', is straightforward:

  ,----
  | ;; custom header, footer, etc.
  | (defvar beastieboy-header
  |   "<link rel=\"stylesheet\" href=\"css/site.css\" type=\"text/css\"/>")
  | (defvar beastieboy-preamble
  |   "<div class=\"intro\">
  |      <h1><b>Beastie</b>Boy</h1>
  |      <p>FreeBSD, Lisp, Emacs, PostgreSQL & co.</p>
  |    </div>
  |    <div class=\"nav\">
  |     <ul>
  |       <li><a href=\"index.html\">Home</a></li>
  |       <li><a href=\"about.html\">About</a></li>
  |       <li><a href=\"contact.html\">Contact</a></li>
  |     </ul>
  |    </div>")
  | (defvar beastieboy-footer
  |   "<div class=\"footer\">
  |       &copy; 2017 %a.<br/>
  |       Created %d.<br/>
  |       Last updated %C. <br/>
  |       Built with %c.<br/>
  |       <img src=\"images/powered-freebsd.gif\" alt=\"Powered by FreeBSD\"/>
  |    </div>")
  `----
  In the above, I set the author's name to that found in the
  properties of the post (the `#+AUTHOR:' bit, called with `%a'
  here), the creation date for the post (taken from `#+CREATED' in
  the preamble, called with `%C'), the date and time the page was
  generated (called with `%d'), I indicate the version of emacs and
  org mode that I used to generate the page and I put a nice little
  blinking Beastie to show my love to the daemon.

  The website itself is handled by nginx, as a set of static HTML
  files. Since there is no dynamic part or anything, the
  configuration is kept to a minimum: a single line in `nginx.conf'
  to point to the document root.


[tramp] <https://www.gnu.org/software/tramp/>


1.3 What's coming/missing
~~~~~~~~~~~~~~~~~~~~~~~~~

  In my trying to keep things as simple as possible, I also left
  aside a few things that I arguably should look into: HTML5
  support, a proper mobile CSS, code-colouring in the examples, an
  index generated automatically (today, I still copy and paste all
  the titles in the index page), a better index with a split
  between short news and longer articles, an integration with
  [flyspell], the minor mode for spell-checking in emacs. I keep
  you posted.


[flyspell] <https://www.emacswiki.org/emacs/FlySpell>