org-mode website
How I'm managing this website with org mode
Just as a disclaimer, I'm still at the very start on this site project, so this article will probably be somewhat constantly updated while I try things out.
Resources
The most relevant resources I read was the community documentation on using org-mode (org-publish) for websites, and the org-mode manual itself, specifically the org-publish and source code sections.
Directory structure
. ├── aboutme.org # This is the "about me" section you can click on the index ├── css │ ├── CozetteVector.ttf # The custom font, my favourite │ └── stylesheet.css # The css stylesheet ├── img # The images directory │ ├── irl.jpg │ ├── keeb2.jpeg ├── index.org # The website index └── txt # Where I keep the articles └── index.org # The "all articles" page
Once I make some art that I'm actually proud off I'll have a gallery index too.
This site directory is kept separate from the actual site I'm pushing to neocities. The directory with the HTML files gets generated with org-publish-project
, which runs a bunch of hooks you will see in the configuration.
Configuration
Keeping the directory structure in mind, there's some configuration on my init.el
file that is responsible for generating the directory structure, handling links, themes and even more things that I disable for the sake of keeping my site less cluttered (i.e making sitemaps automatically, or pre/postamble).
(setq org-publish-project-alist '(("org-notes" :base-directory "~/dox/notes/projects/site/" :base-extension "org" :publishing-directory "~/site/" :recursive t :publishing-function org-html-publish-to-html :headline-levels 4 ; Just the default for this project. :auto-preamble t :section-numbers nil :with-toc nil :html-head-include-default-style nil :html-head "<link rel='stylesheet' type='text/css' href='css/stylesheet.css'>" :html-postamble nil ) ("org-static" :base-directory "~/dox/notes/projects/site/" :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|ttf" :publishing-directory "~/site/" :recursive t :publishing-function org-publish-attachment ) ("org-txt" :base-directory "~/dox/notes/projects/site/txt/" :base-extension "org" :publishing-directory "~/site/txt/" :recursive t :publishing-function org-html-publish-to-html :headline-levels 4 ; Just the default for this project. :auto-preamble t :section-numbers nil :with-toc nil :html-head-include-default-style nil :html-head "<link rel='stylesheet' type='text/css' href='../css/stylesheet.css'>" :html-postamble nil ) ("org" :components ("org-notes" "org-static" "org-txt")) ) )
First, there's "org-notes"
, where most of the work is done:
:base-directory
is the address of the separate directory where I keep all the.org
files:base-extension
only operates with.org
files:publishing-directory
is where the generated html files go:recursive t
makes it works on the directory recursively duh:publishing-function
is the internal function that's run for converting the.org
files into html:section-numbers nil
prevents the headers from having 1. numbers, just a aesthetic thing:with-toc nil
disables the automatically generated table of contents, there's only a few situations where I might want it, for that I can overwrite this option in the files themselves with "#+HTML_OPTIONS: toc: t
":html-head-include-default-style nil
disables the default style, since I have my own stylesheet:html-head
has the tag necessary for referencing the stylesheet:html-postamble nil
disables the postamble, I don't have anything significant to put at the bottom of every page.
Then, there's the "org-static"
bit where all the non-html stuff get exported and it's links handled.
Also, there's "org-txt"
, an extra thing I put in for handling linking stuff that is a directory above.
Finally, with the line ("org" :components ("org-notes" "org-static" "org-txt"))
all those options run when I do a org-publish-project org
On a side note, for you to be able to change image sizes, you have to put (setq org-image-actual-width nil)
somewhere in your configuration. You can change image sizes by putting #+ATTR_HTML: :width 500px
one line above the image you want to resize. You can do way more with this technique, reference the documentation for more info.
"Dynamic" stuff
My site has no JS, so there's no real "dynamic" stuff, but there's some stuff that gets generated and written in some web pages automatically.
For now, there's only automation around the "articles". In the index.org
and txt/index.org
pages I have this code block:
#+begin_src bash :exports results :results output list raw :shebang "#!/bin/bash" :tangle test.sh readarray -t files < <(ls -t1 txt | head -n 5 | grep -v "index.org") for x in "${files[@]}"; do title=$(grep -m 1 "#+title:" txt/"$x"| cut -d ':' -f 2-) date=$(stat -c "%y" txt/"$x" | cut -d ' ' -f 1) echo "$date [[./txt/$x][$title]]" done \#+end_src
Inside the block there's a simple bash script that echoes out a list of the 5 most recent articles, the results are written to the page in a #+RESULTS:
block right below it, and through the header arguments, the source code itself doesn't show up in the page.
#begin_src bash
indicates that it's a bash shell script:exports results
is the part that makes that the source code block doesn't show up in the final HTML file- In the
:results
argumentoutput
makes that results of the script get written out verbatim,list
formats the results into a standard org-mode list, and finallyraw
makes it so that it's just normal text, not inside a source code block like in the default configuration
For extra there's the :shebang
arguments which are a bit redundant since I indicated that it was a bash script, and the :tangle
option points to a file I was testing and running shellcheck in.
And just for the record, by default if you try to evaluate any source code block that isn't elisp, org babel will fail. To fix this you have to put (org-babel-do-load-languages 'org-babel-load-languages '((shell . t)))
somewhere in your configuration. You can also add more languages by customizing the variable (C-h v
).
Publishing
Every time I want to reference some file, or write something in a org file, it goes in the "~/dox/notes/projects/site
" directory. When I'm done I do a M-x org-publish-project <RET> org <RET>
which converts all the files to HTML, handles all the links and runs all the code responsible for parts of the page. Then I open a terminal, navigate to the "~/site/
" directory and run neocities push .
, which pushes all the new/modified files and skips the unmodified ones (I should probably automate that with a entr
daemon).