Making a web-page is extremely easy. Anyone can go use a WYSIWYG editor and mock up a page in minutes, or use a tool like wordpress to make websites with any functionality you wish by adding widgets from a catalog. But be honest, someone making a blog doesn't need any of that. I'm not dogmatic -- use whatever makes you happy, but be honest; paying 96 dollars a year for wordpress so you can "customize fonts and colors" is absurd. For the website you're seeing now, it cost about 60 dollars for three years of hosting. Don't overspend. There's beauty in the old style websites. With my blog, I've tried to emulate it and in doing so have developed a workflow to make it a lot easier. It's a kludge but a very personal one.
The Gameplan
One of the first steps to ascending to command-line wizardhood is understanding that everything is text. Yes, even photos. If it's not text yet, there are tools for it. If there are no tools for it, there will be. That's why there's such an emphasis on command line tools; they're the most effective way to manipulate text in bulk. I like to stick to pure text when practical and I'm not breaking that tradition with my website. I edit everything in normal Emacs buffers and use an external browser (GNU Icecat) to preview it. My window manager is EXWM so it integrates seamlessly into the workflow. One of these days I want to make the jump to a full Lisp browser like Nyxt but I haven't really found the time. Back on topic: HTML is no exception to the "everything is text" policy. It's in-fact one of the simplest textual representations of data I know of. A CSV file has the capacity to be more complex than HTML. So, we can use and abuse HTML with a suite of text based tools. Here's the spread:
GNU M4
What?
Writing HTML by hand can be a pain in the ass, and reading it can be an even bigger pain in the ass. But, there are solutions that don't cost 96 dollars a year. GNU M4 is a macro processor. At its simplest, the user describes some symbol-value pairs: The user could declare that the symbol foo is equal to the value of bar. If M4 comes across foo in its input, it will be transformed into bar in its output. Expanding upon this functionality, M4 also allows you to specify the location of the replaced argument. Using the `$1' variable lets you specify where you want the first argument to appear. You can keep increasing this number if you have multiple variables, but it may be more practical to use `$@' to display all arguments. Some examples:
LOVE(steak)
>`I love steak so much! :)'
define(HATE, `I hate $1 and $2 so much!')
HATE(red, green)
>I hate red and green so much!
define(WANT, `I want $@')
WANT(an xbox, a car, a bike)
>I want an xbox, a car, a bike.
Why?
Despite this looking like a programming langauge, M4 does not interact with anything it does not recognize. You can write whatever you want it'll output it just as it is, unless it's recognized as a macro. For example, if you wished to use M4 to write HTML like I do, you would have the freedom to write HTML directly into an M4 file. This means you do not have to make macros for every little thing and you're free to write directly should the situation call for it. This grants the writer powerful abstraction features that do not get in the way. Everything annoying and complicated is placed on M4's shoulders and the writer is free to write without remembering how a link should be formatted or the hassle of writing <'s and >'s as &\lt and &\gt when you just want to embed some HTML.
In addition, this abstraction can make changing the presentation of your site much easier than contemporary website editors; you can abstract colors, font styles, size and more all away into macros. When I want to put emphasis on a word, I wrap it in an "ACCENT" macro. As the time of me typing this sentence out, the current accent is just making the word bold. If I want to change the color instead, which I probably will end up doing, I do not have to edit everything I put in bold, I just have to edit my one "ACCENT" macro and everything will be changed accordingly.
Macros of Interest
Here are a few macros I use. The other ones are mostly trivial. If you'd like more inspiration, check the manual or read the article listed at the top. For context, all these macros are placed into one file I call "standard_header.m4". I then use the include directive at the top of every page I'm writing. That way, I can change everything in one place and also include some standard formatting information. More on that later.GNU Make
Make?
When one uses Make, it's almost always in the context of compiling non-trivial programs. But Make is effectively an advanced bash script, it's calling other commands to do the heavy lifting. In the manuals' own words, "You can use it to describe any task where some files must be updated automatically from others whenever the others change." Indeed, we are interested in updating .html files whenever we change our corresponding .m4 files. Make is simply a list of instructions on how to update or create files from a set of original files. It's designed so, on subsequent runs, it only operates on whats actually changed. This list of instructions is called a "Makefile". Using Make, it can do all the heavy lifting of manually creating .html files, sorting them, naming them, and updating them. We can just create our files and the right thing will happen when we run Make. Here's my solution:
all: $(OBJS)
%.html : %.m4
-m4 $< | tidy -i --force-output yes -q --tidy-mark no 2>/dev/null > finished_pages/$@
Make can be extended for really whatever you want. If you want javascript, I'm sure it could do that too. When writing this, I don't really feel that my page will ever need it.
GNU Emacs
I thoroughly enjoy Emacs because of its versatility and letting tools integrate with each other. With Emacs, I can edit the CSS and HTML for my page and have it update in real time. I find it very easy to edit CSS, HTML, Makefiles, and M4 all at the same time since they all have their own respective modes with syntax highlighting and other useful features. In any case, here's the package that makes the "real time" magic happen:
Impatient Mode
Impatient Mode is a fantastic tool that integrates simple-httpd mode with one of your Emacs buffers to have its contents displayed in real time. You simply enable "impatient-mode" on the buffers you want to serve up and it'll be available at localhost:8080/imp for you to see. Remember, if you want to edit CSS in real time you need to enable impatient mode on the style sheet. If you don't have Emacs, try this:
entr
Entr is a useful thing that's not really related to Emacs and lets us run a command whenever selected files change. For us, we want to run our Makefile whenever our .m4 file changes. This lets us get some of the "real time" benefit even when we're using M4.auto-revert-mode
Built into Emacs and pairs very nicely with Entr, Make, and
impatient mode. Simply put, a buffer with this mode enabled
will automatically update to the files current contents
whenever the file changes. If you make changes by hand it will
not automatically overwrite your changes and you'll have to use
M-x revert-buffer to do it manually.