Posts tagged "technology:":
About the website
I think every personal blog that is somewhat custom built should have documentation written on its design philosophy and implementation. I see this as an extension of the free-software ideal; you should not only be allowed but also able to extent and modify another program to your needs.
Design
The website is written in Emacs and in org mode, because I find the markup to be intuitive, natural, and easy1. I generally took a lot of inspiration from others using the same tooling as me, as well as from Gwern, Maggie Appleton and various other blogs and homepages I have read over the years. The colour scheme is a slightly adapted version of Protesilaos Stavrou’s modus themes. I find them visually pleasing, and they are apparently very accessible to those with impaired vision, for example with colour blindness. I use them daily in Emacs, and so they fit nicely visually on my desktop when editing content.
The primary font used is Goudy Bookletter 1911, but as a fallback font I also use Sorts Mill Goudy and the legendary Computer Modern, the default typeface used in TeX
. Code (Such as the TeX you just read) uses Protesilaos’ Iosevka Comfy font.
Static website generation
The main landing page (https://joarvarndt.se/) is handwritten in HTML and doesn’t change with a new generation of the site. The blog is all that is generated. It is done so using org-static-blog. I have an elisp
file that runs the necessary configuration code, and it looks like this:
(setq org-static-blog-publish-title "Joar von Arndt") (setq org-static-blog-publish-url "https://joarvarndt.se/blog/") (setq org-static-blog-publish-directory "~/Documents/blog") (setq org-static-blog-posts-directory "~/Documents/blog/posts/") (setq org-static-blog-drafts-directory "~/Documents/blog/drafts/") (setq org-static-blog-enable-tags t) (setq org-export-with-toc nil) (setq org-export-with-section-numbers nil) (setq org-static-blog-index-length 1) (setq org-static-blog-use-preview nil) (setq org-static-blog-page-header "<meta name=\"Joar von Arndt\" content=\"Joar von Arndt\"> <meta name=\"referrer\" content=\"no-referrer\"> <meta name=\"viewport\" content=\"initial-scale=1,width=device-width,minimum-scale=1\"> <link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdn.jsdelivr.net/gh/bitmaks/cm-web-fonts@latest/fonts.css\"> <link href=\"static/style.css\" rel=\"stylesheet\" type=\"text/css\" /> <link rel=\"icon\" href=\"static/favicon.ico\"> <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js\"></script> <script src=\"static/sidenotes.js\"></script> <script id=\"MathJax-script\" async src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\"></script>") (setq org-static-blog-page-preamble "<div class=\"header\"> <a href=\"https://joarvarndt.se/\"><img id=\"themeImageHeader\" src=\"vonArndtCrestBlack.png\" class=\"header-img\" alt=\"Crest\" width=\"50\"></a> <hr size=\"1\" width=\"100%\" align=\"center\"> </div>") (setq org-static-blog-page-postamble "<div id=\"archive\"> <a href=\"https://joarvarndt.se/blog/archive.html\">Other posts</a><script src=\"static/theme.js\" defer></script> </div>") (setq org-static-blog-index-front-matter "<a href=\"https://joarvarndt.se/blog/archive.html\"><h1 class=\"post-title\">All Posts</h1></a>") (setq org-static-blog-enable-tag-rss t) ;; For syntax highlighting of code (Like this). (setq org-src-fontify-natively t) (setq org-html-htmlize-output-type 'css) (setq org-src-preserve-indentation t) (setq org-image-actual-width nil)
This loads the required javascript2 and CSS for themeing, both of which you should have received if you’re reading this. I am a big fan of org-static-blog due to it’s simplicity3, extensibility (its just a simple HTML static site) and obvious org-mode support. I used to use Hugo, a widely praised static website generator, but it only has nominal org-mode support, it requires a special non-org-mode YAML frontmatter that I really dislike. When writing a post, I prefer to leave formatting mostly out of it, and with my main focus on text. Tinkering with the website’s appearance is great fun of course, but I like to keep the two as separate activities. Writing any sort of special syntax brings me out of the experience, and that is partly why I wrote my own javascript to create sidenotes out of basic pandoc (and therefore org-mode) style footnotes.
Sidenotes
The sidenotes are heavily inspired by Gwern and Tufte CSS, but the Gwern sidenotes.js
is not portable and seems way too complex for my needs (it is 1150 lines long!!). In comparison, here is the the script that creates sidenotes. It is merely 70 lines long, including whitespace and comments. It also allows for easy reading on mobile, vertical monitors, and JS-free browsers, since if the dimensions are not adequate for displaying sidenotes or the javascript doesn’t run the content does not disappear. Instead it is shown as a footnote at the bottom of the page with bidirectional links between it and the reference. The Tufte CSS approach is admirable — relying only on pure HTML and CSS — but my aforementioned dislike of jumping between prose and “syntax” means that is is not an approach for me. I have however taken the liberty of inspiration from Tufte CSS in the CSS of sidenotes and margin notes. Margin notes are written in the form of an org-mode export block, and so have to be located at the beginning or end of paragraph.
This is how I write a margin note!
#+begin_marginnote This is how I write a margin note! #+end_marginnote
I can do this since org treats “special blocks” as a <div>
with a synonymously named marginnote
class. This can then be styled however you want using CSS. Margin notes are usually not as critical in my mind as foot/sidenotes, since they serve merely as a general guide to the text rather than an explicit pointed “reference”4. That’s why margin notes are not displayed on mobile devices. This is an opinionated change from Tufte CSS’ approach, where margin notes are instead treated as unnumbered sidenotes when there is no margin to display them in.
Hosting
The website is hosted on my own server at home, on an Intel NUC machine. It runs Debian GNU/Linux and serves the website primarily through an NGINX web server, but the Diplomacy page is served through a gunicorn server that displays a python application so that users can input data that is then saved. I use loopia as my domain registrar, primarily due to having been recommended them from people I trust, however I have made no significant research into alternatives myself. After writing the posts I used to use sftp
to remotely connect to the server from my desktop, laptop, or phone (through Termux) and upload my files but this became quite tedious to do, so I wrote a quick script in elisp that does all this for me:
;;; blogPublish.el --- Summary: ;;; Uploads the contents of the blog folder to the required one on the server. ;;; Commentary: ;;; Probably not the most elegant nor beautiful solution, but it seems to work for me. ;;; The HTML files on the remote server are first deleted through tramp, and then ;;; the content is reuploaded in case there are any changes. Since plain text is so ;;; quick to upload there is no issue with reuploading unaltered content. Video files ;;; are however quite large and so aren't reupload or deleted. This is usually not a ;;; problem since the only work being done iteratively is writing. ;;; Code: (require 'org-static-blog) (defun blog-delete-remote-html () "Deletes all html files on the server." (let ((tramp-default-method "ssh") (remote-directory "/ssh:jovo@parana:/var/www/html/blog/")) (with-current-buffer (find-file-noselect remote-directory) (let ((default-directory remote-directory)) ;; Ensure the remote directory is accessible and its contents are loaded (revert-buffer) (dolist (file (directory-files default-directory t "\\.html$")) (when (file-exists-p file) (message "Deleting %s ..." file) (delete-file file) (message "Deleted all .html files in %s" remote-directory))))))) (defun upload-blog-contents () "Uploads the required HTML to the blog via SCP for async." (let* ((local-dir "/home/jovo/Documents/blog/") (remote-dir "/var/www/html/blog/") (remote-host "parana") (remote-user "jovo") (remote-files-tramp (delq nil (mapcar (lambda (file) ;; Use TRAMP to check the contents of REMOTE-DIR. (when (file-regular-p file) file)) (directory-files (concat "/ssh:" remote-user "@" remote-host ":" remote-dir) t "\\`[^.]"))))) (dolist (file (directory-files local-dir t "\\`[^.]")) ;; Exclude "." and ".." (when (file-regular-p file) (let* ((file-name (file-name-nondirectory file)) (remote-file (replace-regexp-in-string local-dir "" (concat remote-user "@" remote-host ":" remote-dir file)))) (if (and (string= (file-name-extension file) "mp4") (member file-name (mapcar 'file-name-nondirectory remote-files-tramp))) (message "%s already exists on remote, skipping upload." file) (message "Uploading %s to %s" file remote-file) (async-start-process "scp-upload" "scp" nil file remote-file))))))) (defun website-publish () "Function running after org-static-blog-publish to publish to the website." (interactive) (blog-delete-remote-html) (upload-blog-contents)) (advice-add #'org-static-blog-publish :after #'website-publish) ;;; blogPublish.el ends here.
The function is triggered using advice-add
after org-static-blog-publish
so as to fit seamlessly into my preëxisting workflow. It removes old HTML content from the website using TRAMP
, and then uploads it using scp
. I avoid uploading the video files since they are quite large and only need to be uploaded once. TRAMP
is quite capable of uploading the files, but it is quite slow compared to scp
. Deleting files however takes a comparatively short amount of time. Authentication is handled by tailscale SSH, so I don’t have to expose port 22 to the public internet and don’t have to enter any passwords for upload.
Footnotes:
Why would any markup not use “//
” to italicise text? Markdown’s use of just asterisks is admirable, but unintuitive for reading in plaintext (Does two asterisks mean italic or bold?). Org mode’s choice of using __
to underline text is similarly beautiful.
For dark/light mode, mathjax, and of course these sidenotes (But only if you are reading on a wide screen). Sadly the external mathjax reference makes this nontrivial javascript, but that is a sacrifice I am willing to make for easy and beautiful \(\LaTeX\) renderings.
From the repository:
Above all, I tried to make org-static-blog as simple as possible. There are no magic tricks, and all of the source code is meant to be easy to read, understand and modify.
Even if it is not a literal reference, but it may often be, especially when it comes to my academic writings.
Writing About Jacques Ellul
I am by no means an expert on Ellul, I have merely read three of his books (Presence in The Modern World, The Technological Society, and The Meaning of the City) But in trying to communicate his influence on my thinking, I have inadvertently written many times about him, albeit at an all too basic level. There are many theories claiming to explain all of human history, or at least the structure of our current society, but Ellul’s technique works because of its simplicity and deliberate vagueness. It is however this quality that makes explaining Ellul to others so challenging. Here is one example of an attempt made by me to quickly summarise the central ideas of Ellul’s technique.
The technical concept can be briefly summarized as a conglomerate of thoughts, methods, and approaches considered to be objectively the best for achieving a purpose. It is important to distinguish this concept from technology, such as computers, engines, weaving machines, and so on. Technology is merely a consequence of technique, not the cause. People in modern society can no longer imagine life in the way that prehistoric and medieval populations lived. Almost all problems are expected to have technical solutions; if the solution to a problem requires something to be done, then the problem is technical. This seems almost tautological — if nothing needs to be done, is there really a problem? However, problems often arise from attempts to improve the situation, and technique always demands solutions to increasingly complex problems.
This is by no means a short summary, it is longer than the introductory paragraph. But to compress it inevitably means allowing for serious misinterpretation, and readers are not often familiar with an obscure post-war anarchist christian sociologist. This is made even more difficult owing to the fact that technique is applicable to such a wide number of disparate fields. It is for this reason that explaining Ellul has become dreadfully boring, despite the fact that I recognise Ellul as a figure that would bring enormous comfort — I almost dare to say enlightenment — to a great number of people. But I feel compelled to do so, again and again, because I too am a member of our technical society. Just like Kaczynski1 I feel compelled to utilize technique against itself despite being fully aware of the fruitlessness of doing so.
Ellul naturally takes inspiration from Marx’ historical materialism as well as Hegel’s idea of Geist. The main difference is that where Marx and Hegel both see an end point, a perfect communist society and Absolute knowledge respectively, Ellul instead sees technique as an ever-expanding being driven only be a need to encompass every facet of human society. Technique per definition can have no limit because when it reaches absolute mastery over any one idea it will simply move on to greater and greater scales. Only something like the paperclip maximizer converting all of the mass-energy in the universe would ever reach a hard limited; technical society however still hopes for a continued advancement after that.
Since technique dominates every area of society, it has become relevant for an untold number of discussion I have come across. For example, in an article about the possibly planned use of TikTok by the CCP to destroy western civilization, Gurwinder effectively makes clear how Wang Huning describes America’s crisis of technology, and how it shares similarities with Nick Land’s view of accelerationism (all in attempt to expose a CCP accelerationist plot). While I see Gurwinder’s thesis as fundamentally incorrect, the moral decline of western civilisation is not to be solved through any return to “traditional moral values”, technique only moves forward, though it very well might be marketed as such2. Gurwinder quotes Land’s A Quick-and-Dirty Introduction to Accelerationism:
The point of an analysis of capitalism, or of nihilism, is to do more of it. The process is not to be critiqued. The process is the critique, feeding back into itself, as it escalates. The only way forward is through, which means further in.
Land is entirely correct in his description of the symptom, but misattributes the cause. Capitalism is not a driving force of anything, it is simply a state of affairs itself caused by technique. As I write in my essay on the philosophy of nuclear weapons, technique is inherently alienating and a cause for nihilism, as Land has realized. But capitalism is not the cause of this; Soviet socialism is an even purer form of technique3. The planned economy requires a constant need for things to be done, for organisational meetings and for statistics to be collected so that more accurate and better choices can be made, even at exorbitant costs. Why socialism ceased in the USSR and China was because of a technical choice that free-market capitalism was more efficient, and it was this decision that Fukuyama described as his end of history; the triumph of free market liberal democracy as the most efficient mode of societal organisation. This does not mean that it will remain so forever of course, but that it is simply meaningless to discuss the issue, for when something more efficient comes along, it will simply be done.
Footnotes:
Kaczynski was also a reader of Ellul, and found that his experience of reading La Technique hugely influential.
Things like the Glorious Revolution, the rise of Napoleon, and the Treaty of Versailles were all seen as a return to the normalcy of things and to the romanticised idea of the times that came before, but they were all of a fundamentally progressive nature in their consequences.
In fact, the soviet establishment discusses the concept of Taylorism to a great extent, pursuing an ideal of industrial management that disregards the indiviudal organic connections and methods practiced throughout most of human history. Taylorism in its goal is a clear example of large-scale technique.
Diplomacy Today: A backstabbr and AI powered newspaper
Diplomacy Today is a python program and corresponding flask application that serves and hosts an early-twentieth-century-style newspapers generated from the turn orders of a game of Diplomacy hosted on backstabbr. The idea, and a large portion of the core code, are not my work, and I deserve none of the credit for it. But the original program seems to have been abandoned last year, and was perhaps only used for one game. But that is the beauty of free software, I have taken nraw
’s original code and iterated upon it over the course of, so far, four games. It now contains more features and improved polish that builds upon the basic functionality of a GAI generated in-universe newspaper. I attempted to rewrite the program in chez scheme as a learning exercise, but ended up not using it as python has some nice libraries that I couldn’t bother to reimplement in scheme.
To use it you should:
- Make sure Mozilla Firefox is installed.
- Clone the Github repository:
git clone https://github.com/JanJoar/diplomacy_today.git
cd diplomacy_today
- Install all the python packages:
pip install -r requirements.txt
- Get your OpenAI API key and export it to the
OPENAI_API_KEY
environment variable. - Generate the newspaper:
python3 main.py
- Run the web application using something like gunicorn:
gunicorn -b 0.0.0.0:1914 app:app
If you have any issues with installation or want to features, feel free to contact me, preferably at my email at joarxpablo@pm.me so that I can improve the program.