diff options
Diffstat (limited to 'blog/posts')
| -rw-r--r-- | blog/posts/hestia/content.md | 101 | ||||
| -rw-r--r-- | blog/posts/hestia/hestia.webp | bin | 0 -> 90082 bytes | |||
| -rw-r--r-- | blog/posts/hestia/meta.json | 10 | ||||
| -rw-r--r-- | blog/posts/let-there-be-light-theme/blog.webp | bin | 0 -> 67994 bytes | |||
| -rw-r--r-- | blog/posts/let-there-be-light-theme/content.md | 22 | ||||
| -rw-r--r-- | blog/posts/let-there-be-light-theme/deeper.html | 46 | ||||
| -rw-r--r-- | blog/posts/let-there-be-light-theme/meta.json | 7 | ||||
| -rw-r--r-- | blog/posts/making-this-blog/book.md | 13 | ||||
| -rw-r--r-- | blog/posts/making-this-blog/content.md | 78 | ||||
| -rw-r--r-- | blog/posts/making-this-blog/meta.json | 9 | ||||
| -rw-r--r-- | blog/posts/making-this-blog/yggdrasil.webp | bin | 0 -> 24140 bytes | |||
| -rw-r--r-- | blog/posts/still-working-on-this/content.md | 131 | ||||
| -rw-r--r-- | blog/posts/still-working-on-this/main_domain.webp | bin | 0 -> 11464 bytes | |||
| -rw-r--r-- | blog/posts/still-working-on-this/meta.json | 9 |
14 files changed, 426 insertions, 0 deletions
diff --git a/blog/posts/hestia/content.md b/blog/posts/hestia/content.md new file mode 100644 index 0000000..c592078 --- /dev/null +++ b/blog/posts/hestia/content.md @@ -0,0 +1,101 @@ +So I've been working on this multipurpose custom voice assistant for a while now and I think it's time to write a blogpost about it. + +## A project years in the making (technically) +I've started this project last summer, but after getting through the most interesting/hard part (or so I thought), I quickly gave up on it. + +The initial idea was to create a Siri/Cortana/Google Assistant style **voice assistant** for my PC. I wanted to use voice control for basic tasks like opening apps and locking the screen. + +The most interesting part for me was the **voice interpretation**, as I've never done anything similar before. So I've started with looking into all kinds of speech-to-text solutions. I've found a few open-source projects, but by that time most of them had been discontinued in favor of OpenAI's [Whisper](https://github.com/openai/whisper). So I've downloaded Whisper and started to experiment. + +For starters I wanted to make a straightforward version, where I could **activate** the "listening mode" **with a buttonpress**, and it kept listening **until I press the button again**. So I made a shortcut in Sway (my desktop environment) to run a shell script that looked something like this (it's actually a newer version): + +<div class="code-block"><p><span class="blue">#!/bin/bash -eu</span></p> +<br> +<p><span class="cyan">FIFO_PATH</span>=<span class="yellow">"</span><span class="green">/tmp/hestia-listening</span><span class="yellow">"</span></p> +<br> +<p><span class="yellow">if</span> <span class="red">[[</span> <span class="yellow">-p "</span><span class="magenta">$FIFO_PATH</span><span class="yellow">"</span> <span class="red">]]</span><span class="yellow">; then</span> + <span class="yellow">echo >> "</span><span class="magenta">$FIFO_PATH</span><span class="yellow">"</span> +<span class="yellow">else</span> + <span class="cyan">SCRIPT_DIR</span>=<span class="magenta">$(</span> <span class="yellow">cd</span> <span class="red">--</span> <span class="yellow">"</span><span class="magenta">$(</span> <span class="red">dirname --</span> <span class="yellow">"</span><span class="magenta">${BASH_SOURCE[</span><span class="green">0</span><span class="magenta">]}</span><span class="yellow">"</span> <span class="magenta">)</span><span class="yellow">" &></span> <span class="red">/dev/null</span> <span class="yellow">&& pwd</span> <span class="magenta">)</span> + <span class="cyan">MODULE_NAME</span>=<span class="magenta">$(</span><span class="red">basename</span> <span class="yellow">"</span><span class="magenta">$SCRIPT_DIR</span><span class="yellow">"</span><span class="magenta">)</span> + <span class="yellow">cd "</span><span class="magenta">$SCRIPT_DIR</span><span class="yellow">"</span> + <span class="yellow">source</span> venv/bin/activate + <span class="yellow">cd</span> .. + python -m <span class="yellow">"</span><span class="magenta">$MODULE_NAME</span><span class="yellow">"</span> +<span class="yellow">fi</span></p></div> + +The script is pretty simple: it looks for a **fifo (named pipe)** on a predefined path. If the fifo exists, the script **echoes a newline into it** (it's going to be a signal for the voice assistant); **otherwise start the voice assistant** script. When the main script started, it then created the fifo and was waiting in a loop, trying to **read it**. + +Whenever the fifo had some content, the voice assistant script **started recording the microphone input** or **stopped it** if it was already recording. After this the **temporary audiofile was fed into Whisper**. With this I had a simple solution for getting the user's voice input. Unfortunately this was where the magic stopped. I had no meaningful way of interpreting the text output of Whisper, other than matching to some keywords. I made some proof of concept commands, like **locking the screen**, tried them out. I also created some pre-generated text-to-speech generic responses (like "At your service!" or "Welcome back!") to make it more human-like. Then I lost interest in the project. + +## Revival +About a year later, while organizing my projects I wanted to write about on the blog, I came across this code again. Personal assistant tools (like Chat-GPT's voice assistant mode) were also frequently talked about in the news, and I was thinking about setting up [Home assistant](https://www.home-assistant.io) at my place for a while. Eventually these all came together into a single idea: + +"""What if I made my own personal assistant?""" + +I started to brainstorm. And I have to say, I came up with a **LOT of ideas** and features. I'm not even going to list them all here, because I have little hope of ever implementing them all, but if I wanted to I could write blogposts only about this project for years, so that's a relief at least. + +The basic idea was the following: if I wanted to make this assistant useful, I had to solve the biggest issue I had in the original project first. So I did just that. + +## The most important part +Buuuuut... of course I had to find a **new name** for the project first. I can't just call it "voice-assistant" like before, especially since I was planning to make this feel like an AI assistant from some sci-fi or cyberpunk story. I think I was somewhat influenced by [Hades II](https://en.wikipedia.org/wiki/Hades_II), the game which I was playing with at the time. Also, I really liked how all the AIs are named after Greek gods in ||spoiler1||Horizon: Zero Dawn||. So in the end I came up with **Hestia**, the Greek goddess of hearth and home (like a home assistant, get it?). For a while I was ruminating on calling it HestAI but in the end I dropped the idea. + +## HassIL to the rescue +So obviously I could have used some **large language model** to interpret the speech-to-text output, but this was just the thing I **wanted to avoid**: big overhead and/or running non-locally, non-deterministic/unknown random factor and last but not least, I could hardly call it my own. + +I started to look around how natural language processing was done like 10 years ago, and how old chatbots worked. Luckily I didn't have to go too deep in the rabbithole, because [Mike](https://mikesweb.site), a friend of mine, mentioned I should check out how they did it in Home assistant. + +[HassIL](https://github.com/home-assistant/hassil) (Home Assistant Intent Language) is a separate module inside the Home assistant project, and it does _exactly_ what I needed. It has a pretty easy yaml config layout to set up some insane flexible expressions. HassIL then can use these expressions to interpret a text input, understand the **intent** of the user, and even extract some **intent specific data** from the sentence. + +Here's an example from the **config** I set up for Hestia: + +<div class="code-block"><p><span class="red">language</span>: <span class="green">"en"</span></p> +<p><span class="red">intents</span>: + <span class="red">HesExecuteProcess</span>: + <span class="red">data</span>: + - <span class="red">sentences</span>: + - <span class="green">"<execute> <process> [<in_workspace>]"</span> + <span class="red">slots</span>: + <span class="red">domain</span>: <span class="green">"process"</span></p> +<br> +<p><span class="red">expansion_rules</span>: + <span class="red">process</span>: <span class="green">"[the ]{process}"</span> + <span class="red">execute</span>: <span class="green">"(execute|open|run|start)"</span></p></div> + +HassIL have some pretty neat way of defining flexible sentences. The meaning of the different symbols are the following: +* anything between **<>** are subjects to an **expansion rule**; some (usually more complicated) expression defined in the same config, or in a global config file. Basically an alias. +* **[]** marks an **optional** part of the sentence. Can be used for parts where you might or might not use articles (the, a, an), or when you might want to specify some extra info (in this example the workspace). +* with **{}** you can set a **slot**, which is basically a variable/extra info in the sentence, with predefined values (for example: in Home assistant all rooms, device names, etc. are provided to HassIL at the start). +* you can specify **alternative words/phrases** for the same thing, all separated by **|**. +* you can also define **permutations** of words/phrases with **;** (not used in this example). +* when defining alternative words or permutations, you need to enclose them in **()** if they are non-optional (or **[]** if they are) + +Let's take a look at the <span class="code-block-wrap"><span class="green"><execute> <process> [<in_workspace>]</span></span> part, as this is the actual **sentence for the intent of opening an app**. As you can see it starts with two expansion rules (both defined at the end of the config). The sentence has to start with a word of the options "execute", "open", "run" and "start". This is followed by a process/program name (all available programs are provided to HassIL at the start), which can stand with definite article "the" or on its own. + +The last part of the sentence is the workspace that can be optionally defined. In Sway (the window manager I use) workspaces are similar to workspaces in Gnome, or virtual desktops in KDE and Windows. It's basically a group of windows you keep on "one screen", and you can change between these screens by changing the workspace. + +By default, I use at most 10 workspaces in Sway, so in the global config the workspace expansion rule is set up the following way: +* it has to be a number between 1 and 10 +* it can be either in the form of "workspace N" or "Nth workspace" (defined grammatically correctly for the exception numbers) + +You can check this out in detail in the [repository](https://git.wazul.moe/hestia/tree/sentences/_common.yaml). + +## Breathing life into the computer +Now that some basic commands were working, I wanted to concentrate on making this whole assistant a bit more **humanlike**. + +For now, I was not concentrating on the voice reply. In the previous version I used pre-generated text-to-speech voice files (by just simply playing them). But the more I thought about it, the more it became clear that the assistant would be very limited, if it could not react with dynamic data (like referring to something the user asked about or reading new post on an RSS feed). I have looked into some solutions for text-to-speech generation on the fly, but this will be a topic for another blogpost. + +However, I wanted another part implemented as well. It was always part of my goal to have some sort of **UI popup with the face** (of the AI assistant) on the computer screen whenever it is talking. Of course with **different kind of expressions** depending on the situation, and possibly even changing it mid-sentence, similarly how **visual novels** work. + +I was already using [mako](https://github.com/emersion/mako), a lightweight Wayland notification daemon, which luckily had just the flexible configuration options I needed. This way, if I fire a **desktop notification** with [libnotify](https://github.com/GNOME/libnotify), it can display the content the way I want it. + +I defined the colors, icon location and stuff like that in the mako config file under <span class="code-block-wrap magenta">[app-name=hestia]</span>, this way my voice assistant messages will have a unique look compared to other system messages. So when you ask Hestia to start firefox, this is the result (other than firefox actually opening): + + + +Of course the statue is a placeholder image, until I have the time to **draw** (!!!) some artwork for the assistant myself. Expect some weeb animestyle stuff coming soon™. + +## What plans do the Fates have for Hestia? +I'm planning to clean up some things in the immediate future. For example **make a more flexible and extendable response system**. I already started to make the whole project a bit **more modular**, for example you can use text input instead of voice, which is much more convenient way for testing on my laptop with a not so good microphone. I plan to do the same with output, so in the end the assistant could run on different kind of devices with different kind of input and output methods (for example in a local server with Home assistant capabilities and maybe control it over chat messages, who knows). And of course I want to **extend the features** so I can start using it for actual helpful tasks already. As I've said, I have tons of ideas. + +Now that I have more free time to work on this project, I will hopefully start posting more frequently. Until then however, it's farewell. Thank you for reading! diff --git a/blog/posts/hestia/hestia.webp b/blog/posts/hestia/hestia.webp Binary files differnew file mode 100644 index 0000000..bc5a4d4 --- /dev/null +++ b/blog/posts/hestia/hestia.webp diff --git a/blog/posts/hestia/meta.json b/blog/posts/hestia/meta.json new file mode 100644 index 0000000..8fc8bfa --- /dev/null +++ b/blog/posts/hestia/meta.json @@ -0,0 +1,10 @@ +{ + "title" : "Hestia: the homemade home assistant", + "publish_date" : "2025-01-29", + "tags" : [ + "hestia", + "voice_assistant", + "home_assistant", + "python" + ] +} diff --git a/blog/posts/let-there-be-light-theme/blog.webp b/blog/posts/let-there-be-light-theme/blog.webp Binary files differnew file mode 100644 index 0000000..625a835 --- /dev/null +++ b/blog/posts/let-there-be-light-theme/blog.webp diff --git a/blog/posts/let-there-be-light-theme/content.md b/blog/posts/let-there-be-light-theme/content.md new file mode 100644 index 0000000..988c729 --- /dev/null +++ b/blog/posts/let-there-be-light-theme/content.md @@ -0,0 +1,22 @@ +...and there was light theme. + +## print("Hello world.") + +Whenever I read techy blogs, whether one of my friends' or some random dude's who haven't updated the format of his website since the '90s, I get the urge to write one myself. Ever since I first picked up coding as a hobby (and later as a job) I was always on the lookout for opportunities to use my newfound skillset for something fun or useful. About 3 years ago I switched from Windows to Arch Linux as my main OS. I never really used Linux before, so it was quite a challenge at first, but thanks to my good friend [oliva](https://teml.in) I was able to learn more about computers in a year than ever before. Eventually this website was born, hosting my silly little projects and my first ever serious attempt to create something on the internet. + +## What's with the blog? + +I plan to use this blog as a ~~wall of shame for all my abandoned projects~~ collection/documentation/chronicle for all my running projects. Most of them will probably be software related, hopefully some of them hardware related (because I want to get into it more), but I also plan to work on some other geeky stuff (like building a lightsaber!) or learning 3D modeling and animation. + +The skybox is the limit! + +## What's next? + +If you are one of the few unfortunate people to lay your gaze upon this blog too early, you are probably looking at something like this: + + + +This is the current state of the blog as I'm writing these lines. I knew that if I _ever_ want this blog to happen, I have to start writing before setting up the blog itself, otherwise I would never be able to convince myself to work on it. I'm not a huge fan of frontend. {{sarcasm}} I know, shocking. {{}} + +So the first official project: making a somewhat more aesthetically pleasing layout and theme. Probably with dark mode. +I may keep the ugly original theme as an easter egg. Try and find it! diff --git a/blog/posts/let-there-be-light-theme/deeper.html b/blog/posts/let-there-be-light-theme/deeper.html new file mode 100644 index 0000000..a3a2bdc --- /dev/null +++ b/blog/posts/let-there-be-light-theme/deeper.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Let there be light theme</title> +</head> +<body> + <p>…and there was light theme.</p> + <h2 id="printhello-world.">print(“Hello world.”)</h2> + <p>Whenever I read techy blogs, whether one of my friends’ or some + random dude’s who haven’t updated the format of his website since the + ’90s, I get the urge to write one myself. Ever since I first picked up + coding as a hobby (and later as a job) I was always on the lookout for + opportunities to use my newfound skillset for something fun or useful. + About 3 years ago I switched from Windows to Arch Linux as my main OS. I + never really used Linux before, so it was quite a challenge at first, + but thanks to my good friend <a href="https://teml.in">oliva</a> I was + able to learn more about computers in a year than ever before. + Eventually this website was born, hosting my silly little projects and + my first ever serious attempt to create something on the internet.</p> + <h2 id="whats-with-the-blog">What’s with the blog?</h2> + <p>I plan to use this blog as a <del>wall of shame for all my abandoned + projects</del> collection/documentation/chronicle for all my running + projects. Most of them will probably be software related, hopefully some + of them hardware related (because I want to get into it more), but I + also plan to work on some other geeky stuff (like building a + lightsaber!) or learning 3D modeling and animation.</p> + <p>The skybox is the limit!</p> + <h2 id="whats-next">What’s next?</h2> + <p>If you are one of the few unfortunate people to lay your gaze upon + this blog too early, you are probably looking at something like this:</p> + <figure> + <img src="blog.webp" title="INCEPTION" + alt="very ugly blog post with no css at all" style="border: 2px solid #555;width:80%;height:80%" /> + <figcaption aria-hidden="true">INCEPTION</figcaption> + </figure> + <p>This is the current state of the blog as I’m writing these lines. I + knew that if I <em>ever</em> want this blog to happen, I have to start + writing before setting up the blog itself, otherwise I would never be + able to convince myself to work on it. I’m not a huge fan of frontend. + <sarcasm> I know, shocking. </sarcasm></p> + <p>So the first official project: making a somewhat more asteticaly + pleasing layout and theme. Probably with dark mode. I may keep the ugly + original theme as an easter egg. Try and find it!</p> +</body> +</html> diff --git a/blog/posts/let-there-be-light-theme/meta.json b/blog/posts/let-there-be-light-theme/meta.json new file mode 100644 index 0000000..4b0daaa --- /dev/null +++ b/blog/posts/let-there-be-light-theme/meta.json @@ -0,0 +1,7 @@ +{ + "title" : "Let there be light theme...", + "publish_date" : "2024-06-23", + "tags" : [ + "website" + ] +} diff --git a/blog/posts/making-this-blog/book.md b/blog/posts/making-this-blog/book.md new file mode 100644 index 0000000..4f38185 --- /dev/null +++ b/blog/posts/making-this-blog/book.md @@ -0,0 +1,13 @@ +[Enter the Library of Babel...](https://libraryofbabel.info/browse.cgi) + +In the Library of Babel, every little room (a.k.a. hex) has a name. Most of them are pretty long, because they are unique and there is a lot of them. You should start by visiting **this hex**: + +<div class="code-block-wrap"><p class="force-wrap">36j9mt1q6uz4yhglzs9gcclw6x0mhe08g9uo3sfsb2yikskdjq0hllrje5xrod8g51ohi1z9074tkb19zqq3o06x5rml5w6z5lv2w7vc8obmp1m9sczo8vwkhgnk3b7v0f15vvhlappmoveaaq8scehsafitgp2msy7b1tk853ykfyfk3f5i1vizh30r993n2asssj2lyi46ee0xh91fltajjkediytmuenmi7zbtqeqtwyqpw7jjrcehf1kazkws5oujuxabdbb4dovcz1l9zild0lzjzpk9qpye1ms7uzxxvs2w08fl1fwi3brr6izrjo9rvxll0kpee3dv9mux5gjjaqz3vxmvjmz1187nl8rf0lsnkitj7mhcpxox8djbhzs6qq6b3dkdgsleplwtcixjhckjrbcmfa7ynik9hp906lg60zh2rbd6ar8q7pjg9cso1agthxjapbb4gi3mqqxu5jvhbnwdrwop4nj6btnius2j2biy7e75cd8hwo1qdmz9fexysbbxbiwfefj1mas88z4rdu1lfcfuqr6xhi21gliehnr9qi1l37k9cmkyztge3u8ke66e1lz4ftrwgu6radi1nvf5qkpp144tlmdlcl4kj91h7q54rqsi5ewrkxhgasjfjzwyfdqqu6enw2hl5knlthd0pgttlr2095raj8877g35u4v95z26bp9kz61tang689fb9p2e1udcotb9hh5ik76g5ilroazrfr3d2tpoblwr2017zcx2tszmh629toog6ptfk2hbbw7gonfkbx4u2vtvvspktx06td77k901wyby0jlnzrmb9t47rse3xbjpmwipb1oxxo1zjrml4mu4y0fmhfvbc9nrqvn56w6tmzrx10pjcvat5lyd4nqnmx3hl2zvnityu5z76swmalkjcjr1uuowx2redeuwpfuhl76xmgiloh8j0xyxp3amhp41kduxf8h9d6htui3wmqgtrndec35ucnx0jyyntcuyriw26utz3m3lsjtub53taugyly96yf9on3ffop1vxqnpy3s5ko7yp99zdnwgcgsafto64ll5g0c1ovouhc8e44it62yb0u01o4jrg7z1ur712mcrzb3pwiydmi1d7k9aakruak3rxbp420g47s7j7gl4wnsatauiuetl9i3t6mk7ig0zcierq961rqhie21hfh50jv28gqpdr12sd50nkjhmxyj70n12vw9dc0gwhb38q0ym6euba6zl0a3jq7ngnesyg9alvit34f9eloykd8q3hjj1na223uq04gkpjlhfbq7x6muhb7mhpiqctazsewsgg1j8hjr41yeyluxdfychbpgv6jwp79kbymcm6ekoqwi8nvq1fa3rfyy373hph4cacylo4fy0sgsrtpridvxdl80l9mdqe69y88tjfx1fi0bjknlgxsz1bjilg8ojfesrigof73kzr6lszrks89zhwb0azxe2vj1654hk1dkox9zcrfubakfcgzw83kuxmjbj666lvzjabd7hoyakrk1kewdfqctdlxonq7t4qvst5n1h0kgn4dqqtepwfkfwl1elu63x0qentorg04g775caehdoqervlb258tr2r7thrq6d34600j8zp41tfmkdsif7x5g3sv8i2oqtnmb581xblxrzbx8i4bolee489yuh2yqb9aw9hdcxjvgwytgwqqfgcu1x1uf4wetp2w5dkk5hh7ve4m4a03dequypgoe7mff9i7s6ul40qq966fyva37hl5jgzwnck4lej13d2ja95eqdyx3sh6c7ks9u7rp007e44ytqp1x0r9iqlh8ekmsm2rdjj6c80j3zy5f0sr1d7nm6yc3ptazentl88jxbo045lc3rvwb4ybqyq0v9ofsdu12fr9ync29u05ovk3vrj14jmsfhiy6mnnwxnsxbez8i003e3sju4xgaaho36qjm4ijeufrf1c1y92j0qe0zzxsut5p7sv1a13c7ezfstr7g9lfd9qrdk9dkddfh9d0edmy01ei6997ap6mhqt2tlmm6tuehqokruwt4ng314z6xcqtfug9w4744dvwyzst2agssk2th5jqir3waalu3eihtibyjkoy2in184nyxd3yp8pnwxztdpfmoy615z8iero719yz3ft4sx6pv3fgxhz8i8uot1taebqicat2xc809wgr27wgonrdxfrkhzmkg22hwjca2nymfti284dyn6a90tvsy7itzwz8mmfr9zvnp0io0wkfpq7ihkh6fnuq7ieg84pjaeba3srff2gs5f2i14sg014ghmjfd0itafnm3d6ly8wg3c8mxe95x11c6gl668ydjlfusffssaee4qt0yshlypw8e0z2nb6c95102pcq3dvhl3rd6ma59eju2zo1of3ovxsdcogzvbjsau23rmwlrlzyvfdxsojk822gm3c5jdf30hux28vguz2w3oz3j8wxh03vq0gewb12tcbg5zfm3zspap7bhzb85b35e3v5oxigfepbqv0i43jh4nyvmelgv7g679f96sbya4p8aemyuf2wgvaakhazk6zrt3s1tc6m8cgi5mqzxmri21jz24r9jyhymnj3vfns51qyx59p2ipf8jf4j07w18rlbdj5vh57nm5kmfh7aigeww92k8ypdilnl1ekld2nrx9w7g1nkx0im2zq4zxhkobeyth02y0g93f0eq5wi7r28wfaruzdm24ipeo562zjm1jerpyqrwym2ygspbmed1jjec6x1jssjreckdwosvxdobfaqr80j3c0xuhwfyie2ivhwlxay3dwkismpqthy32tnu13dajh563acuvtbpivl7deo7f3s0rc17xtra6d0ewz6jcbrl95x6126yuq7geme9tr3jxvryezrgthxhh8evif5yub8rlyo9fmuglwiolz9qj7lc7dfsu28qxonjqg2gt652zdynfm9o9gzwg301vh97e0s5suz1ke2n69ulbq3dcc06eppuqj9ujm681l9auh5z20ban4oab1k20rvs6vfxr4oj759v2vkvqk80lb8kzhvm6bsjnfdwwelfjjp46c3ppg1i5qcaksf53ash92c0zzvsyzjz44j9o6makhp6asljgivsfrw3b2czeh79zuntnftv9xegi9vs4jjsnu653zdinai2x21kgf656z8k4t6v6e3izdz8fl6ec1ufyx3047fr2cnla6jq6rug</p></div> + +When you have arrived to the room, walk up to the **2nd wall**. + +Look for a book on the **3rd shelf**. + +It should be the **22nd volume** on this shelf. You can't miss it. It's called **qbhejxylqtqfuo**. + +Now turn to **page 201** and be amazed... diff --git a/blog/posts/making-this-blog/content.md b/blog/posts/making-this-blog/content.md new file mode 100644 index 0000000..dd29ee0 --- /dev/null +++ b/blog/posts/making-this-blog/content.md @@ -0,0 +1,78 @@ +This is the story of how I was finally able to create my first normal looking webpage, this blog. + +## The most crucial part of every project +If you have a fondness for your projects like me, you know that finding a good name for your stuff is the most important thing. You want to choose a clever, fitting name, because it makes it _yours_. Almost like a pet dog, cat, raptor or whatever. Sometimes... okay, almost always I use some sort of **pun or acronym**. I had projects where I've decided on the acronym way before trying to figure out a name which it could be an abbreviation for. This is the reason I was able to have multiple serious discussions with colleagues about what my "Maid" (Manageable Asset Information Database) could do, and what additional features should be considered (but this is a story for another time). + +The other approach I have for selecting a name, is finding something with **sentimental value or a grandiose/cool sounding vibe**. For example in a relatively difficult period in my life, I had a PC with the hostname of "Hyouka". It's a Japanese word that translates to "ice cream". If you want to understand the deeper meaning behind the hostname, I recommend checking out the brilliant Kyoto Animation [anime](https://myanimelist.net/anime/12189/Hyouka) with the same name. + +When trying to find a name for my blog I considered things like the [Library of Babel](https://en.wikipedia.org/wiki/The_Library_of_Babel). I love the idea that the place contains all the knowledge that had been or _will_ be known, perfect for a blog striving to be the chronicle of my learnings. In the end I dropped the idea because it was too long and there is a [website](https://libraryofbabel.info) by that name already. If you are interested, I've found a pretty interesting [book](book.html) there. + +In the end, my choice of name fell on... well I don't know, actually. I'm still looking at the placeholder text "@myblogname" as I'm writing these lines. Scroll up to the title at the top of the page, and you will know what I ended up with. + + + +## The core concept +From the very beginning I wanted to create something nerdy and relatively original. Then I remembered, that a computer science teacher (unfortunately I forgot who) back in my university days had a webpage where all the menu items and chapters looked like **shell commands**. I decided I wanted to do something similar. + +I started (with the help of a few friends) brainstorming on ideas I could use for the blog, like a fake "head" command for post summaries, or "ls" for listing the related tags for a post. For a while it was really bugging me, that I couldn't make the whole system **"realistic"**. For example "head" obviously can't display images, even though I wanted the previews to contain one. In the end I decided I will just let it go, and have the commands mean **"something similar"** to their real shell counterparts. + +Unfortunately I don't really have any graphics designer experience, so I had to look up some terminal colors on the internet. Luckily I've found a website called [terminal.sexy](http://terminal.sexy/) where I really liked the default color template, so I could use it almost without any modification. +The current color scheme is this: + +<div class="code-block"> + <p class="fg">fg: #b5aba8</p> + <p class="bg" style="background-color:var(--term-fg)">bg: #2b2b2b</p> + <p class="black">black: #515151</p> + <p class="red">red: #cc6666</p> + <p class="green">green: #b5bd68</p> + <p class="yellow">yellow: #f0c674</p> + <p class="blue">blue: #81a2be</p> + <p class="magenta">magenta: #b294bb</p> + <p class="cyan">cyan: #8abeb7</p> + <p class="white">white: #b5aba8</p> +</div> + +<span class="green">+ Update (2024-09-07): since multiple themes are supported now, the colors may differ if you are reading this with a non-default theme.</span> + +For the font I used my all-time favorite font, [JetBrains Mono](https://www.jetbrains.com/lp/mono), regular size, no ligatures. They had **.woff** format on their GitHub page, + +<span class="red">- but unfortunately only the ligatures version, which I don't like that much, so in the end I had to use **.ttf**.</span> + +<span class="green">+ Update (2024-08-05): as a kind reader, [György](https://kuruczgy.com/) has pointed it out, I can use the **.woff** font, if I specify that I want no ligatures in the css:</span> + +<div class="code-block"> +<p><span class="yellow">html</span> <span class="cyan">{</span> + <span class="green">font-family</span>: <span class="red">"jetbrains-mono"</span>, <span class="red">serif</span>; + <span class="green">font-variant-ligatures</span>: <span class="red">none</span>; +<span class="cyan">}</span></p> +</div> + +<span class="green">+ Also, as a result, I had to implement the css for this **codeblock**, and I got the idea to add updates to a post in a **git diff** +/- style, so it was a good exercise.</span> + +## Putting together the whole thing +For most of the other subdomains under **wazul.moe** I already had a few thrown together Python scripts to generate the content. Luckily my friend [Marcsello](https://blog.marcsello.com) opensourced his whole blog, so it was easy for me to _get inspired_ by it, and the templating engine he used. You could say he "led me into the Jinja". (If you are Hungarian this is your cue to laugh. Otherwise, disregard this pun.) + +So I started learning [Jinja](https://jinja.palletsprojects.com/), the **templating engine**. This was the first time I used it, but probably not the last one. I can see it being used for other than HTML as well. + +Since I'm not really a fan of **frontend**, this was really my first "professional" looking webpage. I was always afraid of creating display size responsive layouts. Fortunately [Bootstrap](https://github.com/twbs/bootstrap) ended up being far easier to use than I anticipated. Truth to be told, I used a [stripped down version](https://github.com/dmhendricks/bootstrap-grid-css) with only the grid system included, nothing else. + +I've written the actual content of the posts in **Markdown**, so I also used [Marko](https://marko-py.readthedocs.io/), which is a neat little Markdown converter with great extensibility. I ended up creating a few extensions for it, they can be found [here](https://git.wazul.moe/warko) on my git (and it's called warko, because W is an upside down M, and also W like Wazul, get it?). + +<span class="red">- When I got to implementing the **RSS feed** I was a bit tired already so I almost straight up ripped it from Marcsello's code (not like I didn't steal all the other libraries from his project). It's using [feedgen](https://feedgen.kiesow.be) to do the job.</span> + +<span class="green">+ Update (2024-08-07): I was not satisfied with the original **RSS feed** generator, as it was leaving out some of the tags, so in the end I made the whole thing in a Jinja template. I guess _that's_ a use other than HTML technically.</span> + +I'm planning to **opensource my blog** as soon as I've got it in order, it will be available on my [git](https://git.wazul.moe) soon™. + +<span class="green">+ Update (2024-09-04): source code is available now in [this repository](https://git.wazul.moe/website).</span> + +## TODO +There is still a lot of small things to do on the blog. I ended up implementing mostly those features I needed for writing this second blogpost. I also want to use my Jinja knowledge and **rebuild the rest of my webpage**. Maybe add a normal menu to the main domain instead of the current content, which is just the game over message from the Legend of Zelda: Mayora's Mask. + +I also want to do other projects, like **designing an icon for myself**. I have some ideas already, now I only need to learn Inkscape and do it. {{sarcasm}} Piece of cake! {{}} + +And of course, I have a **ton to write about**, both my past and future projects, so I think I'm going to be busy. I ended up working a bit more on this post than I first anticipated but I enjoyed it regardless. Hell, I even took my laptop to a holiday drinking party and coded some of the last features for the blog! No sarcasm this time. + +<br> + +Alright then... see you in the next one I guess!
\ No newline at end of file diff --git a/blog/posts/making-this-blog/meta.json b/blog/posts/making-this-blog/meta.json new file mode 100644 index 0000000..ea9eacf --- /dev/null +++ b/blog/posts/making-this-blog/meta.json @@ -0,0 +1,9 @@ +{ + "title" : "Making this blog", + "publish_date" : "2024-07-03", + "tags" : [ + "website", + "css", + "python" + ] +} diff --git a/blog/posts/making-this-blog/yggdrasil.webp b/blog/posts/making-this-blog/yggdrasil.webp Binary files differnew file mode 100644 index 0000000..ebd7a4d --- /dev/null +++ b/blog/posts/making-this-blog/yggdrasil.webp diff --git a/blog/posts/still-working-on-this/content.md b/blog/posts/still-working-on-this/content.md new file mode 100644 index 0000000..a1db62a --- /dev/null +++ b/blog/posts/still-working-on-this/content.md @@ -0,0 +1,131 @@ +This time I made some improvements to the website. + +## Watch out, construction site! +Ever since I've bought my domain, I've been putting all the actual content of my website to thematic subdomains. Since I had nothing to put to the main domain I just used it as a sort of dead-end for the website, with the following game over text from the [Legend of Zelda: Majora's Mask](https://en.wikipedia.org/wiki/The_Legend_of_Zelda:_Majora%27s_Mask): + +"""You've met with a terrible fate, haven't you? "" Majora's Mask, 2000 """ + +After creating more and more silly little projects on the site, I soon realized it was time for me to **create** at least **some sort of menu** where a random visitor can check all the subdomains out (especially since I myself was starting to forget just _what_ all the current projects/subdomains were). + +So a few days ago I've put together this horrible abomination of a webpage for my main domain. I'm going to include a screenshot of it, in case I ever decide to change it to something less a crime against humanity: + + + +## Starting to feel like an icon (would look good on the sidebar) + +I also added a few more links to the sidebar, like my Mastodon which I'm planning to start using more frequently again. So I had to add a few **icons for these entries** (and the Arch Linux logo btw). Luckily [iconify](https://icon-sets.iconify.design) had some really cute Apache license icons which suited my purpose perfectly. + +## Return of the light theme + +Though the first iteration of the blog had white background, it was hardly what you could call a *light theme*. You can check out how it looked in the [first blogpost](/posts/2024/let-there-be-light-theme). After I received some advice that I should actually **implement a light theme** (and I myself experienced just how hard it is to read anything on the blog while sitting outdoors on a platform of the train station with my laptop on my lap during daytime), I've felt it might actually be a good idea to do it. + +My first question was _how_ to do it. Luckily I was already working with a predefined **palette of colors** for the 8 ANSI color (plus foreground and background). These were defined in the <span class="code-block-wrap"><span class="yellow">:root</span></span> of the css file, so the only thing I had to do was change those when another theme was set. + +I know that <span class="code-block-wrap"><span class="magenta">prefers-color-scheme</span>: <span class="green">light</span></span> is a thing in css, but I was not fond of only using that for setting the preferred theme for multiple reasons: +- I may want to change the theme **manually** even if I have a system preference (like on the train station; see above); dark mode is sometimes called night mode for a _reason_ +- {{foreshadowing}} I might want **more than two** color schemes {{}}; let's get the most out of the system if I implement it anyway +- totally personal reason: I prefer dark mode, but I use Firefox with **fingerprintingProtection**, so my agent always lies light mode preference :) + +So of course my other choice was good old **javascript**. I wanted to avoid using javascript on the blog for as long as I can. Three blogposts was the limit as it turns out. + +### Setting theme with "shell scripts" +I wanted the theme changing section of the sidebar to look thematically similar to the rest of the blog. So just like the tag listing, I went with a listing of **"shell scripts"** for the themes, and colored them green (the color for files with execute permission in ls). So while they essentially **work like buttons**, they **look more like links**. That's because they are: + +<div class="code-block"> +<p><span class="cyan"><</span><span class="yellow">a</span> <span class="green">href</span><span class="cyan">=</span><span class="red">"javascript:void(0);"</span> <span class="green">class</span><span class="cyan">=</span><span class="red">"icon-text theme-selector-light"</span> <span class="green">onclick</span><span class="cyan">=</span><span class="red">"setTheme('light')"</span><span class="cyan">></span> + <span class="cyan"><</span><span class="yellow">img</span> <span class="green">src</span><span class="cyan">=</span><span class="red">"/assets/image/sun.svg"</span> <span class="green">class</span><span class="cyan">=</span><span class="red">"svg-icon"</span><span class="cyan">></span> + <span class="cyan"><</span><span class="yellow">span</span><span class="cyan">></span>sweet-celestial.sh<span class="cyan"></</span><span class="yellow">span</span><span class="cyan">></span> +<span class="cyan"></</span><span class="yellow">a</span><span class="cyan">></span></p> +</div> + +I know this goes a bit against visual clarity, but I liked the idea, so I went with it anyway. + +The current theme is stored in <span class="code-block-wrap"><span class="yellow">localStorage</span></span> and the <span class="code-block-wrap"><span class="yellow">data-theme</span></span> attribute is applied to the **root html element** when loading the page or changing the theme: + +<div class="code-block"> +<p><span class="yellow">const</span> <span class="magenta">THEME_KEY</span> = <span class="green">"data-theme"</span>;</p> +<br> +<p><span class="yellow">function</span> <span class="blue">updateTheme</span>() { + <span class="yellow">let</span> theme = <span class="magenta">localStorage</span>.<span class="blue">getItem</span>(<span class="magenta">THEME_KEY</span>); + <span class="yellow">if</span> (theme != <span class="yellow">null</span>) { + <span class="magenta">document</span>.<span class="magenta">documentElement</span>.<span class="blue">setAttribute</span>(<span class="magenta">THEME_KEY</span>, theme) + } +}</p> +<br> +<p><span class="yellow">function</span> <span class="blue">setTheme</span>(theme) { + <span class="magenta">localStorage</span>.<span class="blue">setItem</span>(<span class="magenta">THEME_KEY</span>, theme); + <span class="blue">updateTheme</span>(); +}</p> +</div> + +The root colors in the **.css** file are then looked up in the <span class="code-block-wrap">[<span class="yellow">data-theme</span>=<span class="red">"light"</span>]</span> section, if light theme was selected. + +### Coloring the icons +Some of the svg icons on the blog use specific **"hardcoded" colors**. For example the Arch Linux logo has the official <span class="code-block-wrap"><span style="color: #1793d1">#1793d1</span></span> blue color. But other icons, like the ones for the Website and the E-mail are using the same color scheme as the rest of the blog. So when changing theme, **I need them to change color** as well. I was able to achieve this with tagging them with the <span class="code-block-wrap"><span class="yellow">filter-yellow</span></span> class, and then **styling it** for each theme separately: +<div class="code-block"> +<p>.<span class="yellow">filter-yellow</span> { + <span class="green">filter</span>: <span class="magenta">brightness</span>(<span class="blue">0</span>) <span class="magenta">saturate</span>(<span class="blue">100%</span>) <span class="magenta">invert</span>(<span class="blue">91%</span>) <span class="magenta">sepia</span>(<span class="blue">86%</span>) <span class="magenta">saturate</span>(<span class="blue">596%</span>) <span class="magenta">hue-rotate</span>(<span class="blue">314deg</span>) <span class="magenta">brightness</span>(<span class="blue">96%</span>) <span class="magenta">contrast</span>(<span class="blue">97%</span>); +}</p> +</div> + +For the conversion from **hex color to css filter**, I used the tool on [Isotropic's website](https://isotropic.co/tool/hex-color-to-css-filter). I only have yellow colored icons now, obviously I will need to generate the rest of the palette if I want to use them. + +### Flash bang out! +After this... everything was ready. Or so I thought. I was getting the good old **white flickering effect** on almost every page load. In the end I realized I was only applying the theme on <span class="code-block-wrap"><span class="magenta">window</span>.<span class="magenta">onload</span></span>, instead of **just calling it immediately** at the end of the script file. I changed it and this solved the bulk of the problem. Also, the **font was loading a bit slow**, but separating it into a **different .css file** and loading it first seemed to help with that as well. + +### Theme summary +Light theme is opt-in currently. I may use <span class="code-block-wrap"><span class="magenta">prefers-color-scheme</span>: <span class="green">light</span></span> later as a fallback, if no preference was set by the user, but **luna-eclipsed** (dark mode) is the default color scheme for now. If however you are one of _those guys_ who like their retinas burned to crisp, feel free to use **sweet-celestial** (light mode). Both of them can be found on the side panel under <span class="magenta">I want different colors</span>. + +While I was making the light theme, I just had to reuse the system and make a hidden easter egg theme as well. It's not really usable for reading, but it's fun. Try finding it! +- Hint 1: ||spoiler1||Try looking around where the rest of the theme selectors are.|| +- Hint 2: ||spoiler2||You have to click on a specific spot.|| +- Hint 3: ||spoiler3||It's to the right of "ls ~/themes/"|| + +## Blogpostception +I also had to implement a few things for _writing_ this post. For example, I **styled some new elements**, like lists or the quote at the top of the post. I made marko extensions for the quote, the fake html tags ({{whisper}}psst... hey... like this one!{{}}), and for the spoiler tags||, spoiler4||, which almost made me lose my mind. The css just didn't want to work||. + +The **spoiler text** was tricky, because I wanted them to be clickable (rather than using some hover event) without the usage of javascript. In the end I used a **hidden checkbox with two labels**, of which only one is displayed at a time. This way for the hidden text I could display a series of rectangles <span class="nobr">(▉ [<- this is not a spoiler])</span>, so you can't accidentally spoil yourself with selection. Try selecting the following text, without clicking on it: ||spoiler5||Now you see me!|| +However I had to **keep the whitespaces** so that the lines still wrap the same way as if they had normal content. + +Here's the **html** code for the spoiler above: + +<div class="code-block"> +<p><span class="cyan"><</span><span class="yellow">span</span><span class="cyan">></span> + <span class="cyan"><</span><span class="yellow">input</span> <span class="yellow">type</span><span class="cyan">=</span><span class="red">"checkbox"</span> <span class="yellow">class</span><span class="cyan">=</span><span class="red">"spoiler"</span> <span class="yellow">id</span><span class="cyan">=</span><span class="red">"spoiler5"</span><span class="cyan">></span> + <span class="cyan"><</span><span class="yellow">label</span> <span class="yellow">class</span><span class="cyan">=</span><span class="red">"spoiler-on"</span> <span class="yellow">for</span><span class="cyan">=</span><span class="red">"spoiler5"</span><span class="cyan">></span> + <span class="cyan"><</span><span class="yellow">span</span><span class="cyan">></span>▉▉▉ ▉▉▉ ▉▉▉ ▉▉▉<span class="cyan"></</span><span class="yellow">span</span><span class="cyan">></span> + <span class="cyan"></</span><span class="yellow">label</span><span class="cyan">></span> + <span class="cyan"><</span><span class="yellow">label</span> <span class="yellow">class</span><span class="cyan">=</span><span class="red">"spoiler-off"</span> <span class="yellow">for</span><span class="cyan">=</span><span class="red">"spoiler5"</span><span class="cyan">></span> + <span class="cyan"><</span><span class="yellow">span</span><span class="cyan">></span>Now you see me!<span class="cyan"></</span><span class="yellow">span</span><span class="cyan">></span> + <span class="cyan"></</span><span class="yellow">label</span><span class="cyan">></span> +<span class="cyan"></</span><span class="yellow">span</span><span class="cyan">></span></p> +</div> + +And the **css**: + +<div class="code-block"> +<p>.<span class="yellow">spoiler</span> { + <span class="green">position</span>: <span class="red">absolute</span>; + <span class="green">left</span>: <span class="blue">-10000px</span>; +}</p> +<br> +<p>.<span class="yellow">spoiler</span>:<span class="magenta">checked</span> ~ <span class="yellow">label</span>.<span class="yellow">spoiler-on</span>, +.<span class="yellow">spoiler</span>:<span class="magenta">not</span>(:<span class="magenta">checked</span>) ~ <span class="yellow">label</span>.<span class="yellow">spoiler-off</span> { + <span class="green">display</span>: <span class="red">none</span>; +}</p> +<br> +<p><span class="yellow">label</span>.<span class="yellow">spoiler-on</span> { + <span class="green">background-color</span>: <span class="magenta">var</span>(<span class="blue">--term-fg</span>); +}</p> +<br> +<p><span class="yellow">label</span>.<span class="yellow">spoiler-off</span> { + <span class="green">background-color</span>: <span class="magenta">var</span>(<span class="blue">--term-black</span>); +}</p> +</div> + +I had to use an ugly workaround for the checkbox (<span class="code-block-wrap">.<span class="yellow">spoiler</span></span>). When I set it to <span class="code-block-wrap"><span class="green">display</span>: <span class="red">none</span></span> it was sometimes **scrolling around** on the page, trying to find the position of the checkbox. By keeping it "visible" (just -10000 pixels to the left of the screen), the browser **thinks it's on the screen**, so it does not start to jump around. + +## Afterwords +I still have some things to do on the blog, and especially on the other subdomains, but this blogpost is getting too long already. And I'm tired. + +So see you in the next one, I guess!
\ No newline at end of file diff --git a/blog/posts/still-working-on-this/main_domain.webp b/blog/posts/still-working-on-this/main_domain.webp Binary files differnew file mode 100644 index 0000000..5b689ff --- /dev/null +++ b/blog/posts/still-working-on-this/main_domain.webp diff --git a/blog/posts/still-working-on-this/meta.json b/blog/posts/still-working-on-this/meta.json new file mode 100644 index 0000000..6bdd67e --- /dev/null +++ b/blog/posts/still-working-on-this/meta.json @@ -0,0 +1,9 @@ +{ + "title" : "Still working on this website", + "publish_date" : "2024-09-22", + "tags" : [ + "website", + "css", + "javascript" + ] +} |
